SVN r8568
This commit is contained in:
@@ -1,125 +0,0 @@
|
||||
program ft8sim
|
||||
|
||||
! Generate simulated data for a 15-second HF/6m mode using 8-FSK.
|
||||
! Output is saved to a *.wav file.
|
||||
|
||||
use wavhdr
|
||||
include 'ft8_params.f90' !Set various constants
|
||||
type(hdr) h !Header for .wav file
|
||||
character arg*12,fname*17,sorm*1
|
||||
character msg*22,msgsent*22
|
||||
character*6 mygrid6
|
||||
logical bcontest
|
||||
complex c0(0:NMAX-1)
|
||||
complex c(0:NMAX-1)
|
||||
integer itone(NN)
|
||||
integer*1 msgbits(KK)
|
||||
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||
data mygrid6/'EM48 '/
|
||||
|
||||
! Get command-line argument(s)
|
||||
nargs=iargc()
|
||||
if(nargs.ne.8) then
|
||||
print*,'Usage: ft8sim "message" s|m f0 DT fdop del nfiles snr'
|
||||
print*,'Example: ft8sim "K1ABC W9XYZ EN37" m 1500.0 0.0 0.1 1.0 10 -18'
|
||||
print*,'s|m: "s" for single signal at 1500 Hz, "m" for 25 signals'
|
||||
print*,'f0 is ignored when sorm = m'
|
||||
print*,'Make nfiles negative to invoke 72-bit contest mode.'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,msg) !Message to be transmitted
|
||||
call getarg(2,sorm) !s for single signal, m for multiple sigs
|
||||
if(sorm.eq."s") then
|
||||
print*,"Generating single signal at 1500 Hz."
|
||||
nsig=1
|
||||
elseif( sorm.eq."m") then
|
||||
print*,"Generating 25 signals per file."
|
||||
nsig=25
|
||||
else
|
||||
print*,"sorm parameter must be s (single) or m (multiple)."
|
||||
goto 999
|
||||
endif
|
||||
call getarg(3,arg)
|
||||
read(arg,*) f0 !Frequency (only used for single-signal)
|
||||
call getarg(4,arg)
|
||||
read(arg,*) xdt !Time offset from nominal (s)
|
||||
call getarg(5,arg)
|
||||
read(arg,*) fspread !Watterson frequency spread (Hz)
|
||||
call getarg(6,arg)
|
||||
read(arg,*) delay !Watterson delay (ms)
|
||||
call getarg(7,arg)
|
||||
read(arg,*) nfiles !Number of files
|
||||
call getarg(8,arg)
|
||||
read(arg,*) snrdb !SNR_2500
|
||||
|
||||
bcontest=nfiles.lt.0
|
||||
nfiles=abs(nfiles)
|
||||
twopi=8.0*atan(1.0)
|
||||
fs=12000.0 !Sample rate (Hz)
|
||||
dt=1.0/fs !Sample interval (s)
|
||||
tt=NSPS*dt !Duration of symbols (s)
|
||||
baud=1.0/tt !Keying rate (baud)
|
||||
bw=8*baud !Occupied bandwidth (Hz)
|
||||
txt=NZ*dt !Transmission length (s)
|
||||
bandwidth_ratio=2500.0/(fs/2.0)
|
||||
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||
if(snrdb.gt.90.0) sig=1.0
|
||||
txt=NN*NSPS/12000.0
|
||||
|
||||
! Source-encode, then get itone()
|
||||
call genft8(msg,mygrid6,bcontest,msgsent,msgbits,itone)
|
||||
write(*,1000) f0,xdt,txt,snrdb,bw,msgsent
|
||||
1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||
' BW:',f4.1,2x,a22)
|
||||
|
||||
write(*,'(28i1,1x,28i1)') msgbits(1:56)
|
||||
write(*,'(16i1)') msgbits(57:72)
|
||||
write(*,'(3i1)') msgbits(73:75)
|
||||
write(*,'(12i1)') msgbits(76:87)
|
||||
|
||||
! call sgran()
|
||||
do ifile=1,nfiles
|
||||
c=0.
|
||||
do isig=1,nsig
|
||||
c0=0.
|
||||
if(nsig.eq.25) then
|
||||
f0=(isig+2)*100.0
|
||||
endif
|
||||
k=-1 + nint((xdt+0.5+0.01*gran())/dt)
|
||||
! k=-1 + nint((xdt+0.5)/dt)
|
||||
phi=0.0
|
||||
do j=1,NN !Generate complex waveform
|
||||
dphi=twopi*(f0+itone(j)*baud)*dt
|
||||
do i=1,NSPS
|
||||
k=k+1
|
||||
phi=mod(phi+dphi,twopi)
|
||||
if(k.ge.0 .and. k.lt.NMAX) c0(k)=cmplx(cos(phi),sin(phi))
|
||||
enddo
|
||||
enddo
|
||||
if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c0,NMAX,fs,delay,fspread)
|
||||
c=c+sig*c0
|
||||
enddo
|
||||
if(snrdb.lt.90) then
|
||||
do i=0,NMAX-1 !Add gaussian noise at specified SNR
|
||||
xnoise=gran()
|
||||
ynoise=gran()
|
||||
c(i)=c(i) + cmplx(xnoise,ynoise)
|
||||
enddo
|
||||
endif
|
||||
|
||||
fac=32767.0
|
||||
rms=100.0
|
||||
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*real(c))
|
||||
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*real(c))
|
||||
|
||||
h=default_header(12000,NMAX)
|
||||
write(fname,1102) ifile
|
||||
1102 format('000000_',i6.6,'.wav')
|
||||
open(10,file=fname,status='unknown',access='stream')
|
||||
write(10) h,iwave !Save to *.wav file
|
||||
close(10)
|
||||
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
|
||||
enddo
|
||||
|
||||
999 end program ft8sim
|
||||
@@ -1,20 +0,0 @@
|
||||
// These instructions are up-to-date for WSJT-X v1.8
|
||||
|
||||
*OS X 10.9* and later: Download the file {osx} to your desktop,
|
||||
double-click on it and consult its `ReadMe` file for important
|
||||
installation notes.
|
||||
|
||||
If you have already installed a previous version, you can retain it by
|
||||
changing its name in the *Applications* folder (say, from _WSJT-X_ to
|
||||
_WSJT-X_1.7_). You can then proceed to the installation phase.
|
||||
|
||||
Take note also of the following:
|
||||
|
||||
* Use the Mac's *Audio MIDI Setup* utility to configure your sound
|
||||
card for 48000 Hz, two-channel, 16-bit format.
|
||||
|
||||
* Use *System Preferences* to select an external time source to keep
|
||||
your system clock synchronized to UTC.
|
||||
|
||||
* To uninstall simply drag the _WSJT-X_ application from *Applications*
|
||||
to the *Trash Can*.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,336 +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
|
||||
`R–nn` 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.
|
||||
|
||||
Finally, the message compression algorithm supports messages starting
|
||||
with `CQ AA` through `CQ ZZ`. Such messages are encoded by
|
||||
sending `E9AA` through `E9ZZ` in place of the first callsign of a
|
||||
standard message. Upon reception these calls are converted back to
|
||||
the form `CQ AA` through `CQ ZZ`.
|
||||
|
||||
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 an experimental mode 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.
|
||||
|
||||
Contest Mode in MSK144 conveys an additional acknowledgment bit (the
|
||||
"`R`" in a message of the form `W9XYZ K1ABC R FN42`) by using the fact
|
||||
that meteor scatter and other propagation modes usable with MSK144 are
|
||||
generally effective only out to distances of order 2500 km. To convey
|
||||
the message fragment `R FN42`, WSJT-X encodes the locator as that of
|
||||
its antipodes. The receiving program recognizes a locator with
|
||||
distance greater than 10,000 km, does the reverse transformation, and
|
||||
inserts the implied "`R`".
|
||||
|
||||
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
|
||||
|=====================================================================
|
||||
@@ -1,377 +0,0 @@
|
||||
subroutine osd174(llr,apmask,ndeep,decoded,cw,nhardmin,dmin)
|
||||
!
|
||||
! An ordered-statistics decoder for the (174,87) code.
|
||||
!
|
||||
include "ldpc_174_87_params.f90"
|
||||
|
||||
integer*1 apmask(N),apmaskr(N)
|
||||
integer*1 gen(K,N)
|
||||
integer*1 genmrb(K,N),g2(N,K)
|
||||
integer*1 temp(K),m0(K),me(K),mi(K),misub(K),e2sub(N-K),e2(N-K),ui(N-K)
|
||||
integer*1 r2pat(N-K)
|
||||
integer indices(N),nxor(N)
|
||||
integer*1 cw(N),ce(N),c0(N),hdec(N)
|
||||
integer*1 decoded(K)
|
||||
integer indx(N)
|
||||
real llr(N),rx(N),absrx(N)
|
||||
logical first,reset
|
||||
data first/.true./
|
||||
save first,gen
|
||||
|
||||
if( first ) then ! fill the generator matrix
|
||||
gen=0
|
||||
do i=1,M
|
||||
do j=1,22
|
||||
read(g(i)(j:j),"(Z1)") istr
|
||||
do jj=1, 4
|
||||
irow=(j-1)*4+jj
|
||||
if( btest(istr,4-jj) ) gen(irow,i)=1
|
||||
enddo
|
||||
enddo
|
||||
enddo
|
||||
do irow=1,K
|
||||
gen(irow,M+irow)=1
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
! Re-order received vector to place systematic msg bits at the end.
|
||||
rx=llr(colorder+1)
|
||||
apmaskr=apmask(colorder+1)
|
||||
|
||||
! Hard decisions on the received word.
|
||||
hdec=0
|
||||
where(rx .ge. 0) hdec=1
|
||||
|
||||
! Use magnitude of received symbols as a measure of reliability.
|
||||
absrx=abs(rx)
|
||||
call indexx(absrx,N,indx)
|
||||
|
||||
! Re-order the columns of the generator matrix in order of decreasing reliability.
|
||||
do i=1,N
|
||||
genmrb(1:K,i)=gen(1:K,indx(N+1-i))
|
||||
indices(i)=indx(N+1-i)
|
||||
enddo
|
||||
|
||||
! Do gaussian elimination to create a generator matrix with the most reliable
|
||||
! received bits in positions 1:K in order of decreasing reliability (more or less).
|
||||
do id=1,K ! diagonal element indices
|
||||
do icol=id,K+20 ! The 20 is ad hoc - beware
|
||||
iflag=0
|
||||
if( genmrb(id,icol) .eq. 1 ) then
|
||||
iflag=1
|
||||
if( icol .ne. id ) then ! reorder column
|
||||
temp(1:K)=genmrb(1:K,id)
|
||||
genmrb(1:K,id)=genmrb(1:K,icol)
|
||||
genmrb(1:K,icol)=temp(1:K)
|
||||
itmp=indices(id)
|
||||
indices(id)=indices(icol)
|
||||
indices(icol)=itmp
|
||||
endif
|
||||
do ii=1,K
|
||||
if( ii .ne. id .and. genmrb(ii,id) .eq. 1 ) then
|
||||
genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
|
||||
endif
|
||||
enddo
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
g2=transpose(genmrb)
|
||||
|
||||
! The hard decisions for the K MRB bits define the order 0 message, m0.
|
||||
! Encode m0 using the modified generator matrix to find the "order 0" codeword.
|
||||
! Flip various combinations of bits in m0 and re-encode to generate a list of
|
||||
! codewords. Return the member of the list that has the smallest Euclidean
|
||||
! distance to the received word.
|
||||
|
||||
hdec=hdec(indices) ! hard decisions from received symbols
|
||||
m0=hdec(1:K) ! zero'th order message
|
||||
absrx=absrx(indices)
|
||||
rx=rx(indices)
|
||||
apmaskr=apmaskr(indices)
|
||||
|
||||
call mrbencode(m0,c0,g2,N,K)
|
||||
nxor=ieor(c0,hdec)
|
||||
nhardmin=sum(nxor)
|
||||
dmin=sum(nxor*absrx)
|
||||
|
||||
cw=c0
|
||||
ntotal=0
|
||||
nrejected=0
|
||||
|
||||
if(ndeep.eq.0) goto 998 ! norder=0
|
||||
if(ndeep.gt.5) ndeep=5
|
||||
if( ndeep.eq. 1) then
|
||||
nord=1
|
||||
npre1=0
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
elseif(ndeep.eq.2) then
|
||||
nord=1
|
||||
npre1=1
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
elseif(ndeep.eq.3) then
|
||||
nord=1
|
||||
npre1=1
|
||||
npre2=1
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=14
|
||||
elseif(ndeep.eq.4) then
|
||||
nord=2
|
||||
npre1=1
|
||||
npre2=0
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=19
|
||||
elseif(ndeep.eq.5) then
|
||||
nord=2
|
||||
npre1=1
|
||||
npre2=1
|
||||
nt=40
|
||||
ntheta=12
|
||||
ntau=19
|
||||
endif
|
||||
|
||||
do iorder=1,nord
|
||||
if( iorder.eq. 1 ) then
|
||||
misub(1:K-1)=0
|
||||
misub(K)=1
|
||||
iflag=K
|
||||
elseif( iorder.eq. 2 ) then
|
||||
misub(1:K-2)=0
|
||||
misub(K-1:K)=1
|
||||
iflag=K-1
|
||||
endif
|
||||
do while(iflag .ge.0)
|
||||
if(iorder.eq.nord .and. npre1.eq.0) then
|
||||
iend=iflag
|
||||
else
|
||||
iend=1
|
||||
endif
|
||||
do n1=iflag,iend,-1
|
||||
mi=misub
|
||||
mi(n1)=1
|
||||
if(any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||
ntotal=ntotal+1
|
||||
me=ieor(m0,mi)
|
||||
if(n1.eq.iflag) then
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||
e2=e2sub
|
||||
nd1Kpt=sum(e2sub(1:nt))+1
|
||||
d1=sum(ieor(me(1:K),hdec(1:K))*absrx(1:K))
|
||||
else
|
||||
e2=ieor(e2sub,g2(K+1:N,n1))
|
||||
nd1Kpt=sum(e2(1:nt))+2
|
||||
endif
|
||||
if(nd1Kpt .le. ntheta) then
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
nxor=ieor(ce,hdec)
|
||||
if(n1.eq.iflag) then
|
||||
dd=d1+sum(e2sub*absrx(K+1:N))
|
||||
else
|
||||
dd=d1+ieor(ce(n1),hdec(n1))*absrx(n1)+sum(e2*absrx(K+1:N))
|
||||
endif
|
||||
if( dd .lt. dmin ) then
|
||||
dmin=dd
|
||||
cw=ce
|
||||
nhardmin=sum(nxor)
|
||||
nd1Kptbest=nd1Kpt
|
||||
endif
|
||||
else
|
||||
nrejected=nrejected+1
|
||||
endif
|
||||
enddo
|
||||
! Get the next test error pattern, iflag will go negative
|
||||
! when the last pattern with weight iorder has been generated.
|
||||
call nextpat(misub,k,iorder,iflag)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
if(npre2.eq.1) then
|
||||
reset=.true.
|
||||
ntotal=0
|
||||
do i1=K,1,-1
|
||||
do i2=i1-1,1,-1
|
||||
ntotal=ntotal+1
|
||||
mi(1:ntau)=ieor(g2(K+1:K+ntau,i1),g2(K+1:K+ntau,i2))
|
||||
call boxit(reset,mi(1:ntau),ntau,ntotal,i1,i2)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
ncount2=0
|
||||
ntotal2=0
|
||||
reset=.true.
|
||||
! Now run through again and do the second pre-processing rule
|
||||
if(nord.eq.1) then
|
||||
misub(1:K-1)=0
|
||||
misub(K)=1
|
||||
iflag=K
|
||||
elseif(nord.eq.2) then
|
||||
misub(1:K-1)=0
|
||||
misub(K-1:K)=1
|
||||
iflag=K-1
|
||||
endif
|
||||
do while(iflag .ge.0)
|
||||
me=ieor(m0,misub)
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
e2sub=ieor(ce(K+1:N),hdec(K+1:N))
|
||||
do i2=0,ntau
|
||||
ntotal2=ntotal2+1
|
||||
ui=0
|
||||
if(i2.gt.0) ui(i2)=1
|
||||
r2pat=ieor(e2sub,ui)
|
||||
778 continue
|
||||
call fetchit(reset,r2pat(1:ntau),ntau,in1,in2)
|
||||
if(in1.gt.0.and.in2.gt.0) then
|
||||
ncount2=ncount2+1
|
||||
mi=misub
|
||||
mi(in1)=1
|
||||
mi(in2)=1
|
||||
if(sum(mi).lt.nord+npre1+npre2.or.any(iand(apmaskr(1:K),mi).eq.1)) cycle
|
||||
me=ieor(m0,mi)
|
||||
call mrbencode(me,ce,g2,N,K)
|
||||
nxor=ieor(ce,hdec)
|
||||
dd=sum(nxor*absrx)
|
||||
if( dd .lt. dmin ) then
|
||||
dmin=dd
|
||||
cw=ce
|
||||
nhardmin=sum(nxor)
|
||||
endif
|
||||
goto 778
|
||||
endif
|
||||
enddo
|
||||
call nextpat(misub,K,nord,iflag)
|
||||
enddo
|
||||
endif
|
||||
|
||||
998 continue
|
||||
! Re-order the codeword to place message bits at the end.
|
||||
cw(indices)=cw
|
||||
hdec(indices)=hdec
|
||||
decoded=cw(K+1:N)
|
||||
cw(colorder+1)=cw ! put the codeword back into received-word order
|
||||
return
|
||||
end subroutine osd174
|
||||
|
||||
subroutine mrbencode(me,codeword,g2,N,K)
|
||||
integer*1 me(K),codeword(N),g2(N,K)
|
||||
! fast encoding for low-weight test patterns
|
||||
codeword=0
|
||||
do i=1,K
|
||||
if( me(i) .eq. 1 ) then
|
||||
codeword=ieor(codeword,g2(1:N,i))
|
||||
endif
|
||||
enddo
|
||||
return
|
||||
end subroutine mrbencode
|
||||
|
||||
subroutine nextpat(mi,k,iorder,iflag)
|
||||
integer*1 mi(k),ms(k)
|
||||
! generate the next test error pattern
|
||||
ind=-1
|
||||
do i=1,k-1
|
||||
if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i
|
||||
enddo
|
||||
if( ind .lt. 0 ) then ! no more patterns of this order
|
||||
iflag=ind
|
||||
return
|
||||
endif
|
||||
ms=0
|
||||
ms(1:ind-1)=mi(1:ind-1)
|
||||
ms(ind)=1
|
||||
ms(ind+1)=0
|
||||
if( ind+1 .lt. k ) then
|
||||
nz=iorder-sum(ms)
|
||||
ms(k-nz+1:k)=1
|
||||
endif
|
||||
mi=ms
|
||||
do i=1,k ! iflag will point to the lowest-index 1 in mi
|
||||
if(mi(i).eq.1) then
|
||||
iflag=i
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
return
|
||||
end subroutine nextpat
|
||||
|
||||
subroutine boxit(reset,e2,ntau,npindex,i1,i2)
|
||||
integer*1 e2(1:ntau)
|
||||
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||
logical reset
|
||||
common/boxes/indexes,fp,np
|
||||
|
||||
if(reset) then
|
||||
patterns=-1
|
||||
fp=-1
|
||||
np=-1
|
||||
sc=-1
|
||||
indexes=-1
|
||||
reset=.false.
|
||||
endif
|
||||
|
||||
indexes(npindex,1)=i1
|
||||
indexes(npindex,2)=i2
|
||||
ipat=0
|
||||
do i=1,ntau
|
||||
if(e2(i).eq.1) then
|
||||
ipat=ipat+ishft(1,ntau-i)
|
||||
endif
|
||||
enddo
|
||||
|
||||
ip=fp(ipat) ! see what's currently stored in fp(ipat)
|
||||
if(ip.eq.-1) then
|
||||
fp(ipat)=npindex
|
||||
else
|
||||
do while (np(ip).ne.-1)
|
||||
ip=np(ip)
|
||||
enddo
|
||||
np(ip)=npindex
|
||||
endif
|
||||
return
|
||||
end subroutine boxit
|
||||
|
||||
subroutine fetchit(reset,e2,ntau,i1,i2)
|
||||
integer indexes(4000,2),fp(0:525000),np(4000)
|
||||
integer lastpat
|
||||
integer*1 e2(ntau)
|
||||
logical reset
|
||||
common/boxes/indexes,fp,np
|
||||
save lastpat,inext
|
||||
|
||||
if(reset) then
|
||||
lastpat=-1
|
||||
reset=.false.
|
||||
endif
|
||||
|
||||
ipat=0
|
||||
do i=1,ntau
|
||||
if(e2(i).eq.1) then
|
||||
ipat=ipat+ishft(1,ntau-i)
|
||||
endif
|
||||
enddo
|
||||
index=fp(ipat)
|
||||
|
||||
if(lastpat.ne.ipat .and. index.gt.0) then ! return first set of indices
|
||||
i1=indexes(index,1)
|
||||
i2=indexes(index,2)
|
||||
inext=np(index)
|
||||
elseif(lastpat.eq.ipat .and. inext.gt.0) then
|
||||
i1=indexes(inext,1)
|
||||
i2=indexes(inext,2)
|
||||
inext=np(inext)
|
||||
else
|
||||
i1=-1
|
||||
i2=-1
|
||||
inext=-1
|
||||
endif
|
||||
lastpat=ipat
|
||||
return
|
||||
end subroutine fetchit
|
||||
|
||||
Reference in New Issue
Block a user