Merge branch 'master' into develop

This commit is contained in:
Bill Somerville 2021-03-14 16:40:56 +00:00
commit f0945282dd
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
31 changed files with 1094 additions and 1099 deletions

View File

@ -526,7 +526,6 @@ set (wsjt_FSRCS
lib/symspec2.f90 lib/symspec2.f90
lib/symspec65.f90 lib/symspec65.f90
lib/sync4.f90 lib/sync4.f90
lib/sync64.f90
lib/sync65.f90 lib/sync65.f90
lib/ft4/getcandidates4.f90 lib/ft4/getcandidates4.f90
lib/ft4/get_ft4_bitmetrics.f90 lib/ft4/get_ft4_bitmetrics.f90
@ -1603,7 +1602,7 @@ install (DIRECTORY
if (APPLE) if (APPLE)
install (FILES install (FILES
Darwin/ReadMe.txt Darwin/ReadMe.txt
Darwin/sysctl.conf Darwin/com.wsjtx.sysctl.plist
DESTINATION . DESTINATION .
#COMPONENT runtime #COMPONENT runtime
) )

View File

@ -1,42 +1,21 @@
Notes on WSJT-X Installation for Mac OS X Notes on WSJT-X Installation for Mac OS X
----------------------------------------- -----------------------------------------
Important: If you are using the new Mac with the M1 chip then please read
the section marked: BEGIN M1. Otherwise BEGIN INTEL applies.
If you have already downloaded a previous version of WSJT-X then I suggest If you have already downloaded a previous version of WSJT-X then I suggest
you change the name in the Applications folder from WSJT-X to WSJT-X_previous you change the name in the Applications folder from WSJT-X to WSJT-X_previous
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 of WSJT-X or you have upgraded macOS. are moving from v2.2 to v2.3 or later, of WSJT-X or you have upgraded macOS.
BEGIN M1:
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.
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal. Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
There are two system variables that must be set manually since the M1 Macs do not recognise Along with this ReadMe file there is a file: com.wsjtx.sysctl.plist which must be copied to a
automatic parameter settings by means of the sysctl.conf file present in the download.
Type these commands - you will be asked for your password which will not be echoed:
sudo sysctl -w kern.sysv.shmmax=52428800
sudo sysctl -w kern.sysv.shmall=25600
It is important to note that these parameter settings will not survive a reboot. If you
need to reboot your Mac, then these commands must be re-entered. Now proceed to NEXT.
BEGIN INTEL:
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
Along with this ReadMe file there is a file: sysctl.conf which must be copied to a
system area by typing this line in the Terminal window and then pressing the Return key. system area by typing this line in the Terminal window and then pressing the Return key.
sudo cp /Volumes/WSJT-X/sysctl.conf /etc sudo cp /Volumes/WSJT-X/com.wsjtx.sysctl.plist /Library/LaunchDaemons
you will be asked for your normal password because authorisation is needed to copy this file. you will be asked for your normal password because authorisation is needed to copy this file.
(Your password will not be echoed but press the Return key when completed.) (Your password will not be echoed but press the Return key when completed.)
@ -53,8 +32,6 @@ You can now close the Terminal window. It will not be necessary to repeat this
again, even when you download an updated version of WSJT-X. It might be necessary if you again, even when you download an updated version of WSJT-X. It might be necessary if you
upgrade macOS. upgrade macOS.
NEXT:
Drag the WSJT-X app to your preferred location, such as Applications. Drag the WSJT-X app to your preferred location, such as Applications.
You need to configure your sound card. Visit Applications > Utilities > Audio MIDI You need to configure your sound card. Visit Applications > Utilities > Audio MIDI
@ -95,27 +72,22 @@ Please email me if you have problems.
--- John G4KLA (g4kla@rmnjmn.co.uk) --- John G4KLA (g4kla@rmnjmn.co.uk)
Addendum: Information about sysctl.conf and multiple instances of WSJT-X. Addendum: 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
has to be increased. The sysctl.conf file is used for this purpose. You can has to be increased. The com.wsjtx.sysctl.plist file is used for this purpose. You can
use a Mac editor to examine sysctl.conf. (Do not use another editor - the file use a Mac editor to examine the file. (Do not use another editor - the file
would probably be corrupted.) would probably be corrupted.)
It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2 It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2
Frequently asked Questions" in the User Guide. If you wish to run more than two instances Frequently asked Questions" in the User Guide. If you wish to run more than two instances
simultaneously, the shmall parameter in the sysctl.conf file needs to be modified as follows. simultaneously, the shmall parameter in the com.wsjtx.sysctl.plist file needs to be modified as follows.
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. If (n * 52428800)/4096 where 'n' is the number of instances required to run simultaneously.
you are using an Intel Mac, modify the shmall parameter in the sysctl.conf file using a Mac editor Remember to reboot your Mac afterwards.
and then install in the /etc directory using the installation procedure described above for an
Intel Mac. Remember to reboot your Mac afterwards.
If you are using an M1 Mac, then simply issue the sudo sysctl -w kern.sysv.shmall=xxx command where
xxx is the new value of shmall that is required.
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

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.wsjtx.sysctl</string>
<key>Program</key>
<string>/usr/sbin/sysctl</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/sysctl</string>
<string>kern.sysv.shmmax=52428800</string>
<string>kern.sysv.shmall=25600</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

View File

@ -1,5 +0,0 @@
kern.sysv.shmmax=52428800
kern.sysv.shmmin=1
kern.sysv.shmmni=128
kern.sysv.shmseg=32
kern.sysv.shmall=25600

View File

@ -23,7 +23,7 @@ DecodedText::DecodedText (QString const& the_string)
, is_standard_ {false} , is_standard_ {false}
{ {
// discard appended AP info // discard appended AP info
clean_string_.replace (QRegularExpression {R"(^(.*)(?:(?:\?\s)?a[0-9].*)$)"}, "\\1"); clean_string_.replace (QRegularExpression {R"(^(.*?)(?:\?\s)?a[0-9].*$)"}, "\\1");
// qDebug () << "DecodedText: the_string:" << the_string << "Nbsp pos:" << the_string.indexOf (QChar::Nbsp); // qDebug () << "DecodedText: the_string:" << the_string << "Nbsp pos:" << the_string.indexOf (QChar::Nbsp);
if (message_.length() >= 1) if (message_.length() >= 1)

View File

@ -142,8 +142,8 @@ namespace Logger
err += e.what (); err += e.what ();
// Since we cannot be sure of boost log state, output to cerr and cout. // Since we cannot be sure of boost log state, output to cerr and cout.
std::cerr << "ERROR: " << err << std::endl; std::cerr << "ERROR: " << err << std::endl;
std::cout << "ERROR: " << err << std::endl;
LOG_ERROR (err); LOG_ERROR (err);
throw;
} }
} }

41
NEWS
View File

@ -12,6 +12,41 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT. Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.4.0-rc3
Mar 16, 2021
-------------------------
WSJT-X 2.4.0 Release Candidate 3 adds new Q65 mode functionality and
decoder optimizations; repairs defects and regressions discovered in
the RC2 and v2.3.0 GA releases.
- Repaired a memory corruption related to display of Q65_Sync,
particularly nasty on macOS.
- Q65 now dissplays two sync curves: orange for the current sequence,
red for the accumulated average.
- Behavior of "Save decoded" has been corrected.
- Repaied a defect that caused crash when displaying the Wide Graph
with lower frequency limit set to 0.
- Program no longer terminates a transmission when Settings is
closed.
- Program no longer forces TxFreq to 700 or 1000 Hz when entering Q65
mode or closing Settings. Instead, it highlights TxFreq with red
background when its value should be 700 Hz but is not.
- Program displays a warning label if a contest mode is active in Q65
mode.
- Many updates to User Guide, mostly related to Q65.
- Repaired a regression that disallowed a new QSO initiation after an
abandoned QSO.
Release: WSJT-X 2.4.0-rc2 Release: WSJT-X 2.4.0-rc2
Mar 6, 2021 Mar 6, 2021
------------------------- -------------------------
@ -63,7 +98,7 @@ the RC1 release.
Release: WSJT-X 2.3.1 Release: WSJT-X 2.3.1
Mar 8, 2021 Mar 18, 2021
--------------------- ---------------------
WSJT-X 2.3.1 General Availability release updates the User Guide to WSJT-X 2.3.1 General Availability release updates the User Guide to
@ -96,6 +131,10 @@ below.
- Repair a defect that could caused incorrect log entry fields when - Repair a defect that could caused incorrect log entry fields when
using FT4 mode and a priori (AP) decoding. using FT4 mode and a priori (AP) decoding.
- Repair defects saving .WAV files for periods with decodes.
- Offer a new scheme for adjusting macOS shared memory parameters.
Release: WSJT-X 2.4.0-rc1 Release: WSJT-X 2.4.0-rc1
Feb 3, 2021 Feb 3, 2021

