Merged master 8748

This commit is contained in:
Jordan Sherer
2018-08-05 11:33:30 -04:00
parent 8f8772f1bd
commit 62899069bf
1222 changed files with 70382 additions and 406763 deletions
@@ -1,94 +0,0 @@
=== AP Decoding
With the QRA64 decoder Nico Palermo, IV3NWV, introduced a technique
for decoding with the aid of information that naturally accumulates
during a minimal QSO. This _a priori_ (AP) information can be
used to increase the sensitivity of the decoder.
When an operator decides to answer a CQ, he already knows his own
callsign and that of his potential QSO partner. He therefore knows
what to expect for at least 56 of the 72 message bits in a
standard-format response to his call. The _WSJT-X_ decoders for QRA64
and FT8 can use these AP bits to decode messages containing them with
higher sensitivity than otherwise possible.
We have implemented AP decoding in slightly different ways in QRA64
and FT8. To provide some explicit examples for users, we provide here
a brief description of the FT8 behavior.
The FT8 decoder always tries first to decode a signal without using
any AP information. If this attempt fails, and if *Enable AP* is
checked on the *Decode* menu, a second attempt hypothesizes that the
message contains callsigns MyCall and DxCall. If the QSO has
progressed to the point where signal reports have been exchanged, a
third attempt hypothesizes that the message contains the known
callsigns followed by RRR, RR73, or 73.
AP decoding attempts effectively set the AP bits to the hypothesized
values, as if they had been received perfectly. The decoder then
proceeds to determine whether the remaining message and parity bits
are consistent with the hypothesized AP bits. If a codeword is found
that the decoder judges to have high (but not overwhelmingly high)
probability of being correct, a ? character is appended when the
decoded message is displayed. Decodes thus marked are not sent to
{pskreporter} to avoid occasional misleading spots of false decodes.
Successful AP decodes are always labeled with an end-of-line indicator
of the form aP, where P is one of the single-digit AP decoding types
listed in Table 1. For example, an a2 designator says that the
successful decode used MyCall as hypothetically known information.
[[AP_INFO_TABLE]]
.AP information types
[width="35%",cols="h10,<m20",frame=topbot,options="header"]
|===============================================
|P | Message components
|1 | CQ &#160; &#160; ? &#160; &#160; ?
|2 | MyCall &#160; &#160; ? &#160; &#160; ?
|3 | MyCall DxCall &#160; &#160; ?
|4 | MyCall DxCall RRR
|5 | MyCall DxCall 73
|6 | MyCall DxCall RR73
|===============================================
=== Decoded Lines
Displayed information accompanying decoded messages generally includes UTC,
signal-to-noise ratio in dB, time offset DT in seconds, and
audio frequency in Hz. Some modes include additional information such
as frequency offset from nominal (DF), frequency drift (Drift or F1),
or distance (km or mi).
There may also be some cryptic characters with special meanings
summarized in the following Table:
[[DECODED_LINES_TABLE]]
.Notations used on decoded text lines
[width="50%",cols="h,3*^",frame=topbot,options="header"]
|===========================================
|Mode |Mode character|Sync character|End of line information
|FT8 | ~ | | ? &#160; aP
|JT4 | $ | *, # | f, fN, dNC
|JT9 | @ | |
|JT65 | # | |
|JT65 VHF| # | *, # | f, fN, dNC
|QRA64 | : | * | R
|ISCAT | | * | M N C T
|MSK144 | & | | N
|===========================================
Sync character::
`*` - Normal sync +
`#` - Alternate sync
End of line information::
`?` - Decoded with lower confidence +
`a` - Decoded with aid of some a priori (AP) information +
`C` - Confidence indicator [ISCAT and Deep Search; (0-9,*)] +
`d` - Deep Search algorithm +
`f` - Franke-Taylor or Fano algorithm +
`M` - Message length (characters) +
`N` - Number of Rx intervals or frames averaged +
`P` - Number indicating type of AP information (Table 1, above) +
`R` - Return code from QRA64 decoder +
`T` - Length of analyzed region (s)
@@ -1,240 +0,0 @@
#include "TransceiverBase.hpp"
#include <exception>
#include <QString>
#include <QTimer>
#include <QThread>
#include <QDebug>
#include "moc_TransceiverBase.cpp"
namespace
{
auto const unexpected = TransceiverBase::tr ("Unexpected rig error");
}
void TransceiverBase::start (unsigned sequence_number) noexcept
{
QString message;
try
{
may_update u {this, true};
shutdown ();
startup ();
last_sequence_number_ = sequence_number;
}
catch (std::exception const& e)
{
message = e.what ();
}
catch (...)
{
message = unexpected;
}
if (!message.isEmpty ())
{
offline (message);
}
}
void TransceiverBase::set (TransceiverState const& s,
unsigned sequence_number) noexcept
{
TRACE_CAT ("TransceiverBase", "#:" << sequence_number << s);
QString message;
try
{
may_update u {this, true};
bool was_online {requested_.online ()};
if (!s.online () && was_online)
{
shutdown ();
}
else if (s.online () && !was_online)
{
shutdown ();
startup ();
}
if (requested_.online ())
{
bool ptt_on {false};
bool ptt_off {false};
if (s.ptt () != requested_.ptt ())
{
ptt_on = s.ptt ();
ptt_off = !s.ptt ();
}
if (ptt_off)
{
do_ptt (false);
do_post_ptt (false);
QThread::msleep (100); // some rigs cannot process CAT
// commands while switching from
// Tx to Rx
}
if (s.frequency () // ignore bogus zero frequencies
&& ((s.frequency () != requested_.frequency () // and QSY
|| (s.mode () != UNK && s.mode () != requested_.mode ())) // or mode change
|| ptt_off)) // or just returned to rx
{
do_frequency (s.frequency (), s.mode (), ptt_off);
do_post_frequency (s.frequency (), s.mode ());
// record what actually changed
requested_.frequency (actual_.frequency ());
requested_.mode (actual_.mode ());
}
if (!s.tx_frequency () || s.tx_frequency () > 10000) // ignore bogus startup values
{
if ((s.tx_frequency () != requested_.tx_frequency () // and QSY
|| (s.mode () != UNK && s.mode () != requested_.mode ())) // or mode change
// || s.split () != requested_.split ())) // or split change
|| (s.tx_frequency () && ptt_on)) // or about to tx split
{
do_tx_frequency (s.tx_frequency (), s.mode (), ptt_on);
do_post_tx_frequency (s.tx_frequency (), s.mode ());
// record what actually changed
requested_.tx_frequency (actual_.tx_frequency ());
requested_.split (actual_.split ());
}
}
if (ptt_on)
{
do_ptt (true);
do_post_ptt (true);
QThread::msleep (100); // some rigs cannot process CAT
// commands while switching from
// Rx to Tx
}
// record what actually changed
requested_.ptt (actual_.ptt ());
}
last_sequence_number_ = sequence_number;
}
catch (std::exception const& e)
{
message = e.what ();
}
catch (...)
{
message = unexpected;
}
if (!message.isEmpty ())
{
offline (message);
}
}
void TransceiverBase::startup ()
{
Q_EMIT resolution (do_start ());
do_post_start ();
actual_.online (true);
requested_.online (true);
}
void TransceiverBase::shutdown ()
{
may_update u {this};
if (requested_.online ())
{
try
{
// try and ensure PTT isn't left set
do_ptt (false);
do_post_ptt (false);
if (requested_.split ())
{
// try and reset split mode
do_tx_frequency (0, UNK, true);
do_post_tx_frequency (0, UNK);
}
}
catch (...)
{
// don't care about exceptions
}
}
do_stop ();
do_post_stop ();
actual_.online (false);
requested_.online (false);
}
void TransceiverBase::stop () noexcept
{
QString message;
try
{
shutdown ();
}
catch (std::exception const& e)
{
message = e.what ();
}
catch (...)
{
message = unexpected;
}
if (!message.isEmpty ())
{
offline (message);
}
else
{
Q_EMIT finished ();
}
}
void TransceiverBase::update_rx_frequency (Frequency rx)
{
actual_.frequency (rx);
requested_.frequency (rx); // track rig changes
}
void TransceiverBase::update_other_frequency (Frequency tx)
{
actual_.tx_frequency (tx);
}
void TransceiverBase::update_split (bool state)
{
actual_.split (state);
}
void TransceiverBase::update_mode (MODE m)
{
actual_.mode (m);
requested_.mode (m); // track rig changes
}
void TransceiverBase::update_PTT (bool state)
{
actual_.ptt (state);
}
void TransceiverBase::update_complete (bool force_signal)
{
if ((do_pre_update () && actual_ != last_) || force_signal)
{
Q_EMIT update (actual_, last_sequence_number_);
last_ = actual_;
}
}
void TransceiverBase::offline (QString const& reason)
{
Q_EMIT failure (reason);
try
{
shutdown ();
}
catch (...)
{
// don't care
}
}
@@ -0,0 +1,200 @@
#ifndef TRANSCEIVER_FACTORY_HPP__
#define TRANSCEIVER_FACTORY_HPP__
#include <memory>
#include <QObject>
#include <QMap>
#include "Transceiver.hpp"
#include "qt_helpers.hpp"
class QString;
class QThread;
class QDir;
//
// Transceiver Factory
//
class TransceiverFactory
: public QObject
{
Q_OBJECT
Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode)
public:
//
// Capabilities of a Transceiver that can be determined without
// actually instantiating one, these are for use in Configuration
// GUI behaviour determination
//
struct Capabilities
{
enum PortType {none, serial, network, usb};
explicit Capabilities (int model_number = 0
, PortType port_type = none
, bool has_CAT_PTT = false
, bool has_CAT_PTT_mic_data = false
, bool has_CAT_indirect_serial_PTT = false
, bool asynchronous = false)
: model_number_ {model_number}
, port_type_ {port_type}
, has_CAT_PTT_ {has_CAT_PTT}
, has_CAT_PTT_mic_data_ {has_CAT_PTT_mic_data}
, has_CAT_indirect_serial_PTT_ {has_CAT_indirect_serial_PTT}
, asynchronous_ {asynchronous}
{
}
int model_number_;
PortType port_type_;
bool has_CAT_PTT_;
bool has_CAT_PTT_mic_data_;
bool has_CAT_indirect_serial_PTT_; // OmniRig controls RTS/DTR via COM interface
bool asynchronous_;
};
//
// Dictionary of Transceiver types Capabilities
//
typedef QMap<QString, Capabilities> Transceivers;
//
// various Transceiver parameters
//
enum DataBits {seven_data_bits = 7, eight_data_bits, default_data_bits};
Q_ENUM (DataBits)
enum StopBits {one_stop_bit = 1, two_stop_bits, default_stop_bits};
Q_ENUM (StopBits)
enum Handshake {handshake_default, handshake_none, handshake_XonXoff, handshake_hardware};
Q_ENUM (Handshake)
enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS};
Q_ENUM (PTTMethod)
enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear};
Q_ENUM (TXAudioSource)
enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate};
Q_ENUM (SplitMode)
TransceiverFactory ();
~TransceiverFactory ();
static char const * const basic_transceiver_name_; // dummy transceiver is basic model
//
// fetch all supported rigs as a list of name and model id
//
Transceivers const& supported_transceivers () const;
// supported model queries
Capabilities::PortType CAT_port_type (QString const& name) const; // how to talk to CAT
bool has_CAT_PTT (QString const& name) const; // can be keyed via CAT
bool has_CAT_PTT_mic_data (QString const& name) const; // Tx audio port is switchable via CAT
bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example)
bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled
struct ParameterPack
{
QString rig_name; // from supported_transceivers () key
QString serial_port; // serial port device name or empty
QString network_port; // hostname:port or empty
QString usb_port; // [vid[:pid[:vendor[:product]]]]
int baud;
DataBits data_bits;
StopBits stop_bits;
Handshake handshake;
bool force_dtr;
bool dtr_high; // to power interface
bool force_rts;
bool rts_high; // to power interface
PTTMethod ptt_type; // "CAT" | "DTR" | "RTS" | "VOX"
TXAudioSource audio_source; // some rigs allow audio routing
// to Mic/Data connector
SplitMode split_mode; // how to support split TX mode
QString ptt_port; // serial port device name or special
// value "CAT"
int poll_interval; // in seconds for interfaces that
// require polling for state changes
bool operator == (ParameterPack const& rhs) const
{
return rhs.rig_name == rig_name
&& rhs.serial_port == serial_port
&& rhs.network_port == network_port
&& rhs.usb_port == usb_port
&& rhs.baud == baud
&& rhs.data_bits == data_bits
&& rhs.stop_bits == stop_bits
&& rhs.handshake == handshake
&& rhs.force_dtr == force_dtr
&& rhs.dtr_high == dtr_high
&& rhs.force_rts == force_rts
&& rhs.rts_high == rts_high
&& rhs.ptt_type == ptt_type
&& rhs.audio_source == audio_source
&& rhs.split_mode == split_mode
&& rhs.ptt_port == ptt_port
&& rhs.poll_interval == poll_interval
;
}
};
// make a new Transceiver instance
//
// cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake,
// cat_dtr_control, cat_rts_control are only relevant to interfaces
// that are served by Hamlib
//
// PTT port and to some extent ptt_type are independent of interface
// type
//
std::unique_ptr<Transceiver> create (ParameterPack const&, QThread * target_thread = nullptr);
private:
Transceivers transceivers_;
};
inline
bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs)
{
return !(lhs == rhs);
}
//
// boilerplate routines to make enum types useable and debuggable in
// Qt
//
#if QT_VERSION < 0x050500
Q_DECLARE_METATYPE (TransceiverFactory::DataBits);
Q_DECLARE_METATYPE (TransceiverFactory::StopBits);
Q_DECLARE_METATYPE (TransceiverFactory::Handshake);
Q_DECLARE_METATYPE (TransceiverFactory::PTTMethod);
Q_DECLARE_METATYPE (TransceiverFactory::TXAudioSource);
Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
#endif
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode);
#endif
@@ -1,133 +0,0 @@
program msk144d2
! Test the msk144 decoder for WSJT-X
use options
use timer_module, only: timer
use timer_impl, only: init_timer
use readwav
character c
character*80 line
character*500 infile
character*12 mycall,hiscall
character*6 mygrid
character(len=500) optarg
logical :: display_help=.false.
logical*1 bShMsgs
logical*1 bcontest
logical*1 brxequal
logical*1 bswl
type(wav_header) :: wav
integer*2 id2(30*12000)
integer*2 ichunk(7*1024)
type (option) :: long_options(9) = [ &
option ('ndepth',.true.,'c','ndepth',''), &
option ('dxcall',.true.,'d','hiscall',''), &
option ('evemode',.true.,'e','Must be used with -s.',''), &
option ('frequency',.true.,'f','rxfreq',''), &
option ('help',.false.,'h','Display this help message',''), &
option ('mycall',.true.,'m','mycall',''), &
option ('nftol',.true.,'n','nftol',''), &
option ('rxequalize',.false.,'r','Rx Equalize',''), &
option ('short',.false.,'s','enable Sh','') &
]
t0=0.0
ndepth=3
ntol=100
nrxfreq=1500
mycall=''
mygrid='EN50WC'
hiscall=''
bShMsgs=.false.
bcontest=.false.
brxequal=.false.
bswl=.false.
do
call getopt('c:d:ef:hm:n:rs',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.)
if( nstat .ne. 0 ) then
exit
end if
select case (c)
case ('c')
read (optarg(:narglen), *) ndepth
case ('d')
read (optarg(:narglen), *) hiscall
case ('e')
bswl=.true.
case ('f')
read (optarg(:narglen), *) nrxfreq
case ('h')
display_help = .true.
case ('m')
read (optarg(:narglen), *) mycall
case ('n')
read (optarg(:narglen), *) ntol
case ('r')
brxequal=.true.
case ('s')
bShMsgs=.true.
end select
end do
if(display_help .or. nstat.lt.0 .or. nremain.lt.1) then
print *, ''
print *, 'Usage: msk144d [OPTIONS] file1 [file2 ...]'
print *, ''
print *, ' msk144 decode pre-recorded .WAV file(s)'
print *, ''
print *, 'OPTIONS:'
do i = 1, size (long_options)
call long_options(i) % print (6)
end do
go to 999
endif
call init_timer ('timer.out')
call timer('msk144 ',0)
ndecoded=0
do ifile=noffset+1,noffset+nremain
call get_command_argument(ifile,optarg,narglen)
infile=optarg(:narglen)
call timer('read ',0)
call wav%read (infile)
i1=index(infile,'.wav')
if( i1 .eq. 0 ) i1=index(infile,'.WAV')
read(infile(i1-6:i1-1),*,err=998) nutc
inquire(FILE=infile,SIZE=isize)
npts=min((isize-216)/2,360000)
read(unit=wav%lun) id2(1:npts)
close(unit=wav%lun)
call timer('read ',1)
do i=1,npts-7*1024+1,7*512
ichunk=id2(i:i+7*1024-1)
tsec=(i-1)/12000.0
tt=sum(float(abs(id2(i:i+7*512-1))))
if( tt .ne. 0.0 ) then
call mskrtd(ichunk,nutc,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall,bShMsgs, &
bcontest,brxequal,bswl,line)
if( index(line,"&") .ne. 0 .or. &
index(line,"^") .ne. 0 .or. &
index(line,"!") .ne. 0 .or. &
index(line,"@") .ne. 0 ) then
write(*,*) line
endif
endif
enddo
enddo
call timer('msk144 ',1)
call timer('msk144 ',101)
go to 999
998 print*,'Cannot read from file:'
print*,infile
999 continue
end program msk144d2
@@ -0,0 +1,56 @@
=== New in Version 1.9
For quick reference, here's a short list of features and capabilities
added to _WSJT-X_ since Version 1.8.0:
- New *FT8 DXpedition Mode* to facilitate high QSO rates in pileup
situations
- Decoding improvements for JT65 mode, including _a priori_ (AP)
decoding when VHF/UHF/Microwave features are enabled
- Optional Auto-Sequencing in JT4, JT9, and JT65 when VHF/UHF/Microwave features are enabled
- Better suppression of low-confidence false decodes generated by AP
decoding in FT8 mode
- Improved decoding performance for WSPR mode, especially effective at LF and MF
- Minor adjustments to auto-sequencing behavior
- More flexible Doppler control features for EME
- Improved waterfall sensitivity for very weak signals
- Automatic real-time forwarding of logged information to _N1MM Logger+_
- Expanded and improved UDP messages sent to companion programs
- Bug fixes and other minor tweaks to user interface
=== Documentation Conventions
In this manual the following icons call attention to particular types
of information:
NOTE: *Notes* containing information that may be of interest to
particuar classes of users.
TIP: *Tips* on program features or capabilities that might otherwise be
overlooked.
IMPORTANT: *Warnings* about usage that could lead to undesired
consequences.
=== How You Can Contribute
_WSJT-X_ is part of an open-source project released under the
{gnu_gpl} (GPL). If you have programming or documentation skills or
would like to contribute to the project in other ways, please make
your interests known to the development team. The project's
source-code repository can be found at {devsvn}, and most
communication among the developers takes place on the email reflector
{devmail}. Bug reports and suggestions for new features, improvements
to the _WSJT-X_ User Guide, etc., may also be sent to the
{wsjt_yahoo_group} email reflector. You must join the relevant group
before posting to either email list.
@@ -0,0 +1,27 @@
Type 1 Prefixes:
1A 1S 3A 3B6 3B8 3B9 3C 3C0 3D2 3D2C 3D2R 3DA 3V 3W 3X
3Y 3YB 3YP 4J 4L 4S 4U1I 4U1U 4W 4X 5A 5B 5H 5N 5R
5T 5U 5V 5W 5X 5Z 6W 6Y 7O 7P 7Q 7X 8P 8Q 8R
9A 9G 9H 9J 9K 9L 9M2 9M6 9N 9Q 9U 9V 9X 9Y A2
A3 A4 A5 A6 A7 A9 AP BS7 BV BV9 BY C2 C3 C5 C6
C9 CE CE0X CE0Y CE0Z CE9 CM CN CP CT CT3 CU CX CY0 CY9
D2 D4 D6 DL DU E3 E4 EA EA6 EA8 EA9 EI EK EL EP
ER ES ET EU EX EY EZ F FG FH FJ FK FKC FM FO
FOA FOC FOM FP FR FRG FRJ FRT FT5W FT5X FT5Z FW FY M MD
MI MJ MM MU MW H4 H40 HA HB HB0 HC HC8 HH HI HK
HK0A HK0M HL HM HP HR HS HV HZ I IS IS0 J2 J3 J5
J6 J7 J8 JA JDM JDO JT JW JX JY K KG4 KH0 KH1 KH2
KH3 KH4 KH5 KH5K KH6 KH7 KH8 KH9 KL KP1 KP2 KP4 KP5 LA LU
LX LY LZ OA OD OE OH OH0 OJ0 OK OM ON OX OY OZ
P2 P4 PA PJ2 PJ7 PY PY0F PT0S PY0T PZ R1F R1M S0 S2 S5
S7 S9 SM SP ST SU SV SVA SV5 SV9 T2 T30 T31 T32 T33
T5 T7 T8 T9 TA TF TG TI TI9 TJ TK TL TN TR TT
TU TY TZ UA UA2 UA9 UK UN UR V2 V3 V4 V5 V6 V7
V8 VE VK VK0H VK0M VK9C VK9L VK9M VK9N VK9W VK9X VP2E VP2M VP2V VP5
VP6 VP6D VP8 VP8G VP8H VP8O VP8S VP9 VQ9 VR VU VU4 VU7 XE XF4
XT XU XW XX9 XZ YA YB YI YJ YK YL YN YO YS YU
YV YV0 Z2 Z3 ZA ZB ZC4 ZD7 ZD8 ZD9 ZF ZK1N ZK1S ZK2 ZK3
ZL ZL7 ZL8 ZL9 ZP ZS ZS8 KC4 E5
Type 1 Suffixes: /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /P