Rationalize several VHF-oriented features of the JT4 and JT64 decoders. More additions to the User Guide.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7227 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2016-10-24 20:48:24 +00:00
parent 86d58e142b
commit 2d7f341737
9 changed files with 77 additions and 72 deletions

View File

@ -70,6 +70,8 @@ set (UG_IMGS
images/freemsg.png images/freemsg.png
images/help-menu.png images/help-menu.png
images/JT4F.png images/JT4F.png
images/JT65B.png
images/QRA64.png
images/jtalert.png images/jtalert.png
images/keyboard-shortcuts.png images/keyboard-shortcuts.png
images/log-qso.png images/log-qso.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -125,27 +125,47 @@ image::JT4F.png[align="center",alt="JT4F"]
=== JT65 === JT65
In most ways JT65 operation on VHF and higher bands is similar to HF In many ways JT65 operation on VHF and higher bands is similar to HF
usage. However, a few differences should be noted. Typical VHF/UHF usage, but a few important differences should be noted. Typical
operation involves only a single signal in the receiver passband, or VHF/UHF operation involves only a single signal (or perhaps two or
perhaps a few, rather than many. Normally it's best to check *Single three) in the receiver passband. You may find it best to check
decode* on the *Settings -> General* tab and uncheck *Two pass *Single decode* on the *Settings -> General* tab. There will be
decoding* on the *Advanced* tab. In this mode the JT65 decoder will little need for *Two pass decoding* on the *Advanced* tab. With VHF
respond to special message formats sometimes used for EME, including features enabled the JT65 decoder will respond to special message
the OOO signal report and shorthand messages for RO, RRR, and 73. formats often used for EME: the OOO signal report and two-tone
Those messages will be automatically generated if you check the shorthand messages for RO, RRR, and 73. These messages are always
shorthand message box *Sh*. enabled for reception; they will be automatically generated for
transmission if you check the shorthand message box *Sh*.
As for JT4, you should check *Deep* on *the *Decode* menu, and Be sure to check *Deep* on *the *Decode* menu; you may optionally
optionally *Enable averaging* and *Deep search*. include *Enable averaging* and *Deep search*.
The following screen shot shows three transmissions from a 144 MHz EME
QSO using submode JT65B and shorthand messages. Take note of the
colored tick marks on the Wide Graph frequency scale. The green
marker at 1220 Hz indicates the selected QSO frequency (the frequency
of the JT65 Sync tone) and the *F Tol* range. A green tick at 1575 Hz
marks the frequency of the highest JT65 data tone. Orange markers
indicate the frequency of the upper tone of the two-tone signals for
RO, RRR, and 73.
image::JT65B.png[align="center",alt="JT65B"]
=== QRA64 === QRA64
QRA64 is an experimental mode in the present alpha release of QRA64 is an experimental mode in the Version 1.7 alpha release of
_WSJT-X_, Version 1.7. The protocol is still subject to change, and _WSJT-X_. Some details of the protocol are still subject to change,
some features of the decoder will likely change. In most ways and some features of the decoder will almost surely change. In most
operation of QRA64 is similar to JT65. ways you will find operation of QRA64 similar to JT65. The following
screen shot shows examples of QRA64A transmissions recorded over the
EME path at 144 MHz (G4SWX transmitting to K1JT) and 10 GHz (VK7MO
transmitting to G3WDG). Notice the small red curve plotted below
frequency 1000 Hz in the Wide Graph. Even though the VK7MO signal is
scarcely visible in the waterfall, the red curve shows that the
decoder has accurately and reliably detected its synchronizing
symbols.
image::QRA64.png[align="center",alt="QRA64"]
=== ISCAT === ISCAT

View File

@ -1,6 +1,6 @@
subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,ntrials, & subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,ntrials, &
naggressive,ndepth,ntol,mycall,hiscall,hisgrid,nexp_decode, & naggressive,ndepth,ntol,mycall,hiscall,hisgrid,nexp_decode, &
single_decode,sync2,a,dt,nft,nspecial,qual,nhist,nsmo,decoded) bVHF,sync2,a,dt,nft,nspecial,qual,nhist,nsmo,decoded)
! Apply AFC corrections to a candidate JT65 signal, then decode it. ! Apply AFC corrections to a candidate JT65 signal, then decode it.
@ -15,7 +15,7 @@ subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,ntrials, &
complex c5a(512) complex c5a(512)
real s2(66,126) real s2(66,126)
real a(5) real a(5)
logical single_decode,first logical bVHF,first
character decoded*22,decoded_best*22 character decoded*22,decoded_best*22
character mycall*12,hiscall*12,hisgrid*6 character mycall*12,hiscall*12,hisgrid*6
character*27 cr character*27 cr
@ -30,7 +30,7 @@ subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,ntrials, &
! NB: cx has sample rate 12000*77125/672000 = 1378.125 Hz ! NB: cx has sample rate 12000*77125/672000 = 1378.125 Hz
! Check for a shorthand message ! Check for a shorthand message
if(single_decode .and. mode65.ne.101) then if(bVHF .and. mode65.ne.101) then
call sh65(cx,n5,mode65,ntol,xdf,nspecial,sync2) call sh65(cx,n5,mode65,ntol,xdf,nspecial,sync2)
if(nspecial.gt.0) then if(nspecial.gt.0) then
a=0. a=0.

View File

@ -261,7 +261,7 @@ contains
1011 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' QRA64',i3) 1011 format(i4.4,i4,i5,f6.2,f8.0,i4,3x,a22,' QRA64',i3)
go to 100 go to 100
endif endif
if(ft.eq.0 .and. minsync.ge.0 .and. int(sync).lt.minsync) then if(ft.eq.0 .and. minsync.ge.0 .and. int(sync).lt.minsync) then
write(*,1010) params%nutc,snr,dt,freq write(*,1010) params%nutc,snr,dt,freq
else else
@ -281,7 +281,7 @@ contains
endif endif
csync='# ' csync='# '
i=0 i=0
if(single_decode .and. nflip.ne.0 .and. & if(bVHF .and. nflip.ne.0 .and. &
sync.ge.max(0.0,float(minsync))) then sync.ge.max(0.0,float(minsync))) then
csync='#*' csync='#*'
if(nflip.eq.-1) then if(nflip.eq.-1) then

View File

@ -75,7 +75,7 @@ contains
character*22 decoded character*22 decoded
end type accepted_decode end type accepted_decode
type(accepted_decode) dec(50) type(accepted_decode) dec(50)
logical :: first_time,robust,prtavg,single_decode logical :: first_time,prtavg,single_decode,bVHF
integer h0(0:11),d0(0:11) integer h0(0:11),d0(0:11)
real r0(0:11) real r0(0:11)
@ -93,7 +93,6 @@ contains
this%callback => callback this%callback => callback
first_time=newdat first_time=newdat
robust=nrobust
dd=dd0 dd=dd0
ndecoded=0 ndecoded=0
@ -134,13 +133,16 @@ contains
nfa=nf1 nfa=nf1
nfb=nf2 nfb=nf2
single_decode=iand(nexp_decode,32).ne.0 single_decode=iand(nexp_decode,32).ne.0
if(single_decode .or. (naggressive.gt.0 .and. ntol.lt.1000)) then bVHF=iand(nexp_decode,64).ne.0
!### Q: should either of the next two uses of "single_decode" be "bVHF" instead?
if(single_decode .or. (bVHF .and. ntol.lt.1000)) then
nfa=max(200,nfqso-ntol) nfa=max(200,nfqso-ntol)
nfb=min(4000,nfqso+ntol) nfb=min(4000,nfqso+ntol)
thresh0=1.0 thresh0=1.0
endif endif
df=12000.0/8192.0 !df = 1.465 Hz df=12000.0/8192.0 !df = 1.465 Hz
if(single_decode) then if(bVHF) then
ia=max(1,nint(nfa/df)-ntol) ia=max(1,nint(nfa/df)-ntol)
ib=min(NSZ,nint(nfb/df)+ntol) ib=min(NSZ,nint(nfb/df)+ntol)
nz=ib-ia+1 nz=ib-ia+1
@ -151,30 +153,16 @@ contains
width=a(4)*df width=a(4)*df
endif endif
! robust = .false.: use float ccf. Only if ncand>50 fall back to robust (1-bit) ccf
! robust = .true. : use only robust (1-bit) ccf
ncand=0 ncand=0
if(.not.robust) then call timer('sync65 ',0)
call timer('sync65 ',0) call sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,0,bVHF)
call sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,0, & call timer('sync65 ',1)
single_decode)
call timer('sync65 ',1)
endif
if(ncand.gt.50) robust=.true.
if(robust) then
ncand=0
call timer('sync65 ',0)
call sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,1, &
single_decode)
call timer('sync65 ',1)
endif
! If a candidate was found within +/- ntol of nfqso, move it into ca(1). ! If a candidate was found within +/- ntol of nfqso, move it into ca(1).
call fqso_first(nfqso,ntol,ca,ncand) call fqso_first(nfqso,ntol,ca,ncand)
if(single_decode) then if(single_decode) then
ncand=1 if(ncand.eq.0) ncand=1
if(abs(ca(1)%freq - f0).gt.width) width=2*df if(abs(ca(1)%freq - f0).gt.width) width=2*df !### ??? ###
endif endif
nvec=ntrials nvec=ntrials
if(ncand.gt.75) then if(ncand.gt.75) then
@ -194,19 +182,19 @@ contains
nsave=0 nsave=0
endif endif
if(single_decode) then if(bVHF) then
! Be sure to search for shorthand message at nfqso +/- ntol ! Be sure to search for shorthand message at nfqso +/- ntol
ncand=2 if(ncand.lt.300) ncand=ncand+1
ca(2)%sync=5.0 ca(ncand)%sync=5.0
ca(2)%dt=2.5 ca(ncand)%dt=2.5
ca(2)%freq=nfqso ca(ncand)%freq=nfqso
endif endif
do icand=1,ncand do icand=1,ncand
sync1=ca(icand)%sync sync1=ca(icand)%sync
dtx=ca(icand)%dt dtx=ca(icand)%dt
freq=ca(icand)%freq freq=ca(icand)%freq
if(single_decode) then if(bVHF) then
flip=ca(icand)%flip flip=ca(icand)%flip
nflip=flip nflip=flip
endif endif
@ -215,9 +203,10 @@ contains
if(ipass.eq.2) ntry65b=ntry65b + 1 if(ipass.eq.2) ntry65b=ntry65b + 1
call timer('decod65a',0) call timer('decod65a',0)
nft=0 nft=0
nspecial=0
call decode65a(dd,npts,first_time,nqd,freq,nflip,mode65,nvec, & call decode65a(dd,npts,first_time,nqd,freq,nflip,mode65,nvec, &
naggressive,ndepth,ntol,mycall,hiscall,hisgrid, & naggressive,ndepth,ntol,mycall,hiscall,hisgrid, &
nexp_decode,single_decode,sync2,a,dtx,nft,nspecial,qual, & nexp_decode,bVHF,sync2,a,dtx,nft,nspecial,qual, &
nhist,nsmo,decoded) nhist,nsmo,decoded)
if(nspecial.eq.2) decoded='RO' if(nspecial.eq.2) decoded='RO'
if(nspecial.eq.3) decoded='RRR' if(nspecial.eq.3) decoded='RRR'
@ -234,7 +223,7 @@ contains
nfreq=nint(freq+a(1)) nfreq=nint(freq+a(1))
ndrift=nint(2.0*a(2)) ndrift=nint(2.0*a(2))
if(single_decode) then if(bVHF) then
s2db=sync1 - 30.0 + db(width/3.3) !### VHF/UHF/microwave s2db=sync1 - 30.0 + db(width/3.3) !### VHF/UHF/microwave
if(nspecial.gt.0) s2db=sync2 if(nspecial.gt.0) s2db=sync2
else else
@ -282,7 +271,8 @@ contains
if(rtt.gt.r0(n)) cycle if(rtt.gt.r0(n)) cycle
endif endif
5 if(decoded.eq.decoded0 .and. abs(freq-freq0).lt. 3.0 .and. & 5 continue
if(decoded.eq.decoded0 .and. abs(freq-freq0).lt. 3.0 .and. &
minsync.ge.0) cycle !Don't display dupes minsync.ge.0) cycle !Don't display dupes
if(decoded.ne.' ' .or. minsync.lt.0) then if(decoded.ne.' ' .or. minsync.lt.0) then
if(nsubtract.eq.1) then if(nsubtract.eq.1) then
@ -298,9 +288,7 @@ contains
exit exit
endif endif
enddo enddo
if(ndupe.ne.1 .and. sync1.ge.float(minsync)) then
! if(ndupe.ne.1 .or. minsync.lt.0) then
if(ndupe.ne.1) then
if(ipass.eq.1) n65a=n65a + 1 if(ipass.eq.1) n65a=n65a + 1
if(ipass.eq.2) n65b=n65b + 1 if(ipass.eq.2) n65b=n65b + 1
if(ndecoded.lt.50) ndecoded=ndecoded+1 if(ndecoded.lt.50) ndecoded=ndecoded+1
@ -493,8 +481,6 @@ contains
nftt=nfttbest nftt=nfttbest
endif endif
900 continue 900 continue
! write(*,3301) 'Z',nftt,nsave,nsum,nsmo,qave,avemsg
!3301 format(a1,4i3,f7.1,1x,a22)
return return
end subroutine avg65 end subroutine avg65

View File

@ -1,11 +1,11 @@
subroutine sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,nrobust, & subroutine sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,nrobust, &
single_decode) bVHF)
parameter (NSZ=3413,NFFT=8192,MAXCAND=300) parameter (NSZ=3413,NFFT=8192,MAXCAND=300)
real ss(322,NSZ) real ss(322,NSZ)
real ccfblue(-11:540) !CCF with pseudorandom sequence real ccfblue(-11:540) !CCF with pseudorandom sequence
real ccfred(NSZ) !Peak of ccfblue, as function of freq real ccfred(NSZ) !Peak of ccfblue, as function of freq
logical single_decode logical bVHF
type candidate type candidate
real freq real freq
@ -35,7 +35,7 @@ subroutine sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,nrobust, &
do i=ia,ib do i=ia,ib
call xcor(ss,i,nhsym,nsym,lag1,lag2,ccfblue,ccf0,lagpk0,flip,fdot,nrobust) call xcor(ss,i,nhsym,nsym,lag1,lag2,ccfblue,ccf0,lagpk0,flip,fdot,nrobust)
! Remove best-fit slope from ccfblue and normalize so baseline rms=1.0 ! Remove best-fit slope from ccfblue and normalize so baseline rms=1.0
if(.not.single_decode) call slope(ccfblue(lag1),lag2-lag1+1, & if(.not.bVHF) call slope(ccfblue(lag1),lag2-lag1+1, &
lagpk0-lag1+1.0) lagpk0-lag1+1.0)
ccfred(i)=ccfblue(lagpk0) ccfred(i)=ccfblue(lagpk0)
if(ccfred(i).gt.ccfmax) then if(ccfred(i).gt.ccfmax) then
@ -66,7 +66,7 @@ subroutine sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,nrobust, &
if(itry.ne.0) then if(itry.ne.0) then
call xcor(ss,i,nhsym,nsym,lag1,lag2,ccfblue,ccf0,lagpk,flip,fdot, & call xcor(ss,i,nhsym,nsym,lag1,lag2,ccfblue,ccf0,lagpk,flip,fdot, &
nrobust) nrobust)
if(.not.single_decode) call slope(ccfblue(lag1),lag2-lag1+1, & if(.not.bVHF) call slope(ccfblue(lag1),lag2-lag1+1, &
lagpk-lag1+1.0) lagpk-lag1+1.0)
xlag=lagpk xlag=lagpk
if(lagpk.gt.lag1 .and. lagpk.lt.lag2) then if(lagpk.gt.lag1 .and. lagpk.lt.lag2) then
@ -79,7 +79,7 @@ subroutine sync65(ss,nfa,nfb,naggressive,ntol,nhsym,ca,ncand,nrobust, &
ca(ncand)%freq=freq ca(ncand)%freq=freq
ca(ncand)%dt=dtx ca(ncand)%dt=dtx
ca(ncand)%flip=flip ca(ncand)%flip=flip
if(single_decode) then if(bVHF) then
ca(ncand)%sync=db(ccfred(i)) - 16.0 ca(ncand)%sync=db(ccfred(i)) - 16.0
else else
ca(ncand)%sync=ccfred(i) ca(ncand)%sync=ccfred(i)

View File

@ -2171,7 +2171,7 @@ void MainWindow::decode() //decode()
dec_data.params.nfSplit=m_wideGraph->Fmin(); dec_data.params.nfSplit=m_wideGraph->Fmin();
dec_data.params.nfb=m_wideGraph->Fmax(); dec_data.params.nfb=m_wideGraph->Fmax();
dec_data.params.ntol=m_Ftol; dec_data.params.ntol=m_Ftol;
if(m_mode=="JT9+JT65" or !m_config.enable_VHF_features() or !m_config.single_decode()) { if(m_mode=="JT9+JT65" or !m_config.enable_VHF_features()) {
dec_data.params.ntol=20; dec_data.params.ntol=20;
dec_data.params.naggressive=0; dec_data.params.naggressive=0;
} }
@ -2443,10 +2443,10 @@ void MainWindow::readFromStdout() //readFromStdout
//Right (Rx Frequency) window //Right (Rx Frequency) window
bool bDisplayRight=bAvgMsg; bool bDisplayRight=bAvgMsg;
if(!m_config.single_decode() and m_mode!="JT4" and if(!m_config.enable_VHF_features() and
(abs(decodedtext.frequencyOffset() - m_wideGraph->rxFreq()) <= 10)) bDisplayRight=true; (abs(decodedtext.frequencyOffset() - m_wideGraph->rxFreq()) <= 10)) bDisplayRight=true;
if (bDisplayRight) { if (bDisplayRight) {
// This msg is within 10 hertz of our tuned frequency, or a JT4 avg // This msg is within 10 hertz of our tuned frequency, or a JT4 or JT65 avg
ui->decodedTextBrowser2->displayDecodedText(decodedtext,m_baseCall,false, ui->decodedTextBrowser2->displayDecodedText(decodedtext,m_baseCall,false,
m_logBook,m_config.color_CQ(),m_config.color_MyCall(), m_logBook,m_config.color_CQ(),m_config.color_MyCall(),
m_config.color_DXCC(),m_config.color_NewCall()); m_config.color_DXCC(),m_config.color_NewCall());
@ -4092,7 +4092,7 @@ void MainWindow::on_actionJT65_triggered()
m_mode="JT65"; m_mode="JT65";
bool bVHF=m_config.enable_VHF_features(); bool bVHF=m_config.enable_VHF_features();
if(bVHF) { if(bVHF) {
displayWidgets(nWidgets("11111000000011111011000")); displayWidgets(nWidgets("11111001000011111011000"));
} else { } else {
displayWidgets(nWidgets("11101000000011100001110")); displayWidgets(nWidgets("11101000000011100001110"));
} }
@ -4121,14 +4121,11 @@ void MainWindow::on_actionJT65_triggered()
ui->sbSubmode->setMaximum(2); ui->sbSubmode->setMaximum(2);
if(bVHF) { if(bVHF) {
ui->sbSubmode->setValue(m_nSubMode); ui->sbSubmode->setValue(m_nSubMode);
} else {
ui->sbSubmode->setValue(0);
ui->sbTR->setValue(0);
}
if(m_config.single_decode()) {
ui->label_6->setText("Single-Period Decodes"); ui->label_6->setText("Single-Period Decodes");
ui->label_7->setText("Average Decodes"); ui->label_7->setText("Average Decodes");
} else { } else {
ui->sbSubmode->setValue(0);
ui->sbTR->setValue(0);
ui->label_6->setText("Band Activity"); ui->label_6->setText("Band Activity");
ui->label_7->setText("Rx Frequency"); ui->label_7->setText("Rx Frequency");
} }