View File

@ -12,6 +12,41 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT. Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.4.0-rc3
Mar 16, 2021
-------------------------
WSJT-X 2.4.0 Release Candidate 3 adds new Q65 mode functionality and
decoder optimizations; repairs defects and regressions discovered in
the RC2 and v2.3.0 GA releases.
- Repaired a memory corruption related to display of Q65_Sync,
particularly nasty on macOS.
- Q65 now dissplays two sync curves: orange for the current sequence,
red for the accumulated average.
- Behavior of "Save decoded" has been corrected.
- Repaied a defect that caused crash when displaying the Wide Graph
with lower frequency limit set to 0.
- Program no longer terminates a transmission when Settings is
closed.
- Program no longer forces TxFreq to 700 or 1000 Hz when entering Q65
mode or closing Settings. Instead, it highlights TxFreq with red
background when its value should be 700 Hz but is not.
- Program displays a warning label if a contest mode is active in Q65
mode.
- Many updates to User Guide, mostly related to Q65.
- Repaired a regression that disallowed a new QSO initiation after an
abandoned QSO.
Release: WSJT-X 2.4.0-rc2 Release: WSJT-X 2.4.0-rc2
Mar 6, 2021 Mar 6, 2021
------------------------- -------------------------
@ -63,7 +98,7 @@ the RC1 release.
Release: WSJT-X 2.3.1 Release: WSJT-X 2.3.1
Mar 8, 2021 Mar 18, 2021
--------------------- ---------------------
WSJT-X 2.3.1 General Availability release updates the User Guide to WSJT-X 2.3.1 General Availability release updates the User Guide to
@ -96,6 +131,10 @@ below.
- Repair a defect that could caused incorrect log entry fields when - Repair a defect that could caused incorrect log entry fields when
using FT4 mode and a priori (AP) decoding. using FT4 mode and a priori (AP) decoding.
- Repair defects saving .WAV files for periods with decodes.
- Offer a new scheme for adjusting macOS shared memory parameters.
Release: WSJT-X 2.4.0-rc1 Release: WSJT-X 2.4.0-rc1
Feb 3, 2021 Feb 3, 2021

View File

@ -104,59 +104,11 @@ namespace
<< context.category << ": " << msg.toStdWString (); << context.category << ": " << msg.toStdWString ();
} }
} }
}
WSJTXLogging::WSJTXLogging () void default_log_config ()
{ {
auto core = logging::core::get (); auto core = logging::core::get ();
// Catch relevant exceptions from logging.
core->set_exception_handler
(
logging::make_exception_handler<std::runtime_error, std::logic_error> (exception_handler {})
);
// Check for a user-defined logging configuration settings file.
QFile log_config {QStandardPaths::locate (QStandardPaths::ConfigLocation, "wsjtx_log_config.ini")};
if (log_config.exists () && log_config.open (QFile::ReadOnly) && log_config.isReadable ())
{
QTextStream ts {&log_config};
auto config = ts.readAll ();
// Substitution variables.
container::flat_map<QString, QString> replacements =
{
{"DesktopLocation", QStandardPaths::writableLocation (QStandardPaths::DesktopLocation)},
{"DocumentsLocation", QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation)},
{"TempLocation", QStandardPaths::writableLocation (QStandardPaths::TempLocation)},
{"HomeLocation", QStandardPaths::writableLocation (QStandardPaths::HomeLocation)},
{"CacheLocation", QStandardPaths::writableLocation (QStandardPaths::CacheLocation)},
{"GenericCacheLocation", QStandardPaths::writableLocation (QStandardPaths::GenericCacheLocation)},
{"GenericDataLocation", QStandardPaths::writableLocation (QStandardPaths::GenericDataLocation)},
{"AppDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppDataLocation)},
{"AppLocalDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)},
};
// Parse the configration settings substituting the variable if found.
QString new_config;
int pos {0};
QRegularExpression subst_vars {R"(\${([^}]+)})"};
auto iter = subst_vars.globalMatch (config);
while (iter.hasNext ())
{
auto match = iter.next ();
auto const& name = match.captured (1);
auto repl_iter = replacements.find (name);
auto repl = repl_iter != replacements.end () ? repl_iter->second : "${" + name + "}";
new_config += config.mid (pos, match.capturedStart (1) - 2 - pos) + repl;
pos = match.capturedEnd (0);
}
new_config += config.mid (pos);
std::wstringbuf buffer {new_config.toStdWString (), std::ios_base::in};
std::wistream stream {&buffer};
Logger::init_from_config (stream);
LOG_INFO ("Read logging configuration file: " << log_config.fileName ());
}
else // Default setup
{
// //
// Define sinks, filters, and formatters using expression // Define sinks, filters, and formatters using expression
// templates for efficiency. // templates for efficiency.
@ -219,10 +171,75 @@ WSJTXLogging::WSJTXLogging ()
); );
core->add_sink (sys_sink); core->add_sink (sys_sink);
}
// Indicate start of logging // Indicate start of logging
LOG_INFO ("Log Start"); LOG_INFO ("Log Start");
}
}
WSJTXLogging::WSJTXLogging ()
{
auto core = logging::core::get ();
// Catch relevant exceptions from logging.
core->set_exception_handler
(
logging::make_exception_handler<std::runtime_error, std::logic_error> (exception_handler {})
);
// Check for a user-defined logging configuration settings file.
QFile log_config {QStandardPaths::locate (QStandardPaths::ConfigLocation, "wsjtx_log_config.ini")};
if (log_config.exists () && log_config.open (QFile::ReadOnly) && log_config.isReadable ())
{
QTextStream ts {&log_config};
auto config = ts.readAll ();
// Substitution variables.
container::flat_map<QString, QString> replacements =
{
{"DesktopLocation", QStandardPaths::writableLocation (QStandardPaths::DesktopLocation)},
{"DocumentsLocation", QStandardPaths::writableLocation (QStandardPaths::DocumentsLocation)},
{"TempLocation", QStandardPaths::writableLocation (QStandardPaths::TempLocation)},
{"HomeLocation", QStandardPaths::writableLocation (QStandardPaths::HomeLocation)},
{"CacheLocation", QStandardPaths::writableLocation (QStandardPaths::CacheLocation)},
{"GenericCacheLocation", QStandardPaths::writableLocation (QStandardPaths::GenericCacheLocation)},
{"GenericDataLocation", QStandardPaths::writableLocation (QStandardPaths::GenericDataLocation)},
{"AppDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppDataLocation)},
{"AppLocalDataLocation", QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)},
};
// Parse the configration settings substituting the variable if found.
QString new_config;
int pos {0};
QRegularExpression subst_vars {R"(\${([^}]+)})"};
auto iter = subst_vars.globalMatch (config);
while (iter.hasNext ())
{
auto match = iter.next ();
auto const& name = match.captured (1);
auto repl_iter = replacements.find (name);
auto repl = repl_iter != replacements.end () ? repl_iter->second : "${" + name + "}";
new_config += config.mid (pos, match.capturedStart (1) - 2 - pos) + repl;
pos = match.capturedEnd (0);
}
new_config += config.mid (pos);
std::wstringbuf buffer {new_config.toStdWString (), std::ios_base::in};
std::wistream stream {&buffer};
try
{
Logger::init_from_config (stream);
LOG_INFO ("Read logging configuration file: " << log_config.fileName ());
}
catch (std::exception const& e)
{
default_log_config ();
LOG_ERROR ("Reading logging configuration file: " << log_config.fileName () << " - " << e.what ());
LOG_INFO ("Reverting to default logging configuration");
}
}
else // Default setup
{
default_log_config ();
}
::qInstallMessageHandler (&qt_log_handler); ::qInstallMessageHandler (&qt_log_handler);
} }

