Improve the way messages with compound calls are automatically generated.

Routine packmsg now tries the shortlist (Type 1 prefix or suffix) first.
Then it tries to to make a valid message using a Type 2 prefix or suffix.
If both fail, it packs the first 13 characters as a free-text message.

The GUI now generates the most useful messages with compound callsigns
of all valid types.



git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@4533 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2014-10-19 00:56:41 +00:00
parent 5add0aeb97
commit 0e96882d8b
10 changed files with 139 additions and 105 deletions

View File

@ -235,6 +235,7 @@ set (wsjt_FSRCS
lib/flat3.f90 lib/flat3.f90
lib/flat65.f90 lib/flat65.f90
lib/four2a.f90 lib/four2a.f90
lib/fmtmsg.f90
lib/gen65.f90 lib/gen65.f90
lib/genjt9.f90 lib/genjt9.f90
lib/geodist.f90 lib/geodist.f90

View File

@ -1,4 +1,4 @@
subroutine gen65(msg0,ichk,msgsent,itone,itext) subroutine gen65(msg0,ichk,msgsent,itone,itype)
! Encodes a JT65 message to yieild itone(1:126) ! Encodes a JT65 message to yieild itone(1:126)
! Temporarily, does not implement EME shorthands ! Temporarily, does not implement EME shorthands
@ -37,9 +37,7 @@ subroutine gen65(msg0,ichk,msgsent,itone,itext)
nspecial=0 nspecial=0
! call chkmsg(message,cok,nspecial,flip) ! call chkmsg(message,cok,nspecial,flip)
if(nspecial.eq.0) then if(nspecial.eq.0) then
call packmsg(message,dgen,text) !Pack message into 72 bits call packmsg(message,dgen,itype) !Pack message into 72 bits
itext=0
if(text) itext=1
call unpackmsg(dgen,msgsent) !Unpack to get message sent call unpackmsg(dgen,msgsent) !Unpack to get message sent
if(ichk.ne.0) go to 999 !Return if checking only if(ichk.ne.0) go to 999 !Return if checking only

View File

@ -1,4 +1,4 @@
subroutine genjt9(msg0,ichk,msgsent,i4tone,itext) subroutine genjt9(msg0,ichk,msgsent,i4tone,itype)
! Encodes a JT9 message and returns msgsent, the message as it will ! Encodes a JT9 message and returns msgsent, the message as it will
! be decoded, and an integer array i4tone(85) of 9-FSK tone values ! be decoded, and an integer array i4tone(85) of 9-FSK tone values
@ -31,9 +31,7 @@ subroutine genjt9(msg0,ichk,msgsent,i4tone,itext)
message=message(i+1:) message=message(i+1:)
enddo enddo
call packmsg(message,i4Msg6BitWords,text) !Pack message into 12 6-bit bytes call packmsg(message,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes
itext=0
if(text) itext=1
call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent
if(ichk.ne.0) go to 999 if(ichk.ne.0) go to 999
call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, convert to 8-bit bytes call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, convert to 8-bit bytes

View File

@ -8,7 +8,7 @@ subroutine getpfx1(callsign,k,nv2)
include 'pfx.f90' include 'pfx.f90'
callsign0=callsign callsign0=callsign
nv2=0 nv2=1
iz=index(callsign,' ') - 1 iz=index(callsign,' ') - 1
if(iz.lt.0) iz=12 if(iz.lt.0) iz=12
islash=index(callsign(1:iz),'/') islash=index(callsign(1:iz),'/')
@ -22,11 +22,13 @@ subroutine getpfx1(callsign,k,nv2)
do i=1,NZ do i=1,NZ
if(pfx(i)(1:4).eq.c) then if(pfx(i)(1:4).eq.c) then
k=i k=i
nv2=2
go to 10 go to 10
endif endif
enddo enddo
if(addpfx.eq.c) then if(addpfx.eq.c) then
k=449 k=449
nv2=2
go to 10 go to 10
endif endif
@ -37,6 +39,7 @@ subroutine getpfx1(callsign,k,nv2)
do i=1,NZ2 do i=1,NZ2
if(sfx(i).eq.c(1:1)) then if(sfx(i).eq.c(1:1)) then
k=400+i k=400+i
nv2=3
go to 10 go to 10
endif endif
enddo enddo
@ -75,7 +78,7 @@ subroutine getpfx1(callsign,k,nv2)
k=37*k + nchar(tpfx(2:2)) k=37*k + nchar(tpfx(2:2))
k=37*k + nchar(tpfx(3:3)) k=37*k + nchar(tpfx(3:3))
k=37*k + nchar(tpfx(4:4)) k=37*k + nchar(tpfx(4:4))
nv2=1 nv2=4
i=index(callsign0,'/') i=index(callsign0,'/')
callsign=callsign0(:i-1) callsign=callsign0(:i-1)
callsign=callsign0(i+1:) callsign=callsign0(i+1:)
@ -85,7 +88,7 @@ subroutine getpfx1(callsign,k,nv2)
k=nchar(tsfx(1:1)) k=nchar(tsfx(1:1))
k=37*k + nchar(tsfx(2:2)) k=37*k + nchar(tsfx(2:2))
k=37*k + nchar(tsfx(3:3)) k=37*k + nchar(tsfx(3:3))
nv2=2 nv2=5
i=index(callsign0,'/') i=index(callsign0,'/')
callsign=callsign0(:i-1) callsign=callsign0(:i-1)
endif endif

View File

@ -4,9 +4,8 @@ program JT65code
! Reed Solomon encoding, and other necessary details of the JT65 ! Reed Solomon encoding, and other necessary details of the JT65
! protocol. ! protocol.
character*22 msg0,msg,decoded,cok*3 character*22 msg,msg0,msg1,decoded,cok*3,bad*1,msgtype*10
integer dgen(12),sent(63),recd(12),era(51) integer dgen(12),sent(63),recd(12),era(51)
logical text
nargs=iargc() nargs=iargc()
if(nargs.ne.1) then if(nargs.ne.1) then
@ -14,36 +13,53 @@ program JT65code
go to 999 go to 999
endif endif
call getarg(1,msg0) !Get message from command line call getarg(1,msg) !Get message from command line
msg=msg0 call fmtmsg(msg,iz) !To upper, collapse mult blanks
msg0=msg !Input message
call chkmsg(msg,cok,nspecial,flip) !See if it includes "OOO" report call chkmsg(msg,cok,nspecial,flip) !See if it includes "OOO" report
msg1=msg !Message without "OOO"
if(nspecial.gt.0) then !or is a shorthand message if(nspecial.gt.0) then !or is a shorthand message
write(*,1010) if(nspecial.eq.2) decoded="RO"
1010 format('Shorthand message.') if(nspecial.eq.3) decoded="RRR"
go to 999 if(nspecial.eq.4) decoded="73"
itype=-1
msgtype="Shorthand"
go to 10
endif endif
call packmsg(msg,dgen,text) !Pack message into 12 six-bit bytes call packmsg(msg1,dgen,itype) !Pack message into 12 six-bit bytes
write(*,1020) msg0 msgtype=""
1020 format('Message: ',a22) !Echo input message if(itype.eq.1) msgtype="Std Msg"
if(iand(dgen(10),8).ne.0) write(*,1030) !Is plain text bit set? if(itype.eq.2) msgtype="Type 1 pfx"
1030 format('Plain text.') if(itype.eq.3) msgtype="Type 1 sfx"
write(*,1040) dgen if(itype.eq.4) msgtype="Type 2 pfx"
1040 format('Packed message, 6-bit symbols: ',12i3) !Display packed symbols if(itype.eq.5) msgtype="Type 2 sfx"
if(itype.eq.6) msgtype="Free text"
call rs_encode(dgen,sent) !RS encode call rs_encode(dgen,sent) !RS encode
call interleave63(sent,1) !Interleave channel symbols call interleave63(sent,1) !Interleave channel symbols
call graycode(sent,63,1,sent) !Apply Gray code call graycode(sent,63,1,sent) !Apply Gray code
write(*,1050) sent
1050 format('Information-carrying channel symbols:'/(i5,20i3))
call graycode(sent,63,-1,sent) call graycode(sent,63,-1,sent)
call interleave63(sent,-1) call interleave63(sent,-1)
call rs_decode(sent,era,0,recd,nerr) call rs_decode(sent,era,0,recd,nerr)
call unpackmsg(recd,decoded) !Unpack the user message call unpackmsg(recd,decoded) !Unpack the user message
write(*,1060) decoded,cok if(cok.eq."OOO") decoded(20:22)=cok
1060 format('Decoded message: ',a22,2x,a3) call fmtmsg(decoded,iz)
10 write(*,1010)
1010 format("Message Decoded Err"/ &
"-----------------------------------------------------------------")
bad=" "
if(decoded.ne.msg0) bad="*"
write(*,1020) msg0,decoded,bad,itype,msgtype
1020 format(a22,2x,a22,3x,a1,i3,": ",a10)
if(nspecial.gt.0) go to 999
write(*,1030) dgen
1030 format(/'Packed message, 6-bit symbols ',12i3) !Display packed symbols
write(*,1040) sent
1040 format(/'Information-carrying channel symbols'/(i5,20i3))
999 end program JT65code 999 end program JT65code

View File

@ -2,7 +2,7 @@ program jt9code
! Generate simulated data for testing of WSJT-X ! Generate simulated data for testing of WSJT-X
character msg*22,msg0*22,decoded*22 character msg*22,msg0*22,decoded*22,bad*1,msgtype*10
integer*4 i4tone(85) !Channel symbols (values 0-8) integer*4 i4tone(85) !Channel symbols (values 0-8)
include 'jt9sync.f90' include 'jt9sync.f90'
@ -12,18 +12,30 @@ program jt9code
go to 999 go to 999
endif endif
call getarg(1,msg0) call getarg(1,msg)
write(*,1000) msg0 call fmtmsg(msg,iz) !To upper, collapse mult blanks
1000 format('Message:',3x,a22) msg0=msg !Input message
msg=msg0
ichk=0 ichk=0
itext=0 call genjt9(msg,ichk,decoded,i4tone,itype) !Encode message into tone #s
call genjt9(msg,ichk,decoded,i4tone,itext) !Encode message into tone #s
write(*,1002) i4tone msgtype=""
1002 format('Channel symbols:'/(30i2)) if(itype.eq.1) msgtype="Std Msg"
if(itext.eq.0) write(*,1004) decoded if(itype.eq.2) msgtype="Type 1 pfx"
1004 format('Decoded message:',1x,a22) if(itype.eq.3) msgtype="Type 1 sfx"
if(itext.ne.0) write(*,1005) decoded if(itype.eq.4) msgtype="Type 2 pfx"
1005 format('Decoded message:',1x,a22,3x,'(free text)') if(itype.eq.5) msgtype="Type 2 sfx"
if(itype.eq.6) msgtype="Free text"
write(*,1010)
1010 format("Message Decoded Err"/ &
"-----------------------------------------------------------------")
bad=" "
if(decoded.ne.msg0) bad="*"
write(*,1020) msg0,decoded,bad,itype,msgtype
1020 format(a22,2x,a22,3x,a1,i3,": ",a10)
write(*,1030) i4tone
1030 format(/'Channel symbols'/(30i2))
999 end program jt9code 999 end program jt9code

View File

@ -1,4 +1,16 @@
subroutine packmsg(msg,dat,text) subroutine packmsg(msg,dat,itype)
! Packs a JT4/JT9/JT65 message into twelve 6-bit symbols
! itype Message Type
!--------------------
! 1 Standardd message
! 2 Type 1 prefix
! 3 Type 1 suffix
! 4 Type 2 prefix
! 5 Type 2 suffix
! 6 Free text
! -1 Does not decode correctly
parameter (NBASE=37*36*10*27*27*27) parameter (NBASE=37*36*10*27*27*27)
parameter (NBASE2=262178562) parameter (NBASE2=262178562)
@ -7,24 +19,12 @@ subroutine packmsg(msg,dat,text)
character*12 c1,c2 character*12 c1,c2
character*4 c3 character*4 c3
character*6 grid6 character*6 grid6
logical text1,text2,text3,text logical text1,text2,text3
text=.false. itype=1
! Convert all letters to upper case call fmtmsg(msg,iz)
iz=22
do i=1,22
if(msg(i:i).ge.'a' .and. msg(i:i).le.'z') &
msg(i:i)= char(ichar(msg(i:i))+ichar('A')-ichar('a'))
if(msg(i:i).ne.' ') iz=i
enddo
do iter=1,5 !Collapse multiple blanks into one
ib2=index(msg(1:iz),' ')
if(ib2.lt.1) go to 5
msg=msg(1:ib2)//msg(ib2+2:)
iz=iz-1
enddo
5 if(msg(1:6).eq.'CQ DX ') msg(3:3)='9' if(msg(1:6).eq.'CQ DX ') msg(3:3)='9'
! See if it's a CQ message ! See if it's a CQ message
if(msg(1:3).eq.'CQ ') then if(msg(1:3).eq.'CQ ') then
@ -60,12 +60,14 @@ subroutine packmsg(msg,dat,text)
c3=' ' c3=' '
if(ic.ge.ib+1) c3=msg(ib+1:ic) if(ic.ge.ib+1) c3=msg(ib+1:ic)
if(c3.eq.'OOO ') c3=' ' !Strip out the OOO flag if(c3.eq.'OOO ') c3=' ' !Strip out the OOO flag
call getpfx1(c1,k1,kk) call getpfx1(c1,k1,nv2a)
if(kk.ne.0) go to 10 !Tnx to DL9RDZ for reminding me! if(nv2a.ge.4) go to 10
call packcall(c1,nc1,text1) call packcall(c1,nc1,text1)
call getpfx1(c2,k2,nv2) if(text1) go to 10
call getpfx1(c2,k2,nv2b)
call packcall(c2,nc2,text2) call packcall(c2,nc2,text2)
if(nv2.eq.0) then if(text2) go to 10
if(nv2a.eq.2 .or. nv2a.eq.3 .or. nv2b.eq.2 .or. nv2b.eq.3) then
if(k1.lt.0 .or. k2.lt.0 .or. k1*k2.ne.0) go to 10 if(k1.lt.0 .or. k2.lt.0 .or. k1*k2.ne.0) go to 10
if(k2.gt.0) k2=k2+450 if(k2.gt.0) k2=k2+450
k=max(k1,k2) k=max(k1,k2)
@ -75,29 +77,31 @@ subroutine packmsg(msg,dat,text)
endif endif
endif endif
call packgrid(c3,ng,text3) call packgrid(c3,ng,text3)
if(nv2.eq.0 .and. (.not.text1) .and. (.not.text2) .and. &
if(nv2a.lt.4 .and. nv2b.lt.4 .and. (.not.text1) .and. (.not.text2) .and. &
(.not.text3)) go to 20 (.not.text3)) go to 20
if(nv2.gt.0) then
if(nv2.eq.1) then nc1=0
if(c1(1:3).eq.'CQ ') nc1=262178563 + k2 if(nv2b.eq.4) then
if(c1(1:4).eq.'QRZ ') nc1=264002072 + k2 if(c1(1:3).eq.'CQ ') nc1=262178563 + k2
if(c1(1:3).eq.'DE ') nc1=265825581 + k2 if(c1(1:4).eq.'QRZ ') nc1=264002072 + k2
endif if(c1(1:3).eq.'DE ') nc1=265825581 + k2
if(nv2.eq.2) then else if(nv2b.eq.5) then
if(c1(1:3).eq.'CQ ') nc1=267649090 + k2 if(c1(1:3).eq.'CQ ') nc1=267649090 + k2
if(c1(1:4).eq.'QRZ ') nc1=267698375 + k2 if(c1(1:4).eq.'QRZ ') nc1=267698375 + k2
if(c1(1:3).eq.'DE ') nc1=267747660 + k2 if(c1(1:3).eq.'DE ') nc1=267747660 + k2
endif
go to 20
endif endif
if(nc1.ne.0) go to 20
! The message will be treated as plain text. ! The message will be treated as plain text.
10 text=.true. 10 itype=6
call packtext(msg,nc1,nc2,ng) call packtext(msg,nc1,nc2,ng)
ng=ng+32768 ng=ng+32768
! Encode data into 6-bit words ! Encode data into 6-bit words
20 dat(1)=iand(ishft(nc1,-22),63) !6 bits 20 continue
if(itype.ne.6) itype=max(nv2a,nv2b)
dat(1)=iand(ishft(nc1,-22),63) !6 bits
dat(2)=iand(ishft(nc1,-16),63) !6 bits dat(2)=iand(ishft(nc1,-16),63) !6 bits
dat(3)=iand(ishft(nc1,-10),63) !6 bits dat(3)=iand(ishft(nc1,-10),63) !6 bits
dat(4)=iand(ishft(nc1, -4),63) !6 bits dat(4)=iand(ishft(nc1, -4),63) !6 bits
@ -112,3 +116,4 @@ subroutine packmsg(msg,dat,text)
return return
end subroutine packmsg end subroutine packmsg

View File

@ -2,11 +2,10 @@ logical*1 function stdmsg(msg0)
character*22 msg0,msg character*22 msg0,msg
integer dat(12) integer dat(12)
logical text
call packmsg(msg0,dat,text) call packmsg(msg0,dat,itype)
call unpackmsg(dat,msg) call unpackmsg(dat,msg)
stdmsg=msg.eq.msg0 .and. (.not.text) stdmsg=(msg.eq.msg0) .and. (itype.ge.0)
return return
end function stdmsg end function stdmsg

View File

@ -1508,19 +1508,19 @@ void MainWindow::guiUpdate()
ba2msg(ba,message); ba2msg(ba,message);
// ba2msg(ba,msgsent); // ba2msg(ba,msgsent);
int len1=22; int len1=22;
int ichk=0,itext=0; int ichk=0,itype=0;
if(m_modeTx=="JT9") genjt9_(message if(m_modeTx=="JT9") genjt9_(message
, &ichk , &ichk
, msgsent , msgsent
, const_cast<int *> (itone) , const_cast<int *> (itone)
, &itext , &itype
, len1 , len1
, len1); , len1);
if(m_modeTx=="JT65") gen65_(message if(m_modeTx=="JT65") gen65_(message
, &ichk , &ichk
, msgsent , msgsent
, const_cast<int *> (itone) , const_cast<int *> (itone)
, &itext , &itype
, len1 , len1
, len1); , len1);
msgsent[22]=0; msgsent[22]=0;
@ -1545,7 +1545,7 @@ void MainWindow::guiUpdate()
t=""; t="";
if(w.length()==3) t=w[2]; if(w.length()==3) t=w[2];
icw[0]=0; icw[0]=0;
m_sent73=(t=="73" or itext!=0); m_sent73=(t=="73" or itype==6);
if(m_sent73) { if(m_sent73) {
if(m_config.id_after_73 ()) icw[0]=m_ncw; if(m_config.id_after_73 ()) icw[0]=m_ncw;
if(m_config.prompt_to_log () && !m_tune) logQSOTimer->start(200); if(m_config.prompt_to_log () && !m_tune) logQSOTimer->start(200);
@ -1560,7 +1560,7 @@ void MainWindow::guiUpdate()
} }
QString t2=QDateTime::currentDateTimeUtc().toString("hhmm"); QString t2=QDateTime::currentDateTimeUtc().toString("hhmm");
if(itext==0 and w.length()>=3 and w[1]==m_config.my_callsign ()) { if(itype<6 and w.length()>=3 and w[1]==m_config.my_callsign ()) {
int i1; int i1;
bool ok; bool ok;
i1=t.toInt(&ok); i1=t.toInt(&ok);
@ -1577,7 +1577,7 @@ void MainWindow::guiUpdate()
} }
} }
} }
if(itext==1 or (w.length()==3 and w[2]=="73")) m_qsoStop=t2; if(itype==6 or (w.length()==3 and w[2]=="73")) m_qsoStop=t2;
m_restart=false; m_restart=false;
} }
@ -2027,9 +2027,10 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4);
msgtype(t, ui->tx6); msgtype(t, ui->tx6);
if(m_config.my_callsign ()!=myBase) { if(m_config.my_callsign ()!=myBase) {
if(shortList(m_config.my_callsign ())) { if(shortList(m_config.my_callsign ())) {
t=hisCall + " " + m_config.my_callsign ();
msgtype(t, ui->tx1);
t="CQ " + m_config.my_callsign (); t="CQ " + m_config.my_callsign ();
msgtype(t, ui->tx6); msgtype(t, ui->tx6);
} else { } else {
@ -2044,7 +2045,10 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
if(hisCall!=hisBase) { if(hisCall!=hisBase) {
if(shortList(hisCall)) { if(shortList(hisCall)) {
t=hisCall + " " + m_config.my_callsign (); t=hisCall + " " + m_config.my_callsign ();
msgtype(t, ui->tx2); msgtype(t, ui->tx1);
} else {
t=hisCall + " 73";
msgtype(t, ui->tx5->lineEdit());
} }
} }
} }
@ -2196,17 +2200,17 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
t=t.toUpper(); t=t.toUpper();
QByteArray s=t.toUpper().toLocal8Bit(); QByteArray s=t.toUpper().toLocal8Bit();
ba2msg(s,message); ba2msg(s,message);
int ichk=1,itext=0; int ichk=1,itype=0;
genjt9_(message genjt9_(message
, &ichk , &ichk
, msgsent , msgsent
, const_cast<int *> (itone) , const_cast<int *> (itone)
, &itext , &itype
, len1 , len1
, len1); , len1);
msgsent[22]=0; msgsent[22]=0;
bool text=false; bool text=false;
if(itext!=0) text=true; if(itype==6) text=true;
QString t1; QString t1;
t1.fromLatin1(msgsent); t1.fromLatin1(msgsent);
if(text) t1=t1.mid(0,13); if(text) t1=t1.mid(0,13);

View File

@ -216,13 +216,19 @@ private:
Frequency m_dialFreq; Frequency m_dialFreq;
Detector m_detector;
SoundInput m_soundInput;
Modulator m_modulator;
SoundOutput m_soundOutput;
QThread * m_audioThread;
qint64 m_msErase; qint64 m_msErase;
qint64 m_secBandChanged; qint64 m_secBandChanged;
qint32 m_waterfallAvg; qint32 m_waterfallAvg;
qint32 m_ntx; qint32 m_ntx;
qint32 m_timeout; qint32 m_timeout;
int m_XIT; qint32 m_XIT;
qint32 m_setftx; qint32 m_setftx;
qint32 m_ndepth; qint32 m_ndepth;
qint32 m_sec0; qint32 m_sec0;
@ -230,14 +236,6 @@ private:
qint32 m_nutc0; qint32 m_nutc0;
qint32 m_nrx; qint32 m_nrx;
qint32 m_hsym; qint32 m_hsym;
Detector m_detector;
SoundInput m_soundInput;
Modulator m_modulator;
SoundOutput m_soundOutput;
QThread * m_audioThread;
qint32 m_TRperiod; qint32 m_TRperiod;
qint32 m_nsps; qint32 m_nsps;
qint32 m_hsymStop; qint32 m_hsymStop;
@ -246,7 +244,6 @@ private:
qint32 m_nsave; qint32 m_nsave;
qint32 m_ncw; qint32 m_ncw;
qint32 m_secID; qint32 m_secID;
QString m_band;
qint32 m_repeatMsg; qint32 m_repeatMsg;
qint32 m_watchdogLimit; qint32 m_watchdogLimit;
qint32 m_astroFont; qint32 m_astroFont;
@ -339,6 +336,7 @@ private:
QString m_cmnd; QString m_cmnd;
QString m_msgSent0; QString m_msgSent0;
QString m_fileToSave; QString m_fileToSave;
QString m_band;
QStringList m_prefix; QStringList m_prefix;
QStringList m_suffix; QStringList m_suffix;