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,86 +0,0 @@
/* RAND-SRC.C - Generate random message bits. */
/* Copyright (c) 1995-2012 by Radford M. Neal.
*
* Permission is granted for anyone to copy, use, modify, and distribute
* these programs and accompanying documents for any purpose, provided
* this copyright notice is retained and prominently displayed, and note
* is made of any changes made to these programs. These programs and
* documents are distributed without any warranty, express or implied.
* As the programs were written for research purposes only, they have not
* been tested to the degree that would be advisable in any important
* application. All use of these programs is entirely at the user's own
* risk.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "open.h"
#include "rand.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
int seed, bs, nb;
char *file, *n_bits;
char junk;
int i, j;
FILE *f;
if (!(file = argv[1])
|| !argv[2] || sscanf(argv[2],"%d%c",&seed,&junk)!=1
|| !(n_bits = argv[3])
|| argv[4])
{ usage();
}
if (sscanf(n_bits,"%d%c",&nb,&junk)==1)
{ if (nb<=0) usage();
bs = 1;
}
else if (sscanf(n_bits,"%dx%d%c",&bs,&nb,&junk)==2)
{ if (nb<=0 || bs<=0) usage();
}
else
{ usage();
}
f = open_file_std(file,"w");
if (f==NULL)
{ fprintf(stderr,"Can't create source file: %s\n",file);
exit(1);
}
rand_seed(10*seed+2);
for (i = 0; i<nb; i++)
{ for (j = 0; j<bs; j++)
{ fprintf(f,"%d",rand_int(2));
}
fprintf(f,"\n");
}
if (ferror(f) || fclose(f)!=0)
{ fprintf(stderr,"Error writing random source blocks to %s\n",file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage: rand-src source-file seed n-bits\n");
exit(1);
}
@@ -1,337 +0,0 @@
[[PROTOCOL_OVERVIEW]]
=== Overview
All QSO modes except ISCAT use structured messages that compress
user-readable information into fixed-length packets of 72 bits. Each
message consists of two 28-bit fields normally used for callsigns and
a 15-bit field for a grid locator, report, acknowledgment, or 73. An
additional bit flags a message containing arbitrary alphanumeric text,
up to 13 characters. Special cases allow other information such as
add-on callsign prefixes (e.g., ZA/K1ABC) or suffixes (e.g., K1ABC/P)
to be encoded. The basic aim is to compress the most common messages
used for minimally valid QSOs into a fixed 72-bit length. Information
payloads in FT8 include 3 additional bits (75 bits total), with
definitions yet to be defined.
A standard amateur callsign consists of a one- or two-character
prefix, at least one of which must be a letter, followed by a digit
and a suffix of one to three letters. Within these rules, the number
of possible callsigns is equal to 37×36×10×27×27×27, or somewhat over
262 million. (The numbers 27 and 37 arise because in the first and
last three positions a character may be absent, or a letter, or
perhaps a digit.) Since 2^28^ is more than 268 million, 28 bits are
enough to encode any standard callsign uniquely. Similarly, the number
of 4-digit Maidenhead grid locators on earth is 180×180 = 32,400,
which is less than 2^15^ = 32,768; so a grid locator requires 15 bits.
Some 6 million of the possible 28-bit values are not needed for
callsigns. A few of these slots have been assigned to special message
components such as `CQ`, `DE`, and `QRZ`. `CQ` may be followed by three
digits to indicate a desired callback frequency. (If K1ABC transmits
on a standard calling frequency, say 50.280, and sends `CQ 290 K1ABC
FN42`, it means that s/he will listen on 50.290 and respond there to
any replies.) A numerical signal report of the form `nn` or
`Rnn` can be sent in place of a grid locator. (As originally
defined, numerical signal reports `nn` were required to fall between -01
and -30 dB. Recent program versions accommodate reports between
-50 and +49 dB.) A country prefix or portable suffix may be
attached to one of the callsigns. When this feature is used the
additional information is sent in place of the grid locator or by
encoding additional information into some of the 6 million available
slots mentioned above.
As a convenience for sending directed CQ messages, the compression
algorithm supports messages starting with `CQ AA` through `CQ ZZ`.
These message fragments are encoded internally as if they were the
callsigns `E9AA` through `E9ZZ`. Upon reception they are converted
back to the form `CQ AA` through `CQ ZZ`, for display to the user.
The FT8 and MSK144 modes support a special feature allowing convenient
transmission and acknowledgment of four-character grid locators, the
required exchanges in most North American VHF contests. With this
Contest Mode enabled, _WSJT-X_ supports messages of the form `W9XYZ
K1ABC R FN42` by converting the grid locator to that of its
diametrically opposite point on Earth. The receiving program
recognizes a locator implying a distance greater than 10,000 km, does
the reverse transformation, and inserts the implied "`R`". Obviously,
this mode should not be used on the HF bands or under other
circumstances where world-wide propagation is possible.
To be useful on channels with low signal-to-noise ratio, this kind of
lossless message compression requires use of a strong forward error
correcting (FEC) code. Different codes are used for each mode.
Accurate synchronization of time and frequency is required between
transmitting and receiving stations. As an aid to the decoders, each
protocol includes a "`sync vector`" of known symbols interspersed with
the information-carrying symbols. Generated waveforms for all of the
_WSJT-X_ modes have continuous phase and constant envelope.
[[SLOW_MODES]]
=== Slow Modes
[[FT8PRO]]
==== FT8
Forward error correction (FEC) in FT8 uses a low-density parity check
(LDPC) code with 75 information bits, a 12-bit cyclic redundancy check
(CRC), and 87 parity bits making a 174-bit codeword. It is thus
called an LDPC (174,87) code. Synchronization uses 7×7 Costas arrays
at the beginning, middle, and end of each transmission. Modulation is
8-tone frequency-shift keying (8-FSK) at 12000/1920 = 6.25 baud. Each
transmitted symbol carries three bits, so the total number of channel
symbols is 174/3 + 21 = 79. The total occupied bandwidth is 8 × 6.25
= 50 Hz.
[[JT4PRO]]
==== JT4
FEC in JT4 uses a strong convolutional code with constraint length
K=32, rate r=1/2, and a zero tail. This choice leads to an encoded
message length of (72+31) x 2 = 206 information-carrying bits.
Modulation is 4-tone frequency-shift keying (4-FSK) at 11025 / 2520 =
4.375 baud. Each symbol carries one information bit (the most
significant bit) and one synchronizing bit. The two 32-bit
polynomials used for convolutional encoding have hexadecimal values
0xf2d05351 and 0xe4613c47, and the ordering of encoded bits is
scrambled by an interleaver. The pseudo-random sync vector is the
following sequence (60 bits per line):
000011000110110010100000001100000000000010110110101111101000
100100111110001010001111011001000110101010101111101010110101
011100101101111000011011000111011101110010001101100100011111
10011000011000101101111010
[[JT9PRO]]
==== JT9
FEC in JT9 uses the same strong convolutional code as JT4: constraint
length K=32, rate r=1/2, and a zero tail, leading to an encoded
message length of (72+31) × 2 = 206 information-carrying
bits. Modulation is nine-tone frequency-shift keying, 9-FSK at
12000.0/6912 = 1.736 baud. Eight tones are used for data, one for
synchronization. Eight data tones means that three data bits are
conveyed by each transmitted information symbol. Sixteen symbol
intervals are devoted to synchronization, so a transmission requires a
total of 206 / 3 + 16 = 85 (rounded up) channel symbols. The sync
symbols are those numbered 1, 2, 5, 10, 16, 23, 33, 35, 51, 52, 55,
60, 66, 73, 83, and 85 in the transmitted sequence. Tone spacing of
the 9-FSK modulation for JT9A is equal to the keying rate, 1.736 Hz.
The total occupied bandwidth is 9 × 1.736 = 15.6 Hz.
[[JT65PRO]]
==== JT65
A detailed description of the JT65 protocol was published in
{jt65protocol} for September-October, 2005. A Reed Solomon (63,12)
error-control code converts 72-bit user messages into sequences of 63
six-bit information-carrying symbols. These are interleaved with
another 63 symbols of synchronizing information according to the
following pseudo-random sequence:
100110001111110101000101100100011100111101101111000110101011001
101010100100000011000000011010010110101010011001001000011111111
The synchronizing tone is normally sent in each interval having a
"`1`" in the sequence. Modulation is 65-FSK at 11025/4096 = 2.692
baud. Frequency spacing between tones is equal to the keying rate for
JT65A, and 2 and 4 times larger for JT65B and JT65C. For EME QSOs the
signal report OOO is sometimes used instead of numerical signal
reports. It is conveyed by reversing sync and data positions in the
transmitted sequence. Shorthand messages for RO, RRR, and 73 dispense
with the sync vector entirely and use time intervals of 16384/11025 =
1.486 s for pairs of alternating tones. The lower frequency is the
same as that of the sync tone used in long messages, and the frequency
separation is 110250/4096 = 26.92 Hz multiplied by n for JT65A, with n
= 2, 3, 4 used to convey the messages RO, RRR, and 73.
[[QRA64_PROTOCOL]]
==== QRA64
QRA64 is intended for EME and other extreme weak-signal applications.
Its internal code was designed by IV3NWV. The protocol uses a (63,12)
**Q**-ary **R**epeat **A**ccumulate code that is inherently better
than the Reed Solomon (63,12) code used in JT65, yielding a 1.3 dB
advantage. A new synchronizing scheme is based on three 7 x 7 Costas
arrays. This change yields another 1.9 dB advantage.
In most respects the current implementation of QRA64 is operationally
similar to JT65. QRA64 does not use two-tone shorthand messages, and
it makes no use of a callsign database. Rather, additional
sensitivity is gained by making use of already known information as a
QSO progresses -- for example, when reports are being exchanged and
you have already decoded both callsigns in a previous transmission.
QRA64 presently offers no message averaging capability, though that
feature may be added. In early tests, many EME QSOs were made using
submodes QRA64A-E on bands from 144 MHz to 24 GHz.
[[SLOW_SUMMARY]]
==== Summary
Table 2 provides a brief summary parameters for the slow modes in
_WSJT-X_. Parameters K and r specify the constraint length and rate
of the convolutional codes; n and k specify the sizes of the
(equivalent) block codes; Q is the alphabet size for the
information-carrying channel symbols; Sync Energy is the fraction of
transmitted energy devoted to synchronizing symbols; and S/N Threshold
is the signal-to-noise ratio (in a 2500 Hz reference bandwidth) above
which the probability of decoding is 50% or higher.
[[SLOW_TAB]]
.Parameters of Slow Modes
[width="90%",cols="3h,^3,^2,^1,^2,^2,^2,^2,^2,^2",frame=topbot,options="header"]
|===============================================================================
|Mode |FEC Type |(n,k) | Q|Modulation type|Keying rate (Baud)|Bandwidth (Hz)
|Sync Energy|Tx Duration (s)|S/N Threshold (dB)
|FT8 |LDPC, r=1/2|(174,87)| 8| 8-FSK| 6.25 | 50.0 | 0.27| 12.6 | -21
|JT4A |K=32, r=1/2|(206,72)| 2| 4-FSK| 4.375| 17.5 | 0.50| 47.1 | -23
|JT9A |K=32, r=1/2|(206,72)| 8| 9-FSK| 1.736| 15.6 | 0.19| 49.0 | -27
|JT65A |Reed Solomon|(63,12) |64|65-FSK| 2.692| 177.6 | 0.50| 46.8 | -25
|QRA64A|Q-ary Repeat Accumulate|(63,12) |64|64-FSK|1.736|111.1|0.25|48.4| -26
| WSPR |K=32, r=1/2|(162,50)| 2| 4-FSK| 1.465| 5.9 | 0.50|110.6 | -28
|===============================================================================
Submodes of JT4, JT9, JT65, and QRA64 offer wider tone spacings for
circumstances that may require them, such significant Doppler spread.
Table 3 summarizes the tone spacings, bandwidths, and approximate
threshold sensitivities of the various submodes when spreading is
comparable to tone spacing.
[[SLOW_SUBMODES]]
.Parameters of Slow Submodes
[width="50%",cols="h,3*^",frame=topbot,options="header"]
|=====================================
|Mode |Tone Spacing |BW (Hz)|S/N (dB)
|FT8 |6.25 | 50.0 |-21
|JT4A |4.375| 17.5 |-23
|JT4B |8.75 | 30.6 |-22
|JT4C |17.5 | 56.9 |-21
|JT4D |39.375| 122.5 |-20
|JT4E |78.75| 240.6 |-19
|JT4F |157.5| 476.9 |-18
|JT4G |315.0| 949.4 |-17
|JT9A |1.736| 15.6 |-27
|JT9B |3.472| 29.5 |-26
|JT9C |6.944| 57.3 |-25
|JT9D |13.889| 112.8 |-24
|JT9E |27.778| 224.0 |-23
|JT9F |55.556| 446.2 |-22
|JT9G |111.111|890.6 |-21
|JT9H |222.222|1779.5|-20
|JT65A |2.692| 177.6 |-25
|JT65B |5.383| 352.6 |-25
|JT65C |10.767| 702.5 |-25
|QRA64A|1.736| 111.1 |-26
|QRA64B|3.472| 220.5 |-25
|QRA64C|6.944| 439.2 |-24
|QRA64D|13.889| 876.7 |-23
|QRA64E|27.778|1751.7 |-22
|=====================================
[[FAST_MODES]]
=== Fast Modes
==== ISCAT
ISCAT messages are free-form, up to 28 characters in length.
Modulation is 42-tone frequency-shift keying at 11025 / 512 = 21.533
baud (ISCAT-A), or 11025 / 256 = 43.066 baud (ISCAT-B). Tone
frequencies are spaced by an amount in Hz equal to the baud rate. The
available character set is:
----
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /.?@-
----
Transmissions consist of sequences of 24 symbols: a synchronizing
pattern of four symbols at tone numbers 0, 1, 3, and 2, followed by
two symbols with tone number corresponding to (message length) and
(message length + 5), and finally 18 symbols conveying the user's
message, sent repeatedly character by character. The message always
starts with `@`, the beginning-of-message symbol, which is not
displayed to the user. The sync pattern and message-length indicator
have a fixed repetition period, recurring every 24 symbols. Message
information occurs periodically within the 18 symbol positions set
aside for its use, repeating at its own natural length.
For example, consider the user message `CQ WA9XYZ`. Including the
beginning-of-message symbol `@`, the message is 10 characters long.
Using the character sequence displayed above to indicate tone numbers,
the transmitted message will therefore start out as shown in the first
line below:
----
0132AF@CQ WA9XYZ@CQ WA9X0132AFYZ@CQ WA9XYZ@CQ W0132AFA9X ...
sync## sync## sync##
----
Note that the first six symbols (four for sync, two for message
length) repeat every 24 symbols. Within the 18 information-carrying
symbols in each 24, the user message `@CQ WA9XYZ` repeats at its own
natural length, 10 characters. The resulting sequence is extended as
many times as will fit into a Tx sequence.
==== JT9
The JT9 slow modes all use keying rate 12000/6912 = 1.736 baud. By contrast, with
the *Fast* setting submodes JT9E-H adjust the keying rate to match the
increased tone spacings. Message durations are therefore much
shorter, and they are sent repeatedly throughout each Tx sequence.
For details see Table 4, below.
==== MSK144
Standard MSK144 messages are structured in the same way as those in
the slow modes, with 72 bits of user information. Forward error
correction is implemented by first augmenting the 72 message bits with
an 8-bit cyclic redundancy check (CRC) calculated from the message
bits. The CRC is used to detect and eliminate most false decodes at
the receiver. The resulting 80-bit augmented message is mapped to a
128-bit codeword using a (128,80) binary low-density-parity-check
(LDPC) code designed by K9AN specifically for this purpose. Two 8-bit
synchronizing sequences are added to make a message frame 144 bits
long. Modulation is Offset Quadrature Phase-Shift Keying (OQPSK) at
2000 baud. Even-numbered bits are conveyed over the in-phase channel,
odd-numbered bits on the quadrature channel. Individual symbols are
shaped with half-sine profiles, thereby ensuring a generated waveform
with constant envelope, equivalent to a Minimum Shift Keying (MSK)
waveform. Frame duration is 72 ms, so the effective character
transmission rate for standard messages is up to 250 cps.
MSK144 also supports short-form messages that can be used after QSO
partners have exchanged both callsigns. Short messages consist of 4
bits encoding R+report, RRR, or 73, together with a 12-bit hash code
based on the ordered pair of "`to`" and "`from`" callsigns. Another
specially designed LDPC (32,16) code provides error correction, and an
8-bit synchronizing vector is appended to make up a 40-bit frame.
Short-message duration is thus 20 ms, and short messages can be
decoded from very short meteor pings.
The 72 ms or 20 ms frames of MSK144 messages are repeated without gaps
for the full duration of a transmission cycle. For most purposes, a
cycle duration of 15 s is suitable and recommended for MSK144.
The modulated MSK144 signal occupies the full bandwidth of a SSB
transmitter, so transmissions are always centered at audio frequency
1500 Hz. For best results, transmitter and receiver filters should be
adjusted to provide the flattest possible response over the range
300Hz to 2700Hz. The maximum permissible frequency offset between you
and your QSO partner ± 200 Hz.
==== Summary
.Parameters of Fast Modes
[width="90%",cols="3h,^3,^2,^1,^2,^2,^2,^2,^2",frame="topbot",options="header"]
|=====================================================================
|Mode |FEC Type |(n,k) | Q|Modulation Type|Keying rate (Baud)
|Bandwidth (Hz)|Sync Energy|Tx Duration (s)
|ISCAT-A | - | - |42|42-FSK| 21.5 | 905 | 0.17| 1.176
|ISCAT-B | - | - |42|42-FSK| 43.1 | 1809 | 0.17| 0.588
|JT9E |K=32, r=1/2|(206,72)| 8| 9-FSK| 25.0 | 225 | 0.19| 3.400
|JT9F |K=32, r=1/2|(206,72)| 8| 9-FSK| 50.0 | 450 | 0.19| 1.700
|JT9G |K=32, r=1/2|(206,72)| 8| 9-FSK|100.0 | 900 | 0.19| 0.850
|JT9H |K=32, r=1/2|(206,72)| 8| 9-FSK|200.0 | 1800 | 0.19| 0.425
|MSK144 |LDPC |(128,80)| 2| OQPSK| 2000 | 2400 | 0.11| 0.072
|MSK144 Sh|LDPC |(32,16) | 2| OQPSK| 2000 | 2400 | 0.20| 0.020
|=====================================================================
@@ -0,0 +1,143 @@
program jt65
! Test the JT65 decoder for WSJT-X
use options
use timer_module, only: timer
use timer_impl, only: init_timer
use jt65_test
use readwav
character c,mode
logical :: display_help=.false.,nrobust=.false.,single_decode=.false., ljt65apon=.false.
type(wav_header) :: wav
integer*2 id2(NZMAX)
real*4 dd(NZMAX)
character*80 infile
character(len=500) optarg
character*12 mycall,hiscall
character*6 hisgrid
type (option) :: long_options(12) = [ &
option ('aggressive',.true.,'a','aggressiveness [0-10], default AGGR=0','AGGR'), &
option ('depth',.true.,'d','depth=5 hinted decoding, default DEPTH=0','DEPTH'), &
option ('freq',.true.,'f','signal frequency, default FREQ=1270','FREQ'), &
option ('help',.false.,'h','Display this help message',''), &
option ('mode',.true.,'m','Mode A, B, C. Default is A.','MODE'), &
option ('ntrials',.true.,'n','number of trials, default TRIALS=10000','TRIALS'), &
option ('robust-sync',.false.,'r','robust sync',''), &
option ('my-call',.true.,'c','my callsign',''), &
option ('his-call',.true.,'x','his callsign',''), &
option ('his-grid',.true.,'g','his grid locator',''), &
option ('experience-decoding',.true.,'X' &
,'experience decoding options (1..n), default FLAGS=0','FLAGS'), &
option ('single-signal-mode',.false.,'s','decode at signal frequency only','') ]
naggressive=10
nfqso=1500
ntrials=100000
nexp_decode=0
ntol=20
nsubmode=0
nlow=200
nhigh=4000
n2pass=1
ndepth=1
nQSOProgress=6
do
call getopt('a:d:f:hm:n:rc:x:g:X:s',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.)
if( nstat .ne. 0 ) then
exit
end if
select case (c)
case ('a')
read (optarg(:narglen), *) naggressive
case ('d')
read (optarg(:narglen), *) ndepth
case ('f')
read (optarg(:narglen), *) nfqso
case ('h')
display_help = .true.
case ('m')
read (optarg(:narglen), *) mode
if( mode .eq. 'b' .or. mode .eq. 'B' ) then
nsubmode=1
endif
if( mode .eq. 'c' .or. mode .eq. 'C' ) then
nsubmode=2
endif
case ('n')
read (optarg(:narglen), *) ntrials
case ('r')
nrobust=.true.
case ('c')
read (optarg(:narglen), *) mycall
case ('x')
read (optarg(:narglen), *) hiscall
case ('g')
read (optarg(:narglen), *) hisgrid
case ('X')
read (optarg(:narglen), *) nexp_decode
case ('s')
single_decode=.true.
ntol=100
nlow=nfqso-ntol
nhigh=nfqso+ntol
n2pass=1
end select
end do
if(single_decode) nexp_decode=ior(nexp_decode,32)
if(display_help .or. nstat.lt.0 .or. nremain.lt.1) then
print *, ''
print *, 'Usage: jt65 [OPTIONS] file1 [file2 ...]'
print *, ''
print *, ' JT65 decode pre-recorded .WAV file(s)'
print *, ''
print *, 'OPTIONS:'
print *, ''
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('jt65 ',0)
ndecoded=0
do ifile=noffset+1,noffset+nremain
nfa=nlow
nfb=nhigh
minsync=0
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-4:i1-1),*,err=998) nutc
npts=52*12000
read(unit=wav%lun) id2(1:npts)
close(unit=wav%lun)
call timer('read ',1)
dd(1:npts)=id2(1:npts)
dd(npts+1:)=0.
call test(dd,nutc,nfa,nfb,nfqso,ntol,nsubmode, &
n2pass,nrobust,ntrials,naggressive,ndepth, &
mycall,hiscall,hisgrid,nexp_decode,nQSOProgress,ljt65apon)
! if(nft.gt.0) exit
enddo
call timer('jt65 ',1)
call timer('jt65 ',101)
! call four2a(a,-1,1,1,1) !Free the memory used for plans
! call filbig(a,-1,1,0.0,0,0,0,0,0) ! (ditto)
go to 999
998 print*,'Cannot read from file:'
print*,infile
999 continue
end program jt65
@@ -0,0 +1,483 @@
#ifndef NETWORK_MESSAGE_HPP__
#define NETWORK_MESSAGE_HPP__
/*
* WSJT-X Message Formats
* ======================
*
* All messages are written or read using the QDataStream derivatives
* defined below, note that we are using the default for floating
* point precision which means all are double precision i.e. 64-bit
* IEEE format.
*
* Message is big endian format
*
* Header format:
*
* 32-bit unsigned integer magic number 0xadbccbda
* 32-bit unsigned integer schema number
*
* Payload format:
*
* As per the QDataStream format, see below for version used and
* here:
*
* http://doc.qt.io/qt-5/datastreamformat.html
*
* for the serialization details for each type, at the time of
* writing the above document is for Qt_5_0 format which is buggy
* so we use Qt_5_4 format, differences are:
*
* QDateTime:
* QDate qint64 Julian day number
* QTime quint32 Milli-seconds since midnight
* timespec quint8 0=local, 1=UTC, 2=Offset from UTC
* (seconds)
* 3=time zone
* offset qint32 only present if timespec=2
* timezone several-fields only present if timespec=3
*
* we will avoid using QDateTime fields with time zones for simplicity.
*
* Type utf8 is a utf-8 byte string formatted as a QByteArray for
* serialization purposes (currently a quint32 size followed by size
* bytes, no terminator is present or counted).
*
* The QDataStream format document linked above is not complete for
* the QByteArray serialization format, it is similar to the QString
* serialization format in that it differentiates between empty
* strings and null strings. Empty strings have a length of zero
* whereas null strings have a length field of 0xffffffff.
*
* Schema Negotiation
* ------------------
*
* The NetworkMessage::Builder class specifies a schema number which
* may be incremented from time to time. It represents a version of
* the underlying encoding schemes used to store data items. Since the
* underlying encoding is defined by the Qt project in it's
* QDataStream stream operators, it is essential that clients and
* servers of this protocol can agree on a common scheme. The
* NetworkMessage utility classes below exchange the schema number
* actually used. The handling of the schema is backwards compatible
* to an extent, so long as clients and servers are written
* correctly. For example a server written to any particular schema
* version can communicate with a client written to a later schema.
*
* Schema Version 1:- this schema used the QDataStream::Qt_5_0 version
* which is broken.
*
* Schema Version 2:- this schema uses the QDataStream::Qt_5_2 version.
*
* Schema Version 3:- this schema uses the QDataStream::Qt_5_4 version.
*
*
*
* Message Direction Value Type
* ------------- --------- ---------------------- -----------
* Heartbeat Out/In 0 quint32
* Id (unique key) utf8
* Maximum schema number quint32
* version utf8
* revision utf8
*
* The heartbeat message shall be sent on a periodic basis every
* NetworkMessage::pulse seconds (see below), the WSJT-X
* application does that using the MessageClient class. This
* message is intended to be used by servers to detect the presence
* of a client and also the unexpected disappearance of a client
* and by clients to learn the schema negotiated by the server
* after it receives the initial heartbeat message from a client.
* The message_aggregator reference server does just that using the
* MessageServer class. Upon initial startup a client must send a
* heartbeat message as soon as is practical, this message is used
* to negotiate the maximum schema number common to the client and
* server. Note that the server may not be able to support the
* client's requested maximum schema number, in which case the
* first message received from the server will specify a lower
* schema number (never a higher one as that is not allowed). If a
* server replies with a lower schema number then no higher than
* that number shall be used for all further outgoing messages from
* either clients or the server itself.
*
* Note: the "Maximum schema number" field was introduced at the
* same time as schema 3, therefore servers and clients must assume
* schema 2 is the highest schema number supported if the Heartbeat
* message does not contain the "Maximum schema number" field.
*
*
* Status Out 1 quint32
* Id (unique key) utf8
* Dial Frequency (Hz) quint64
* Mode utf8
* DX call utf8
* Report utf8
* Tx Mode utf8
* Tx Enabled bool
* Transmitting bool
* Decoding bool
* Rx DF qint32
* Tx DF qint32
* DE call utf8
* DE grid utf8
* DX grid utf8
* Tx Watchdog bool
* Sub-mode utf8
* Fast mode bool
*
* WSJT-X sends this status message when various internal state
* changes to allow the server to track the relevant state of each
* client without the need for polling commands. The current state
* changes that generate status messages are:
*
* Application start up,
* "Enable Tx" button status changes,
* Dial frequency changes,
* Changes to the "DX Call" field,
* Operating mode, sub-mode or fast mode changes,
* Transmit mode changed (in dual JT9+JT65 mode),
* Changes to the "Rpt" spinner,
* After an old decodes replay sequence (see Replay below),
* When switching between Tx and Rx mode,
* At the start and end of decoding,
* When the Rx DF changes,
* When the Tx DF changes,
* When the DE call or grid changes (currently when settings are exited),
* When the DX call or grid changes,
* When the Tx watchdog is set or reset.
*
*
* Decode Out 2 quint32
* Id (unique key) utf8
* New bool
* Time QTime
* snr qint32
* Delta time (S) float (serialized as double)
* Delta frequency (Hz) quint32
* Mode utf8
* Message utf8
* Low confidence bool
* Off air bool
*
* The decode message is sent when a new decode is completed, in
* this case the 'New' field is true. It is also used in response
* to a "Replay" message where each old decode in the "Band
* activity" window, that has not been erased, is sent in order
* as a one of these messages with the 'New' field set to false.
* See the "Replay" message below for details of usage. Low
* confidence decodes are flagged in protocols where the decoder
* has knows that a decode has a higher than normal probability
* of being false, they should not be reported on publicly
* accessible services without some attached warning or further
* validation. Off air decodes are those that result from playing
* back a .WAV file.
*
*
* Clear Out 3 quint32
* Id (unique key) utf8
*
* This message is send when all prior "Decode" messages in the
* "Band activity" window have been discarded and therefore are
* no long available for actioning with a "Reply" message. It is
* sent when the user erases the "Band activity" window and when
* WSJT-X closes down normally. The server should discard all
* decode messages upon receipt of this message.
*
*
* Reply In 4 quint32
* Id (target unique key) utf8
* Time QTime
* snr qint32
* Delta time (S) float (serialized as double)
* Delta frequency (Hz) quint32
* Mode utf8
* Message utf8
* Low confidence bool
* Modifiers quint8
*
* In order for a server to provide a useful cooperative service
* to WSJT-X it is possible for it to initiate a QSO by sending
* this message to a client. WSJT-X filters this message and only
* acts upon it if the message exactly describes a prior decode
* and that decode is a CQ or QRZ message. The action taken is
* exactly equivalent to the user double clicking the message in
* the "Band activity" window. The intent of this message is for
* servers to be able to provide an advanced look up of potential
* QSO partners, for example determining if they have been worked
* before or if working them may advance some objective like
* award progress. The intention is not to provide a secondary
* user interface for WSJT-X, it is expected that after QSO
* initiation the rest of the QSO is carried out manually using
* the normal WSJT-X user interface.
*
* The Modifiers field allows the equivalent of keyboard
* modifiers to be sent "as if" those modifier keys where pressed
* while double-clicking the specified decoded message. The
* modifier values (hexadecimal) are as follows:
*
* no modifier 0x00
* SHIFT 0x02
* CTRL 0x04 CMD on Mac
* ALT 0x08
* META 0x10 Windows key on MS Windows
* KEYPAD 0x20 Keypad or arrows
* Group switch 0x40 X11 only
*
*
* QSO Logged Out 5 quint32
* Id (unique key) utf8
* Date & Time Off QDateTime
* DX call utf8
* DX grid utf8
* Tx frequency (Hz) quint64
* Mode utf8
* Report send utf8
* Report received utf8
* Tx power utf8
* Comments utf8
* Name utf8
* Date & Time On QDateTime
* Operator call utf8
* My call utf8
* My grid utf8
*
* The QSO logged message is sent to the server(s) when the
* WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
* button.
*
*
* Close Out 6 quint32
* Id (unique key) utf8
*
* Close is sent by a client immediately prior to it shutting
* down gracefully.
*
*
* Replay In 7 quint32
* Id (unique key) utf8
*
* When a server starts it may be useful for it to determine the
* state of preexisting clients. Sending this message to each
* client as it is discovered will cause that client (WSJT-X) to
* send a "Decode" message for each decode currently in its "Band
* activity" window. Each "Decode" message sent will have the
* "New" flag set to false so that they can be distinguished from
* new decodes. After all the old decodes have been broadcast a
* "Status" message is also broadcast. If the server wishes to
* determine the status of a newly discovered client; this
* message should be used.
*
*
* Halt Tx In 8
* Id (unique key) utf8
* Auto Tx Only bool
*
* The server may stop a client from transmitting messages either
* immediately or at the end of the current transmission period
* using this message.
*
*
* Free Text In 9
* Id (unique key) utf8
* Text utf8
* Send bool
*
* This message allows the server to set the current free text
* message content. Sending this message with a non-empty "Text"
* field is equivalent to typing a new message (old contents are
* discarded) in to the WSJT-X free text message field or "Tx5"
* field (both are updated) and if the "Send" flag is set then
* clicking the "Now" radio button for the "Tx5" field if tab one
* is current or clicking the "Free msg" radio button if tab two
* is current.
*
* It is the responsibility of the sender to limit the length of
* the message text and to limit it to legal message
* characters. Despite this, it may be difficult for the sender
* to determine the maximum message length without reimplementing
* the complete message encoding protocol. Because of this is may
* be better to allow any reasonable message length and to let
* the WSJT-X application encode and possibly truncate the actual
* on-air message.
*
* If the message text is empty the meaning of the message is
* refined to send the current free text unchanged when the
* "Send" flag is set or to clear the current free text when the
* "Send" flag is unset. Note that this API does not include a
* command to determine the contents of the current free text
* message.
*
*
* WSPRDecode Out 10 quint32
* Id (unique key) utf8
* New bool
* Time QTime
* snr qint32
* Delta time (S) float (serialized as double)
* Frequency (Hz) quint64
* Drift (Hz) qint32
* Callsign utf8
* Grid utf8
* Power (dBm) qint32
* Off air bool
*
* The decode message is sent when a new decode is completed, in
* this case the 'New' field is true. It is also used in response
* to a "Replay" message where each old decode in the "Band
* activity" window, that has not been erased, is sent in order
* as a one of these messages with the 'New' field set to
* false. See the "Replay" message below for details of
* usage. The off air field indicates that the decode was decoded
* from a played back recording.
*
*
* Location In 11
* Id (unique key) utf8
* Location utf8
*
* This message allows the server to set the current current
* geographical location of operation. The supplied location is
* not persistent but is used as a session lifetime replacement
* loction that overrides the Maidenhead grid locater set in the
* application settings. The intent is to allow an external
* application to update the operating location dynamically
* during a mobile period of operation.
*
* Currently only Maidenhead grid squares or sub-squares are
* accepted, i.e. 4- or 6-digit locators. Other formats may be
* accepted in future.
*
*
* Logged ADIF Out 12 quint32
* Id (unique key) utf8
* ADIF text utf8
*
* The logged ADIF message is sent to the server(s) when the
* WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
* button. The "ADIF text" field consists of a valid ADIF file
* such that the WSJT-X UDP header information is encapsulated
* into a valid ADIF header. E.g.:
*
* <magic-number><schema-number><type><id><32-bit-count> # binary encoded fields
* # the remainder is the contents of the ADIF text field
* <adif_ver:5>3.0.7
* <programid:6>WSJT-X
* <EOH>
* ADIF log data fields ...<EOR>
*
* Note that receiving applications can treat the whole message
* as a valid ADIF file with one record without special parsing.
*
*
* Highlight Callsign In 13 quint32
* Id (unique key) utf8
* Callsign utf8
* Background Color QColor
* Foreground Color QColor
* Highlight last bool
*
* The server may send this message at any time. The message
* specifies the background and foreground color that will be
* used to highlight the specified callsign in the decoded
* messages printed in the Band Activity panel. The WSJT-X
* clients maintain a list of such instructions and apply them to
* all decoded messages in the band activity window. To clear
* highlighting send an invalid QColor value for either or both
* of the background and foreground fields.
*
* The "Highlight last" field allows the sender to request that
* the last instance only instead of all instances of the
* specified call be highlighted or have it's highlighting
* cleared.
*/
#include <QDataStream>
#include "pimpl_h.hpp"
class QIODevice;
class QByteArray;
class QString;
namespace NetworkMessage
{
// NEVER DELETE MESSAGE TYPES
enum Type
{
Heartbeat,
Status,
Decode,
Clear,
Reply,
QSOLogged,
Close,
Replay,
HaltTx,
FreeText,
WSPRDecode,
Location,
LoggedADIF,
HighlightCallsign,
maximum_message_type_ // ONLY add new message types
// immediately before here
};
quint32 constexpr pulse {15}; // seconds
//
// NetworkMessage::Builder - build a message containing serialized Qt types
//
class Builder
: public QDataStream
{
public:
static quint32 constexpr magic {0xadbccbda}; // never change this
// increment this if a newer Qt schema is required and add decode
// logic to the Builder and Reader class implementations
#if QT_VERSION >= 0x050400
static quint32 constexpr schema_number {3};
#elif QT_VERSION >= 0x050200
static quint32 constexpr schema_number {2};
#else
// Schema 1 (Qt_5_0) is broken
#error "Qt version 5.2 or greater required"
#endif
explicit Builder (QIODevice *, Type, QString const& id, quint32 schema);
explicit Builder (QByteArray *, Type, QString const& id, quint32 schema);
Builder (Builder const&) = delete;
Builder& operator = (Builder const&) = delete;
private:
void common_initialization (Type type, QString const& id, quint32 schema);
};
//
// NetworkMessage::Reader - read a message containing serialized Qt types
//
// Message is as per NetworkMessage::Builder above, the schema()
// member may be used to determine the schema of the original
// message.
//
class Reader
: public QDataStream
{
public:
explicit Reader (QIODevice *);
explicit Reader (QByteArray const&);
Reader (Reader const&) = delete;
Reader& operator = (Reader const&) = delete;
~Reader ();
quint32 schema () const;
Type type () const;
QString id () const;
private:
class impl;
pimpl<impl> m_;
};
}
#endif
@@ -1,28 +0,0 @@
#!/bin/sh
# Copy the LPDC programs to the directory specified. The program file
# might be the name of the program, or (eg, on Cygwin) the name of the
# program with .exe appended.
if [ x$1 == x -o x$2 != x ]; then
echo Usage: LDPC-install bin-directory
exit 1
fi
echo Installing LPDC programs in $1
mkdir -p $1
for prog in make-pchk alist-to-pchk pchk-to-alist \
make-ldpc print-pchk make-gen print-gen \
rand-src encode transmit decode extract verify; do
if [ -f $prog ]; then
cp $prog $1
elif [ -f $prog.exe ]; then
cp $prog.exe $1
else
echo No program $prog to install
fi
done
echo Done