1307
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -95,7 +95,7 @@ set (UG_IMGS
images/JT65B.png images/JT65B.png
images/keyboard-shortcuts.png images/keyboard-shortcuts.png
images/MSK144.png images/MSK144.png
images/QRA64.png images/Q65_6m_ionoscatter.png
images/WSPR_WideGraphControls.png images/WSPR_WideGraphControls.png
images/WSPR_1a.png images/WSPR_1a.png
images/WSPR_2.png images/WSPR_2.png
@ -224,7 +224,7 @@ foreach (lang ${LANGUAGES})
SOURCE user_guide/wsjtx-main.adoc SOURCE user_guide/wsjtx-main.adoc
LANG "${lang}" LANG "${lang}"
OUTPUT html OUTPUT html
ASCIIDOCTOR_OPTIONS -d book -a data-uri -a toc=left -a max-width=1024px ASCIIDOCTOR_OPTIONS -d book -a data-uri -a toc=left
DEPENDS ${common_SRCS} ${_sources} DEPENDS ${common_SRCS} ${_sources}
) )
document( document(

View File

@ -2,18 +2,20 @@
The _WSJT_ project was started by *K1JT* in 2001. Since 2005 it has The _WSJT_ project was started by *K1JT* in 2001. Since 2005 it has
been an Open Source project, which now includes the programs _WSJT_, been an Open Source project, which now includes the programs _WSJT_,
_MAP65_, _WSPR_, _WSJT-X_, and _WSPR-X_. *G4WJS* (since 2013) and _MAP65_, _WSPR_, _WSJT-X_, and _WSPR-X_. *G4WJS* (since 2013), *K9AN*
*K9AN* (since 2015) have made major contributions to _WSJT-X_. (since 2015), and *IV3NWV* (since 2016) have made major contributions
Together with K1JT they now form the core development team. to _WSJT-X_. Together with K1JT they now form the core development
team. *G4WJS* and *W9MDB* have made major contributiions to _hamlib_,
on which _WSJT-X_ depends for rig control.
All code in the _WSJT_ project is licensed under the GNU Public All code in the _WSJT_ project is licensed under the GNU Public
License (GPL). Many users of these programs, too numerous to mention License (GPL). Many users of these programs, too numerous to mention
here individually, have contributed suggestions and advice that have here individually, have contributed suggestions and advice that have
greatly aided the development of _WSJT_ and its sister programs. For greatly aided the development of _WSJT_ and its sister programs. For
_WSJT-X_ in particular, we acknowledge contributions from *AC6SL, _WSJT-X_ in particular, we acknowledge contributions from *AC6SL,
AE4JY, DJ0OT, G3WDG, G4KLA, IV3NWV, IW3RAB, K3WYC, KA6MAL, KA9Q, AE4JY, DF2ET, DJ0OT, G3WDG, G4KLA, IW3RAB, K3WYC, KA1GT, KA6MAL, KA9Q,
KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR, VE1SKY, VK3ACF, VK4BDJ, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR, VE1SKY, VK3ACF, VK4BDJ,
VK7MO, W4TI, W4TV, and W9MDB*. Each of these amateurs has helped to VK7MO, W3DJS, W4TI, W4TV, and W9MDB*. Each of these amateurs has helped to
bring the programs design, code, testing, and/or documentation to its bring the programs design, code, testing, and/or documentation to its
present state. present state.

View File

@ -20,6 +20,7 @@ sky background temperature in the direction of the moon, scaled to the
operating frequency; *Dpol*, the spatial polarization offset in operating frequency; *Dpol*, the spatial polarization offset in
degrees; *MNR*, the maximum non-reciprocity of the EME path in dB, degrees; *MNR*, the maximum non-reciprocity of the EME path in dB,
owing to a combination of Faraday rotation and spatial polarization; owing to a combination of Faraday rotation and spatial polarization;
*Dist*, the distance from your location to the moon, in km;
and finally *Dgrd*, an estimate of the signal degradation in dB, and finally *Dgrd*, an estimate of the signal degradation in dB,
relative to the best possible time with the moon at perigee in a cold relative to the best possible time with the moon at perigee in a cold
part of the sky. part of the sky.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

View File

@ -5,39 +5,38 @@ radio communication using very weak signals. The first four letters in
the program name stand for "`**W**eak **S**ignal communication by the program name stand for "`**W**eak **S**ignal communication by
K1**JT**,`" while the suffix "`*-X*`" indicates that _WSJT-X_ started K1**JT**,`" while the suffix "`*-X*`" indicates that _WSJT-X_ started
as an extended branch of an earlier program, _WSJT_, first released in as an extended branch of an earlier program, _WSJT_, first released in
2001. Bill Somerville, G4WJS, and Steve Franke, K9AN, have been major 2001. Bill Somerville, G4WJS, Steve Franke, K9AN, and Nico Palermo,
contributors to development of _WSJT-X_ since 2013 and 2015, respectively. IV3NWV, have been major contributors to development of _WSJT-X_ since
2013, 2015, and 2016, respectively.
_WSJT-X_ Version {VERSION_MAJOR}.{VERSION_MINOR} offers eleven _WSJT-X_ Version {VERSION_MAJOR}.{VERSION_MINOR} offers eleven
different protocols or modes: *FST4*, *FT4*, *FT8*, *JT4*, *JT9*, different protocols or modes: *FST4*, *FT4*, *FT8*, *JT4*, *JT9*,
*JT65*, *Q65*, *MSK144*, *WSPR*, *FST4W*, and *Echo*. The *JT65*, *Q65*, *MSK144*, *WSPR*, *FST4W*, and *Echo*. The first seven
first seven are designed for making reliable QSOs under weak-signal are designed for making reliable QSOs under weak-signal
conditions. They use nearly identical message structure and source conditions. They use nearly identical message structure and source
encoding. JT65 was designed for EME ("`moonbounce`") on VHF and encoding. JT65 was designed for EME ("`moonbounce`") on VHF and
higher bands and is mostly used for that purpose today. Q65 replaces higher bands and is mostly used for that purpose today. Q65 is
an earlier mode, QRA64. Q65 is particularly effective for tropospheric particularly effective for tropospheric scatter, rain scatter,
scatter, rain scatter, ionospheric scatter, TEP, and EME on VHF and ionospheric scatter, TEP, and EME on VHF and higher bands, as well as
higher bands, as well as other types of fast-fading signals. JT9 was other types of fast-fading signals. JT9 was designed for the HF and
originally designed for the HF and lower bands. Its submode JT9A is 1 lower bands. Its submode JT9A is 1 dB more sensitive than JT65 while
dB more sensitive than JT65 while using less than 10% of the using less than 10% of the bandwidth. JT4 offers a wide variety of
bandwidth. JT4 offers a wide variety of tone spacings and has proven tone spacings and has proven highly effective for EME on microwave
highly effective for EME on microwave bands up to 24 GHz. These four bands up to 24 GHz. The "`slow`" modes use timed sequences of
"`slow`" modes use one-minute timed sequences of alternating alternating transmission and reception. JT4, JT9, and JT65 use
transmission and reception, so a minimal QSO takes four to six minutes one-minute sequences, so a minimal QSO takes four to six minutes — two
— two or three transmissions by each station, one sending in odd UTC or three transmissions by each station, one sending in odd UTC minutes
minutes and the other even. FT8 is operationally similar but four and the other even. FT8 is four times faster (15-second T/R
times faster (15-second T/R sequences) and less sensitive by a few dB. sequences) and less sensitive by a few dB. FT4 is faster still (7.5 s
FT4 is faster still (7.5 s T/R sequences) and especially well-suited T/R sequences) and especially well-suited for radio contesting. FST4
for radio contesting. FST4 was added to _WSJT-X_ in version 2.3.0. is designed especially for the LF and MF bands. Both FST4 and Q65
It is intended especially for use on the LF and MF bands, and already offer a wide variety of timed sequence lengths, and Q65 a range of
during its first few months of testing intercontinental paths have tone spacings for different propagation conditions. On the HF bands,
been spanned many times on the 2200 and 630 m bands. Further details world-wide QSOs are possible with any of these modes using power
can be found in the following section, <<NEW_FEATURES,New Features in levels of a few watts (or even milliwatts) and compromise antennas.
Version 2.4.0>>. On the HF bands, world-wide QSOs are possible with On VHF bands and higher, QSOs are possible (by EME, scatter, and other
any of these modes using power levels of a few watts (or even propagation types) at signal levels 10 to 15 dB below those required
milliwatts) and compromise antennas. On VHF bands and higher, QSOs for CW.
are possible (by EME, scatter, and other propagation types) at signal
levels 10 to 15 dB below those required for CW.
*MSK144*, and optionally submodes *JT9E-H* are "`fast`" *MSK144*, and optionally submodes *JT9E-H* are "`fast`"
protocols designed to take advantage of brief signal enhancements from protocols designed to take advantage of brief signal enhancements from

View File

@ -75,8 +75,8 @@ responder to your CQ.
NOTE: When *Auto-Seq* is enabled, the program de-activates *Enable Tx* NOTE: When *Auto-Seq* is enabled, the program de-activates *Enable Tx*
at the end of each QSO. It is not intended that _WSJT-X_ should make at the end of each QSO. It is not intended that _WSJT-X_ should make
fully automated QSOs. *Auto-sequencing is an operator aid, not an fully automated QSOs. Auto-sequencing is an operator aid, not an
operator replacement.* operator replacement.
[[CONTEST_MSGS]] [[CONTEST_MSGS]]
=== Contest Messages === Contest Messages
@ -159,9 +159,9 @@ guidelines for contest logging with FT4, FT8, and MSK144:
[[COMP-CALL]] [[COMP-CALL]]
=== Nonstandard Callsigns === Nonstandard Callsigns
*FST4, FT4, FT8, MSK144, and Q65* *Modes with 77-bit message payloads: FST4, FT4, FT8, MSK144, and Q65*
Compound callsigns like xx/K1ABC or K1ABC/x and special event Compound callsigns like PJ4/K1ABC or K1ABC/3 and special event
callsigns like YW18FIFA are supported for normal QSOs but not for callsigns like YW18FIFA are supported for normal QSOs but not for
contest-style messages. Model QSOs look something like this: contest-style messages. Model QSOs look something like this:
@ -195,7 +195,7 @@ the types of information that can be included in a message. It
prevents including your locator in standard messages, which prevents including your locator in standard messages, which
necessarily impairs the usefulness of tools like PSK Reporter. necessarily impairs the usefulness of tools like PSK Reporter.
*JT4, JT9, and JT65* *Modes with 72-bit message payloads: JT4, JT9, and JT65*
In the 72-bit modes, compound callsigns are handled in one of two In the 72-bit modes, compound callsigns are handled in one of two
possible ways: possible ways:

View File

@ -175,19 +175,20 @@ separation is 110250/4096 = 26.92 Hz multiplied by n for JT65A, with n
Q65 is intended for scatter, EME, and other extreme weak-signal Q65 is intended for scatter, EME, and other extreme weak-signal
applications. Forward error correction (FEC) uses a specially applications. Forward error correction (FEC) uses a specially
designed (65,15) block code with six-bit symbols. Two symbols are designed (65,15) block code with six-bit symbols. Two symbols are
“punctured” from the code, yielding an effective (63,13) code with a “punctured” from the code and not transmitted, thereby yielding an
payload of k = 13 information symbols conveyed by n = 63 channel effective (63,13) code with a payload of k = 13 information symbols
symbols. The punctured symbols consist of a 12-bit CRC computed from conveyed by n = 63 channel symbols. The punctured symbols consist of
the 13 information symbols. The CRC is used to reduce the a 12-bit CRC computed from the 13 information symbols. The CRC is
false-decode rate to a very low value. A 22-symbol pseudo-random used to reduce the false-decode rate to a very low value. A 22-symbol
sequence spread throughout a transmission is sent as “tone 0” and used pseudorandom sequence spread throughout a transmission is sent as
for synchronization. The total number of channel symbols in a Q65 “tone 0” and used for synchronization. The total number of channel
transmission is thus 63 + 22 = 85. symbols in a Q65 transmission is thus 63 + 22 = 85. Q65 offers T/R
sequence lengths of 15, 30, 60, 120, and 300 s, and submodes A - E
For each T/R sequence length, submodes A - E have tone spacings and have tone spacings 1, 2, 4, 8, and 16 times the symbol rate. Submode
occupied bandwidths 1, 2, 4, 8, and 16 times those specified in the designations include a number for sequence length and a letter for
above table. Full submode designations include a number for sequence tone spacing, as in Q65-15A, Q65-120C, etc. Occupied bandwidths are
length and a letter for tone spacing, as in Q65-15A, Q65-120C, etc. 65 times the tone spacing, ranging from 19 Hz (Q65-300A) to a maximum
of 1733 Hz (Q65-15C, Q65-30D, and Q65-60E).
[[WSPR_PROTOCOL]] [[WSPR_PROTOCOL]]
==== WSPR ==== WSPR

View File

@ -26,13 +26,7 @@ TIP: The PC audio mixer normally has two sliders, one for each
- If your transceiver offers more than one bandwidth setting in USB - If your transceiver offers more than one bandwidth setting in USB
mode, it may be advantageous to choose the widest one possible, up mode, it may be advantageous to choose the widest one possible, up
to about 5 kHz. This choice has the desirable effect of allowing to about 5 kHz.
the *Wide Graph* (waterfall and 2D spectrum) to display the
conventional JT65 and JT9 sub-bands simultaneously on most HF bands.
Further details are provided in the <<TUTORIAL,Basic Operating
Tutorial>>. A wider displayed bandwidth may also be helpful at VHF
and above, where FT8, JT4, JT65, and Q65 signals may be found over
much wider ranges of frequencies.
- If you have only a standard SSB filter you wont be able to display - If you have only a standard SSB filter you wont be able to display
more than about 2.7 kHz bandwidth. Depending on the exact dial more than about 2.7 kHz bandwidth. Depending on the exact dial

View File

@ -1,15 +1,15 @@
_WSJT-X_ supports a number of features designed for use on the VHF and _WSJT-X_ supports a number of features designed for use on the VHF and
higher bands. These features include: higher bands. These features include:
- *FT4*, designed especially for contesting - *FT4*, for contesting
- *FT8*, designed for making fast QSOs with weak, fading signals - *FT8*, for fast QSOs with weak, fading signals
- *JT4*, particularly useful for EME on the microwave bands - *JT4*, for EME on the microwave bands
- *JT9 fast modes*, useful for scatter propagation on VHF bands - *JT9 fast modes*, for scatter propagation on VHF bands
- *JT65*, widely used for EME on VHF and higher bands - *JT65*, for EME on VHF and higher bands
- *Q65*, for ionospheric scatter, tropospheric scatter, rain scatter, - *Q65*, for ionospheric scatter, tropospheric scatter, rain scatter,
TEP, and EME TEP, and EME
@ -175,29 +175,31 @@ image::JT65B.png[align="center",alt="JT65B"]
=== Q65 === Q65
Q65 is designed for propagation paths that produce fast fading Q65 is designed for fast-fading signals: tropospheric scatter, rain
signals: tropospheric scatter, rain scatter, ionospheric scatter, scatter, ionospheric scatter, trans-equatorial propagation (TEP), EME,
trans-equatorial propagation (TEP), EME, and the like. The following and the like. The following screen shot shows a series of ionospheric
screen shot shows an example with submode Q65-30A on a 6-meter scatter QSOs using submode Q65-30A on the 6 meter band. The received
ionospheric scatter path of about 1100 km. signals were barely audible most of the time.
image::Q65_6m_ionoscatter.png[align="center",alt="Q65"] image::Q65_6m_ionoscatter.png[align="center",alt="Q65"]
The Q65 decoder makes no use of a callsign database. Instead, it The Q65 decoder takes advantage of _a priori_ (AP) information such as
takes advantage of _a priori_ (AP) information such as one's own the encoded forms of one's own callsign and the message word `CQ`. In
callsign and the message word `CQ`. In normal usage, as a QSO normal usage, as a QSO progresses AP information increases to include
progresses the available AP information increases to include the the callsign of the station being worked and perhaps his/her 4-digit
callsign of the station being worked and perhaps also his/her 4-digit
grid locator. The decoder takes advantage of whatever AP information grid locator. The decoder takes advantage of whatever AP information
is available. is currently available.
For Q65 EME QSOs, particularly on the micriowave bands, some operators For Q65 EME QSOs on the microwave bands, some operators
use short-form messages consisting of a single tone. To activate use short-form messages consisting of a single tone. To activate
automatic generation of these messages, check the box labeled *Sh*. automatic generation of these messages, check the box labeled *Sh*.
This also enables the generation of a single tone at 1000Hz by This also enables the generation of a single tone at 1000Hz by
selecting Tx6, to assist in finding signals initially. The box selecting Tx6, to assist in finding signals initially. The box
labeled *Tx6* switches the Tx6 message from 1000Hz to 1250Hz to labeled *Tx6* switches the Tx6 message from 1000Hz to 1250Hz to
indicate to the other station that you are ready to receive messages. indicate to the other station that you are ready to receive messages.
These short-form messages are not decoded automatically, and
auto-sequencing will not respond to them. You must recognize and
interpret them yourself.
// TIP: G3WDG has prepared a more detailed tutorial on using {QRA64_EME}. // TIP: G3WDG has prepared a more detailed tutorial on using {QRA64_EME}.
@ -314,11 +316,12 @@ image::echo_144.png[align="center",alt="Echo 144 MHz"]
Until the advent of Q65, digital EME has mostly been done using JT65A Until the advent of Q65, digital EME has mostly been done using JT65A
on the 50 MHz band, JT65B on 144 and 432 MHz, and JT65C on 1296 MHz. on the 50 MHz band, JT65B on 144 and 432 MHz, and JT65C on 1296 MHz.
On higher microwave bands typical choices have been JT65C or one of On higher microwave bands typical choices have been JT65C, one of the
the wider QRA64 or JT4 submodes, depending on the expected amount of wider JT4 submodes, or QRA64, depending on the expected amount of
Doppler spread. We now recommend a suitable submodes of Q65 for EME Doppler spread. We now recommend a suitable submode of Q65 (which has
on all bands: for example, Q65-60A on 50 and 144 MHz, -60B on replaced QRA64) for EME on any VHF or higher band: for example,
432 MHz, -60C on 1296 MHz, and -60D on 10 GHz. Q65-60A on 50 and 144 MHz, Q65-60B on 432 MHz, Q65-60C on 1296 MHz,
and Q65-60D on 10 GHz.
JT4, JT65, and Q65 offer *Message Averaging* -- the summation of JT4, JT65, and Q65 offer *Message Averaging* -- the summation of
subsequent transmissions that convey the same message -- to enable subsequent transmissions that convey the same message -- to enable

View File

@ -6,7 +6,7 @@ Joseph H Taylor, Jr, K1JT
// package building .deb, .rpm, etc as it exposes the IP address and the images // package building .deb, .rpm, etc as it exposes the IP address and the images
// are non-free, so can't be included as part of the Debian package. // are non-free, so can't be included as part of the Debian package.
// :badges: // :badges:
:docinfo1: :docinfo: shared
:imagesdir: {docdir}/images :imagesdir: {docdir}/images
:icons: font :icons: font
:numbered: :numbered:

View File

@ -87,7 +87,7 @@ contains
! Determine the T/R sequence: iseq=0 (even), or iseq=1 (odd) ! Determine the T/R sequence: iseq=0 (even), or iseq=1 (odd)
n=nutc n=nutc
if(ntrperiod.ge.60) n=100*n if(ntrperiod.ge.60 .and. nutc.le.2359) n=100*n
write(cutc,'(i6.6)') n write(cutc,'(i6.6)') n
read(cutc,'(3i2)') ih,im,is read(cutc,'(3i2)') ih,im,is
nsec=3600*ih + 60*im + is nsec=3600*ih + 60*im + is
@ -234,7 +234,9 @@ contains
nsnr=nint(snr2) nsnr=nint(snr2)
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
idec,nused,ntrperiod) idec,nused,ntrperiod)
if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode ! if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode) call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios) position='append',iostat=ios)
@ -246,13 +248,13 @@ contains
if(c6.eq.' ') c6='<b> ' if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4) c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> ' if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f6.2,'// & fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, & write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, &
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,tdecode, & ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
mycall(1:6),c6,c4,trim(decoded) tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) close(22)
endif endif
! else ! else
@ -316,7 +318,9 @@ contains
nsnr=nint(snr2) nsnr=nint(snr2)
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
idec,nused,ntrperiod) idec,nused,ntrperiod)
if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode ! if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode) call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios) position='append',iostat=ios)
@ -328,13 +332,13 @@ contains
if(c6.eq.' ') c6='<b> ' if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4) c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> ' if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f6.2,'// & fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, & write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, &
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,tdecode, & ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
mycall(1:6),c6,c4,trim(decoded) tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) close(22)
endif endif
endif endif

View File

@ -20,8 +20,10 @@ module q65
real, allocatable :: s1raw(:,:) !Symbol spectra, 1/8-symbol steps real, allocatable :: s1raw(:,:) !Symbol spectra, 1/8-symbol steps
real, allocatable :: s1(:,:) !Symbol spectra w/suppressed peaks real, allocatable :: s1(:,:) !Symbol spectra w/suppressed peaks
real, allocatable,save :: s1a(:,:,:) !Cumulative symbol spectra real, allocatable,save :: s1a(:,:,:) !Cumulative symbol spectra
real, allocatable,save :: ccf2(:) !Max CCF(freq) at any lag, single seq
real, allocatable,save :: ccf2_avg(:) !Like ccf2, but for accumulated average
real sync(85) !sync vector real sync(85) !sync vector
real df,dtstep,dtdec,f0dec,ftol real df,dtstep,dtdec,f0dec,ftol,plog
contains contains
@ -64,7 +66,6 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
logical first,lclearave logical first,lclearave
real, allocatable :: s3(:,:) !Data-symbol energies s3(LL,63) real, allocatable :: s3(:,:) !Data-symbol energies s3(LL,63)
real, allocatable :: ccf1(:) !CCF(freq) at fixed lag (red) real, allocatable :: ccf1(:) !CCF(freq) at fixed lag (red)
real, allocatable :: ccf2(:) !Max CCF(freq) at any lag (orange)
data first/.true./ data first/.true./
save first save first
@ -98,7 +99,6 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
allocate(s3(-64:LL-65,63)) allocate(s3(-64:LL-65,63))
allocate(ccf1(-ia2:ia2)) allocate(ccf1(-ia2:ia2))
allocate(ccf2(iz))
if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then
if(allocated(s1raw)) deallocate(s1raw) if(allocated(s1raw)) deallocate(s1raw)
allocate(s1raw(iz,jz)) allocate(s1raw(iz,jz))
@ -106,6 +106,10 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
allocate(s1(iz,jz)) allocate(s1(iz,jz))
if(allocated(s1a)) deallocate(s1a) if(allocated(s1a)) deallocate(s1a)
allocate(s1a(iz,jz,0:1)) allocate(s1a(iz,jz,0:1))
if(allocated(ccf2)) deallocate(ccf2)
allocate(ccf2(iz))
if(allocated(ccf2_avg)) deallocate(ccf2_avg)
allocate(ccf2_avg(iz))
s1=0. s1=0.
s1a=0. s1a=0.
navg=0 navg=0
@ -114,6 +118,8 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
jz0=jz jz0=jz
lclearave=.false. lclearave=.false.
endif endif
ccf1=0.
ccf2_avg=0.
dtstep=nsps/(NSTEP*12000.0) !Step size in seconds dtstep=nsps/(NSTEP*12000.0) !Step size in seconds
lag1=-1.0/dtstep lag1=-1.0/dtstep
lag2=1.0/dtstep + 0.9999 lag2=1.0/dtstep + 0.9999
@ -145,7 +151,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
enddo enddo
dat4=0 dat4=0
if(ncw.gt.0 .and. iavg.lt.2) then if(ncw.gt.0 .and. iavg.le.1) then
! 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
@ -157,8 +163,14 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call timer('list_dec',1) call timer('list_dec',1)
endif endif
! Get 2d CCF and ccf2 using sync symbols only if(iavg.eq.0) then
call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2) call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2)
endif
! Get 2d CCF and ccf2 using sync symbols only
if(iavg.ge.1) then
call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2_avg)
endif
if(idec.lt.0) then if(idec.lt.0) then
f0=f0a f0=f0a
xdt=xdta xdt=xdta
@ -188,7 +200,9 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
width=df*(i2-i1) width=df*(i2-i1)
if(ncw.eq.0) ccf1=0. if(ncw.eq.0) ccf1=0.
call q65_write_red(iz,ia2,xdt,ccf1,ccf2) ! write(*,3001) nutc,iavg,navg(0),sum(ccf2_avg),sum(ccf2)
!3001 format(i4.4,2i4,2f8.2)
call q65_write_red(iz,xdt,ccf2_avg,ccf2)
if(iavg.eq.2) then if(iavg.eq.2) then
call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded)
@ -555,28 +569,28 @@ subroutine q65_s1_to_s3(s1,iz,jz,ipk,jpk,LL,mode_q65,sync,s3)
return return
end subroutine q65_s1_to_s3 end subroutine q65_s1_to_s3
subroutine q65_write_red(iz,ia2,xdt,ccf1,ccf2) subroutine q65_write_red(iz,xdt,ccf2_avg,ccf2)
! Write data for the red and orange sync curves to LU 17. ! Write data for the red and orange sync curves to LU 17.
real ccf1(-ia2:ia2) real ccf2_avg(iz)
real ccf2(iz) real ccf2(iz)
call q65_sync_curve(ccf1,-ia2,ia2,rms1) call q65_sync_curve(ccf2_avg,1,iz,rms1)
call q65_sync_curve(ccf2,1,iz,rms2) call q65_sync_curve(ccf2,1,iz,rms2)
rewind 17 rewind 17
write(17,1000) xdt write(17,1000) xdt
do i=1,iz do i=max(1,nint(nfa/df)),nint(nfb/df)
freq=i*df freq=i*df
ii=i-i0 y1=ccf2_avg(i)
if(freq.ge.float(nfa) .and. freq.le.float(nfb)) then if(y1.gt.10.0) y1=10.0 + 2.0*log10(y1/10.0)
ccf1a=-99.0 y2=ccf2(i)
if(ii.ge.-ia2 .and. ii.le.ia2) ccf1a=ccf1(ii) if(y2.gt.10.0) y2=10.0 + 2.0*log10(y2/10.0)
write(17,1000) freq,ccf1a,ccf2(i) write(17,1000) freq,y1,y2
1000 format(3f10.3) 1000 format(3f10.3)
endif
enddo enddo
flush(17)
return return
end subroutine q65_write_red end subroutine q65_write_red
@ -596,9 +610,9 @@ subroutine q65_sync_curve(ccf1,ia,ib,rms1)
dot_product(ccf1(ib-ic:ib),ccf1(ib-ic:ib)) dot_product(ccf1(ib-ic:ib),ccf1(ib-ic:ib))
rms1=0. rms1=0.
if(nsum.gt.0) rms1=sqrt(sq/nsum) if(nsum.gt.0) rms1=sqrt(sq/nsum)
if(rms1.gt.0.0) ccf1=2.0*ccf1/rms1 if(rms1.gt.0.0) ccf1=ccf1/rms1
smax1=maxval(ccf1) ! smax1=maxval(ccf1)
if(smax1.gt.10.0) ccf1=10.0*ccf1/smax1 ! if(smax1.gt.10.0) ccf1=10.0*ccf1/smax1
return return
end subroutine q65_sync_curve end subroutine q65_sync_curve

View File

@ -1,164 +0,0 @@
subroutine sync64(c0,nf1,nf2,nfqso,ntol,minsync,mode64,emedelay,dtx,f0, &
jpk,sync,sync2,width)
use timer_module, only: timer
parameter (NMAX=60*12000) !Max size of raw data at 12000 Hz
parameter (NSPS=3456) !Samples per symbol at 6000 Hz
parameter (NSPC=7*NSPS) !Samples per Costas waveform
real s1(0:NSPC-1) !Power spectrum of Costas 1
real s2(0:NSPC-1) !Power spectrum of Costas 2
real s3(0:NSPC-1) !Power spectrum of Costas 3
real s0(0:NSPC-1) !Sum of s1+s2+s3
real s0a(0:NSPC-1) !Best synchromized spectrum (saved)
real s0b(0:NSPC-1) !tmp
real a(5) !Parameters of Lorentzian fit
integer icos7(0:6) !Costas 7x7 tones
integer ipk0(1)
complex cc(0:NSPC-1) !Costas waveform
complex c0(0:720000) !Complex spectrum of dd()
complex c1(0:NSPC-1) !Complex spectrum of Costas 1
complex c2(0:NSPC-1) !Complex spectrum of Costas 2
complex c3(0:NSPC-1) !Complex spectrum of Costas 3
data icos7/2,5,6,0,4,1,3/ !Costas 7x7 tone pattern
data mode64z/-1/
save
if(mode64.ne.mode64z) then
! Submode has changed, recompute the complex Costas waveform
twopi=8.0*atan(1.0)
dfgen=mode64*12000.0/6912.0
k=-1
phi=0.
do j=0,6
dphi=twopi*10.0*icos7(j)*dfgen/6000.0
do i=1,NSPS
phi=phi + dphi
if(phi.gt.twopi) phi=phi-twopi
k=k+1
cc(k)=cmplx(cos(phi),sin(phi))
enddo
enddo
mode64z=mode64
endif
nfft3=NSPC
df3=6000.0/nfft3
fa=max(nf1,nfqso-ntol)
fb=min(nf2,nfqso+ntol)
iaa=max(0,nint(fa/df3))
ibb=min(NSPC-1,nint(fb/df3))
maxtol=max(ntol,500)
fa=max(nf1,nfqso-maxtol)
fb=min(nf2,nfqso+maxtol)
ia=max(0,nint(fa/df3))
ib=min(NSPC-1,nint(fb/df3))
id=0.1*(ib-ia)
iz=ib-ia+1
sync=-1.e30
smaxall=0.
jpk=0
ja=0
! jb=(5.0+emedelay)*6000 !Bigger range than necessary?
jb=(2.0+emedelay)*6000 !Bigger range than necessary?
jstep=100
ipk=0
kpk=0
nadd=10*mode64
if(minsync.eq.-2) nadd=10 !###
if(mod(nadd,2).eq.0) nadd=nadd+1 !Make nadd odd
nskip=max(49,nadd)
do j1=ja,jb,jstep !Loop over DT
call timer('sync64_1',0)
j2=j1 + 39*NSPS
j3=j1 + 77*NSPS
c1=1.e-4*c0(j1:j1+NSPC-1) * conjg(cc)
c2=1.e-4*c0(j2:j2+NSPC-1) * conjg(cc)
c3=1.e-4*c0(j3:j3+NSPC-1) * conjg(cc)
call four2a(c1,nfft3,1,-1,1)
call four2a(c2,nfft3,1,-1,1)
call four2a(c3,nfft3,1,-1,1)
s1=0.
s2=0.
s3=0.
s0b=0.
do i=ia,ib
freq=i*df3
s1(i)=real(c1(i))**2 + aimag(c1(i))**2
s2(i)=real(c2(i))**2 + aimag(c2(i))**2
s3(i)=real(c3(i))**2 + aimag(c3(i))**2
enddo
call timer('sync64_1',1)
call timer('sync64_2',0)
s0(ia:ib)=s1(ia:ib) + s2(ia:ib) + s3(ia:ib)
s0(:ia-1)=0.
s0(ib+1:)=0.
if(nadd.ge.3) then !Smooth the spectrum
iiz=3
if(minsync.eq.-2) iiz=1
do ii=1,iiz !### Was ii=1,3
s0b(ia:ib)=s0(ia:ib)
call smo(s0b(ia:ib),iz,s0(ia:ib),nadd)
enddo
endif
call averms(s0(ia+id:ib-id),iz-2*id,nskip,ave,rms)
s=(maxval(s0(iaa:ibb))-ave)/rms
ipk0=maxloc(s0(iaa:ibb))
ip=ipk0(1) + iaa - 1
if(s.gt.sync) then
jpk=j1
s0a=(s0-ave)/rms
sync=s
dtx=jpk/6000.0 - 1.0
ipk=ip
f0=ip*df3
endif
call timer('sync64_2',1)
enddo ! j1 (DT loop)
s0a=s0a+2.0
nskip=50
call lorentzian(s0a(ia+nskip:ib-nskip),iz-2*nskip,a)
f0a=(a(3)+ia+49)*df3
w1=df3*a(4)
w2=2*nadd*df3
width=w1
if(w1.gt.1.2*w2) width=sqrt(w1**2 - w2**2)
sq=0.
do i=1,20
j=ia+nskip+1
k=ib-nskip-21+i
sq=sq + (s0a(j)-a(1))**2 + (s0a(k)-a(1))**2
enddo
rms2=sqrt(sq/40.0)
sync2=10.0*log10(a(2)/rms2)
slimit=6.0
rewind 17
write(17,1110) 0.0,0.0
rewind 17
do i=2,iz-2*nskip-1,3
x=i
z=(x-a(3))/(0.5*a(4))
yfit=a(1)
if(abs(z).lt.3.0) then
d=1.0 + z*z
yfit=a(1) + a(2)*(1.0/d - 0.1)
endif
j=i+ia+49
freq=j*df3
ss=(s0a(j-1)+s0a(j)+s0a(j+1))/3.0
if(ss.gt.slimit) write(17,1110) freq,ss
1110 format(3f10.3)
enddo
flush(17)
close(17)
return
end subroutine sync64

View File

@ -21,7 +21,6 @@ set (SAMPLE_FILES
JT9/130418_1742.wav JT9/130418_1742.wav
MSK144/181211_120500.wav MSK144/181211_120500.wav
MSK144/181211_120800.wav MSK144/181211_120800.wav
QRA64/QRA64C/161113_0111.wav
WSPR/150426_0918.wav WSPR/150426_0918.wav
Q65/30A_Ionoscatter_6m/201203_022700.wav Q65/30A_Ionoscatter_6m/201203_022700.wav
Q65/30A_Ionoscatter_6m/201203_022800.wav Q65/30A_Ionoscatter_6m/201203_022800.wav

View File

@ -21,7 +21,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"&copy; 2001-2021 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />" "&copy; 2001-2021 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />"
"and Steve Franke, K9AN. <br /><br />" "and Steve Franke, K9AN. <br /><br />"
"We gratefully acknowledge contributions from AC6SL, AE4JY,<br />" "We gratefully acknowledge contributions from AC6SL, AE4JY,<br />"
"DF2ET, DJ0OT, G3WDG, G4KLA, IV3NWV, IW3RAB, KA1GT, K3WYC,<br />" "DF2ET, DJ0OT, G3WDG, G4KLA, IW3RAB, K3WYC, KA1GT,<br />"
"KA6MAL, KA9Q, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR,<br />" "KA6MAL, KA9Q, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR,<br />"
"VE1SKY, VK3ACF, VK4BDJ, VK7MO, W3DJS, W4TI, W4TV, and W9MDB.<br /><br />" "VE1SKY, VK3ACF, VK4BDJ, VK7MO, W3DJS, W4TI, W4TV, and W9MDB.<br /><br />"
"WSJT-X is licensed under the terms of Version 3 <br />" "WSJT-X is licensed under the terms of Version 3 <br />"

View File

@ -3293,7 +3293,6 @@ void MainWindow::to_jt9(qint32 n, qint32 istart, qint32 idone)
void MainWindow::decodeDone () void MainWindow::decodeDone ()
{ {
if(m_mode!="FT8" or dec_data.params.nzhsym==50) m_nDecodes=0;
if(m_mode=="Q65") m_wideGraph->drawRed(0,0); if(m_mode=="Q65") m_wideGraph->drawRed(0,0);
if ("FST4W" == m_mode) if ("FST4W" == m_mode)
{ {
@ -3310,11 +3309,20 @@ void MainWindow::decodeDone ()
double tdone = fmod(double(tnow.time().second()),m_TRperiod); double tdone = fmod(double(tnow.time().second()),m_TRperiod);
int mswait; int mswait;
if( tdone < 0.5*m_TRperiod ) { if( tdone < 0.5*m_TRperiod ) {
mswait = 1000.0 * ( 0.75 * m_TRperiod - tdone ); mswait = 1000.0 * ( 0.6 * m_TRperiod - tdone );
} else { } else {
mswait = 1000.0 * ( 1.75 * m_TRperiod - tdone ); mswait = 1000.0 * ( 1.6 * m_TRperiod - tdone );
} }
if(!m_diskData) killFileTimer.start(mswait); //Kill at 3/4 period m_bDecoded=m_nDecodes>0;
// qDebug() << "aa 3316" << m_saveDecoded << m_saveAll << m_bDecoded << m_nDecodes
// << m_TRperiod << tdone << mswait;
if(!m_diskData and !m_saveAll) {
if(m_saveDecoded and (m_nDecodes==0)) {
// qDebug() << "bb 3319" << mswait;
killFileTimer.start(mswait); //Kill at 3/4 period
}
}
if(m_mode!="FT8" or dec_data.params.nzhsym==50) m_nDecodes=0;
dec_data.params.nagain=0; dec_data.params.nagain=0;
dec_data.params.ndiskdat=0; dec_data.params.ndiskdat=0;
@ -3717,6 +3725,7 @@ void MainWindow::pskPost (DecodedText const& decodedtext)
void MainWindow::killFile () void MainWindow::killFile ()
{ {
// qDebug() << "cc 3725" << m_saveDecoded << m_saveAll << m_bDecoded << m_nDecodes << m_fnameWE;
if (m_fnameWE.size () && !(m_saveAll || (m_saveDecoded && m_bDecoded))) { if (m_fnameWE.size () && !(m_saveAll || (m_saveDecoded && m_bDecoded))) {
QFile f1 {m_fnameWE + ".wav"}; QFile f1 {m_fnameWE + ".wav"};
if(f1.exists()) f1.remove(); if(f1.exists()) f1.remove();
@ -4029,8 +4038,8 @@ void MainWindow::guiUpdate()
if(m_tune or m_mode=="Echo") { if(m_tune or m_mode=="Echo") {
itone[0]=0; itone[0]=0;
} else { } else {
if(m_QSOProgress==2 or m_QSOProgress==3) m_bSentReport=true; if(m_QSOProgress==REPORT || m_QSOProgress==ROGER_REPORT) m_bSentReport=true;
if(m_bSentReport and (m_QSOProgress<2 or m_QSOProgress>3)) m_bSentReport=false; if(m_bSentReport and (m_QSOProgress<REPORT or m_QSOProgress>ROGER_REPORT)) m_bSentReport=false;
if(m_modeTx=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone), if(m_modeTx=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22); &m_currentMessageType, 22, 22);
if(m_modeTx=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone), if(m_modeTx=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone),
@ -4997,7 +5006,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
auto const& word_3 = message_words.at (3); auto const& word_3 = message_words.at (3);
auto word_3_as_number = word_3.toInt (); auto word_3_as_number = word_3.toInt ();
if (("RRR" == word_3 if (("RRR" == word_3
|| word_3_as_number == 73 || (word_3_as_number == 73 && ROGERS == m_QSOProgress)
|| "RR73" == word_3 || "RR73" == word_3
|| ("R" == word_3 && m_QSOProgress != REPORT))) { || ("R" == word_3 && m_QSOProgress != REPORT))) {
if(m_mode=="FT4" and "RR73" == word_3) m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc(); if(m_mode=="FT4" and "RR73" == word_3) m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc();
@ -5026,11 +5035,31 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
m_ntx=4; m_ntx=4;
ui->txrb4->setChecked(true); ui->txrb4->setChecked(true);
} }
else else if ((m_QSOProgress > CALLING && m_QSOProgress < ROGERS)
|| word_3.contains (QRegularExpression {"^RR(?:R|73)$"}))
{ {
m_ntx=5; m_ntx=5;
ui->txrb5->setChecked(true); ui->txrb5->setChecked(true);
} }
else if (ROGERS == m_QSOProgress)
{
logQSOTimer.start(0);
m_ntx=6;
ui->txrb6->setChecked(true);
}
else
{
// just work them (again)
if (ui->tx1->isEnabled ()) {
m_ntx = 1;
m_QSOProgress = REPLYING;
ui->txrb1->setChecked (true);
} else {
m_ntx=2;
m_QSOProgress = REPORT;
ui->txrb2->setChecked (true);
}
}
} }
if (m_QSOProgress >= ROGER_REPORT) if (m_QSOProgress >= ROGER_REPORT)
{ {
@ -5182,10 +5211,10 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
lookup(); lookup();
m_hisGrid = ui->dxGridEntry->text(); m_hisGrid = ui->dxGridEntry->text();
QString rpt = message.report(); if (!m_bSentReport || base_call != qso_partner_base_call) // Don't change report within a QSO
int n=rpt.toInt(); {
auto n = message.report ().toInt ();
if(m_mode=="MSK144" and m_bShMsgs) { if(m_mode=="MSK144" and m_bShMsgs) {
int n=rpt.toInt();
if(n<=-2) n=-3; if(n<=-2) n=-3;
if(n>=-1 and n<=1) n=0; if(n>=-1 and n<=1) n=0;
if(n>=2 and n<=4) n=3; if(n>=2 and n<=4) n=3;
@ -5193,14 +5222,13 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
if(n>=8 and n<=11) n=10; if(n>=8 and n<=11) n=10;
if(n>=12 and n<=14) n=13; if(n>=12 and n<=14) n=13;
if(n>=15) n=16; if(n>=15) n=16;
rpt=QString::number(n);
} }
ui->rptSpinBox->setValue (n);
if(!m_bSentReport) ui->rptSpinBox->setValue(n); //Don't change report within a QSO }
// Don't genStdMsgs if we're already sending 73, or a "TU; " msg is queued. // Don't genStdMsgs if we're already sending 73, or a "TU; " msg is queued.
m_bTUmsg=false; //### Temporary: disable use of "TU;" messages m_bTUmsg=false; //### Temporary: disable use of "TU;" messages
if (!m_bSentReport and !m_nTx73 and !m_bTUmsg) { if (!m_nTx73 and !m_bTUmsg) {
genStdMsgs(rpt); genStdMsgs (QString::number (ui->rptSpinBox->value ()));
} }
if(m_transmitting) m_restart=true; if(m_transmitting) m_restart=true;
if (ui->cbAutoSeq->isVisible () && ui->cbAutoSeq->isChecked () if (ui->cbAutoSeq->isVisible () && ui->cbAutoSeq->isChecked ()
@ -6406,7 +6434,6 @@ void MainWindow::on_actionJT65_triggered()
void MainWindow::on_actionQ65_triggered() void MainWindow::on_actionQ65_triggered()
{ {
// on_actionFST4_triggered();
m_mode="Q65"; m_mode="Q65";
m_modeTx="Q65"; m_modeTx="Q65";
ui->actionQ65->setChecked(true); ui->actionQ65->setChecked(true);
@ -6432,11 +6459,19 @@ void MainWindow::on_actionQ65_triggered()
switch_mode (Modes::Q65); switch_mode (Modes::Q65);
// 0123456789012345678901234567890123456 // 0123456789012345678901234567890123456
displayWidgets(nWidgets("1111110101101101001110000001000000001")); displayWidgets(nWidgets("1111110101101101001110000001000000001"));
ui->labDXped->setText("");
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes")); ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes")); ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
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);
ui->labDXped->setText("Contest ?");
} else {
ui->labDXped->setVisible(false);
ui->labDXped->setText("");
}
} }
void MainWindow::on_actionMSK144_triggered() void MainWindow::on_actionMSK144_triggered()
@ -6684,6 +6719,16 @@ void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
if(m_mode!="MSK144") { if(m_mode!="MSK144") {
Q_EMIT transmitFrequency (n - m_XIT); Q_EMIT transmitFrequency (n - m_XIT);
} }
if(m_mode=="Q65") {
if(((m_nSubMode==4 && m_TRperiod==60.0) || (m_nSubMode==3 && m_TRperiod==30.0) ||
(m_nSubMode==2 && m_TRperiod==15.0)) && ui->TxFreqSpinBox->value()!=700) {
ui->TxFreqSpinBox->setStyleSheet("QSpinBox{background-color:red}");
} else {
ui->TxFreqSpinBox->setStyleSheet("");
}
}
statusUpdate (); statusUpdate ();
} }
@ -7562,9 +7607,7 @@ void MainWindow::on_sbTR_valueChanged(int value)
progressBar.setMaximum (value); progressBar.setMaximum (value);
} }
if(m_mode=="FST4") chk_FST4_freq_range(); if(m_mode=="FST4") chk_FST4_freq_range();
if(m_transmitting) { // if(m_transmitting) on_stopTxButton_clicked(); //### Is this needed or desirable? ###
on_stopTxButton_clicked();
}
on_sbSubmode_valueChanged(ui->sbSubmode->value()); on_sbSubmode_valueChanged(ui->sbSubmode->value());
statusUpdate (); statusUpdate ();
} }
@ -7598,10 +7641,11 @@ void MainWindow::on_sbSubmode_valueChanged(int n)
mode_label.setText (m_mode); mode_label.setText (m_mode);
} }
if(m_mode=="Q65") { if(m_mode=="Q65") {
if((m_nSubMode==4 && m_TRperiod==60.0) || (m_nSubMode==3 && m_TRperiod==30.0) || (m_nSubMode==2 && m_TRperiod==15.0)) if(((m_nSubMode==4 && m_TRperiod==60.0) || (m_nSubMode==3 && m_TRperiod==30.0) ||
{ ui->TxFreqSpinBox->setValue(700); (m_nSubMode==2 && m_TRperiod==15.0)) && ui->TxFreqSpinBox->value()!=700) {
ui->TxFreqSpinBox->setStyleSheet("QSpinBox{background-color:red}");
} else { } else {
ui->TxFreqSpinBox->setValue(1000); ui->TxFreqSpinBox->setStyleSheet("");
} }
} }
if(m_mode=="JT9") { if(m_mode=="JT9") {

View File

@ -239,7 +239,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
if(y2>y2max) y2max=y2; if(y2>y2max) y2max=y2;
j++; j++;
} }
if(m_bReplot) return; if(m_bReplot and m_mode!="Q65") return;
if(swide[0]>1.0e29) m_line=0; if(swide[0]>1.0e29) m_line=0;
if(m_mode=="FT4" and m_line==34) m_line=0; if(m_mode=="FT4" and m_line==34) m_line=0;
@ -274,7 +274,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
painter2D.drawText(x1-4,y,"73"); painter2D.drawText(x1-4,y,"73");
} }
if(bRed and m_bQ65_Sync) { //Plot the Q65 red or orange sync curve if(bRed and m_bQ65_Sync) { //Plot the Q65 red/orange sync curves
int k=0; int k=0;
int k2=0; int k2=0;
std::ifstream f; std::ifstream f;
@ -283,9 +283,10 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
int x,y; int x,y;
float freq,xdt,sync,sync2; float freq,xdt,sync,sync2;
f >> xdt; f >> xdt;
if(f) {
for(int i=0; i<99999; i++) { for(int i=0; i<99999; i++) {
f >> freq >> sync >> sync2; f >> freq >> sync >> sync2;
if(f.eof()) break; if(!f or f.eof()) break;
x=XfromFreq(freq); x=XfromFreq(freq);
if(sync > -99.0 and sync != 0.0) { if(sync > -99.0 and sync != 0.0) {
y=m_h2*(0.9 - 0.09*gain2d*sync) - m_plot2dZero - 10; y=m_h2*(0.9 - 0.09*gain2d*sync) - m_plot2dZero - 10;
@ -298,6 +299,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
LineBuf3[k].setY(y); LineBuf3[k].setY(y);
k++; k++;
} }
}
f.close(); f.close();
QPen pen0(Qt::red,2); QPen pen0(Qt::red,2);
painter2D.setPen(pen0); painter2D.setPen(pen0);
@ -335,6 +337,9 @@ void CPlotter::replot()
plotsave_(swide,&m_w,&m_h1,&irow); plotsave_(swide,&m_w,&m_h1,&irow);
draw(swide,false,false); draw(swide,false,false);
} }
if(m_mode=="Q65" and m_bQ65_Sync) {
draw(swide,false,true);
}
update(); //trigger a new paintEvent update(); //trigger a new paintEvent
m_bReplot=false; m_bReplot=false;
} }
@ -623,7 +628,6 @@ void CPlotter::MakeFrequencyStrs() //MakeFrequencyStrs
int CPlotter::XfromFreq(float f) //XfromFreq() int CPlotter::XfromFreq(float f) //XfromFreq()
{ {
// float w = m_WaterfallPixmap.width();
int x = int(m_w * (f - m_startFreq)/m_fSpan + 0.5); int x = int(m_w * (f - m_startFreq)/m_fSpan + 0.5);
if(x<0 ) return 0; if(x<0 ) return 0;
if(x>m_w) return m_w; if(x>m_w) return m_w;
@ -765,6 +769,7 @@ void CPlotter::mouseReleaseEvent (QMouseEvent * event)
else { else {
event->ignore (); // let parent handle event->ignore (); // let parent handle
} }
// replot(); // ### Not needed? ###
} }
void CPlotter::mouseDoubleClickEvent (QMouseEvent * event) void CPlotter::mouseDoubleClickEvent (QMouseEvent * event)
@ -774,8 +779,7 @@ void CPlotter::mouseDoubleClickEvent (QMouseEvent * event)
int n=2; int n=2;
if(ctrl) n+=100; if(ctrl) n+=100;
emit freezeDecode1(n); emit freezeDecode1(n);
} } else {
else {
event->ignore (); // let parent handle event->ignore (); // let parent handle
} }
} }