diff --git a/CMakeLists.txt b/CMakeLists.txt index 694371d97..ed9aaff05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -556,6 +556,7 @@ set (wsjt_FSRCS lib/sync9w.f90 lib/synciscat.f90 lib/timf2.f90 + lib/to_contest_msg.f90 lib/tweak1.f90 lib/twkfreq.f90 lib/fsk4hf/twkfreq1.f90 diff --git a/decodedtext.cpp b/decodedtext.cpp index 4cd085f27..e8a293fab 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -2,20 +2,22 @@ #include #include +#include extern "C" { - bool stdmsg_(const char* msg, int len); + bool stdmsg_(char const * msg, bool contest_mode, char const * mygrid, int len_msg, int len_grid); } namespace { - QRegularExpression words_re {R"(^(?:(?(?:CQ|DE|QRZ)(?:\s?DX|\s(?:[A-Z]{2}|\d{3}))|[A-Z0-9/]+)\s)(?:(?[A-Z0-9/]+)(?:\sR\s)?(?:\s(?[-+A-Z0-9]+)(?:\s(?OOO))?)?)?)"}; + QRegularExpression words_re {R"(^(?:(?(?:CQ|DE|QRZ)(?:\s?DX|\s(?:[A-Z]{2}|\d{3}))|[A-Z0-9/]+)\s)(?:(?[A-Z0-9/]+)(?:\s(?[-+A-Z0-9]+)(?:\s(?(?:OOO|(?!RR73)[A-R]{2}[0-9]{2})))?)?)?)"}; } -DecodedText::DecodedText (QString const& the_string) +DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString const& my_grid) : string_ {the_string} , padding_ {the_string.indexOf (" ") > 4 ? 2 : 0} // allow for // seconds + , contest_mode_ {contest_mode} , message_ {string_.mid (column_qsoText + padding_).trimmed ()} , is_standard_ {false} { @@ -39,8 +41,16 @@ DecodedText::DecodedText (QString const& the_string) // remove DXCC entity and worked B4 status. TODO need a better way to do this message_ = message_.left (eom_pos + 1); } - // stdmsg is a fortran routine that packs the text, unpacks it and compares the result - is_standard_ = stdmsg_ ((message_ + " ").toLatin1 ().constData (),22); + // stdmsg is a fortran routine that packs the text, unpacks it + // and compares the result + auto message_c_string = message_.toLocal8Bit (); + message_c_string += QByteArray {22 - message_c_string.size (), ' '}; + auto grid_c_string = my_grid.toLocal8Bit (); + grid_c_string += QByteArray {6 - grid_c_string.size (), ' '}; + is_standard_ = stdmsg_ (message_c_string.constData () + , contest_mode_ + , grid_c_string.constData () + , 22, 6); } }; @@ -51,7 +61,11 @@ QStringList DecodedText::messageWords () const // extract up to the first four message words return words_re.match (message_).capturedTexts (); } - return message_.split (' '); // simple word split for free text messages + // simple word split for free text messages + auto words = message_.split (' ', QString::SkipEmptyParts); + // add whole message as item 0 to mimic RE capture list + words.prepend (message_); + return words; } QString DecodedText::CQersCall() const @@ -157,22 +171,10 @@ void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid) const auto const& match = words_re.match (message_); call = match.captured ("word2"); grid = match.captured ("word3"); - - // auto msg = string_; - // if(msg.mid(4,1)!=" ") msg=msg.mid(0,4)+msg.mid(6,-1); //Remove seconds from UTC - // msg = msg.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText + padding_); - // int i1 = msg.indexOf (" "); - // call = msg.mid (i1 + 1); - // int i2 = call.indexOf (" "); - // if (" R " == call.mid (i2, 3)) // MSK144 contest mode report - // { - // grid = call.mid (i2 + 3, 4); - // } - // else - // { - // grid = call.mid (i2 + 1, 4); - // } - // call = call.left (i2).replace (">", ""); + if (contest_mode_ && "R" == grid) + { + grid = match.captured ("word4"); + } } unsigned DecodedText::timeInSeconds() const diff --git a/decodedtext.h b/decodedtext.h index 18859026a..93ef67e9c 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -29,7 +29,7 @@ class DecodedText { public: - explicit DecodedText (QString const&); + explicit DecodedText (QString const& message, bool, QString const& my_grid); QString string() const { return string_; }; QStringList messageWords () const; @@ -77,6 +77,7 @@ private: QString string_; int padding_; + bool contest_mode_; QString message_; bool is_standard_; }; diff --git a/doc/common/links.adoc b/doc/common/links.adoc index d000c1a02..d9b84fbe5 100644 --- a/doc/common/links.adoc +++ b/doc/common/links.adoc @@ -104,6 +104,7 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes. :nh6z: http://www.nh6z.net/Amatuer_Radio_Station_NH6Z/Other_Peoples_Software.html[here] :omnirig: http://www.dxatlas.com/OmniRig/Files/OmniRig.zip[Download] :osx: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-Darwin.dmg[wsjtx-{VERSION}-Darwin.dmg] +:QRA64_EME: http://physics.princeton.edu/pulsar/K1JT/QRA64_EME.pdf[QRA64 for microwave EME] :svn: http://subversion.apache.org/packages.html#windows[Subversion] :win32: http://physics.princeton.edu/pulsar/K1JT/wsjtx-{VERSION}-win32.exe[wsjtx-{VERSION}-win32.exe] :wsjt_svn: http://sourceforge.net/p/wsjt/wsjt/HEAD/tree/[WSJT Source Repository] diff --git a/doc/user_guide/en/protocols.adoc b/doc/user_guide/en/protocols.adoc index 101ad476e..a25df3f22 100644 --- a/doc/user_guide/en/protocols.adoc +++ b/doc/user_guide/en/protocols.adoc @@ -149,13 +149,12 @@ separation is 110250/4096 = 26.92 Hz multiplied by n for JT65A, with n [[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. +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 diff --git a/doc/user_guide/en/vhf-features.adoc b/doc/user_guide/en/vhf-features.adoc index 4a595daaa..635da5dc7 100644 --- a/doc/user_guide/en/vhf-features.adoc +++ b/doc/user_guide/en/vhf-features.adoc @@ -158,15 +158,14 @@ image::JT65B.png[align="center",alt="JT65B"] === QRA64 -QRA64 is an experimental mode in Version 1.8 of _WSJT-X_. The mode is -designed especially for EME on VHF and higher bands; its operation is -generally similar to JT4 and JT65. The following screen shot shows an -example of a QRA64C transmission from DL7YC recorded at G3WDG over the -EME path at 24 GHz. Doppler spread on the path was 78 Hz, so although -the signal is reasonably strong its tones are broadened enough to make -them hard to see on the waterfall. The triangular red marker below -the frequency scale shows that the decoder has achieved -synchronization with a signal at approximately 967 Hz. +QRA64 is designed for EME on VHF and higher bands; its +operation is generally similar to JT4 and JT65. The following screen +shot shows an example of a QRA64C transmission from DL7YC recorded at +G3WDG over the EME path at 24 GHz. Doppler spread on the path was 78 +Hz, so although the signal is reasonably strong its tones are +broadened enough to make them hard to see on the waterfall. The +triangular red marker below the frequency scale shows that the decoder +has achieved synchronization with a signal at approximately 967 Hz. image::QRA64.png[align="center",alt="QRA64"] @@ -192,11 +191,12 @@ initially, as the QRA64 tones are often not visible on the waterfall. The box labeled *Tx6* switches the Tx6 message from 1000Hz to 1250Hz to indicate to the other station that you are ready to receive messages. - TIP: QRA64 is different from JT65 in that the decoder attempts to find and decode only a single signal in the receiver passband. If many signals are present you may be able to decode them by double-clicking -on the lowest tone of each one in the waterfall. +on the lowest tone of each one in the waterfall. + +TIP: G3WDG has prepared a more detailed tutorial on using {QRA64_EME}. === ISCAT diff --git a/lib/contest72.f90 b/lib/contest72.f90 index 2a23c1181..f637c4327 100644 --- a/lib/contest72.f90 +++ b/lib/contest72.f90 @@ -36,10 +36,8 @@ program contest72 1001 format(a22) endif msg=msg0 - if(bcontest) call to_contest_msg(msg0,msg) - call packmsg(msg,dat,itype) - call unpackmsg(dat,msg1) - call fix_contest_msg(mygrid,msg1) + call packmsg(msg,dat,itype,bcontest) + call unpackmsg(dat,msg1,bcontest,mygrid) ok=msg1.eq.msg0 if(msg0.eq.' ') then write(*,1002) @@ -78,9 +76,9 @@ program contest72 cycle endif - call packmsg(msg,dat,itype) + call packmsg(msg,dat,itype,.false.) write(ct1,1010) dat - call packtext(msg,nc1,nc2,ng) + call packtext(msg,nc1,nc2,ng,.false.,'') ! write(ct2,1012) nc1,nc2,ng+32768 !1012 format(2b28.28,b16.16) ! write(*,1014) ct1 diff --git a/lib/encode4.f90 b/lib/encode4.f90 index 974f0c2b7..4e73699b5 100644 --- a/lib/encode4.f90 +++ b/lib/encode4.f90 @@ -9,7 +9,7 @@ subroutine encode4(message,ncode) integer*1 data0(13),symbol(216) call chkmsg(message,cok,nspecial,flip) - call packmsg(message,dgen,itype) !Pack 72-bit message into 12 six-bit symbols + call packmsg(message,dgen,itype,.false.) !Pack 72-bit message into 12 six-bit symbols call entail(dgen,data0) call encode232(data0,206,symbol) !Convolutional encoding call interleave4(symbol,1) !Apply JT4 interleaving diff --git a/lib/extract.f90 b/lib/extract.f90 index 2bc262e0b..3e7fa6fe1 100644 --- a/lib/extract.f90 +++ b/lib/extract.f90 @@ -122,7 +122,7 @@ subroutine extract(s3,nadd,mode65,ntrials,naggressive,ndepth,nflip, & correct(1:63)=tmp(1:63) call interleave63(correct,63,1) call graycode65(correct,63,1) - call unpackmsg(dat4,decoded) !Unpack the user message + call unpackmsg(dat4,decoded,.false.,' ') !Unpack the user message ncount=0 if(iand(dat4(10),8).ne.0) ltext=.true. endif diff --git a/lib/extract4.f90 b/lib/extract4.f90 index ce8fb86a5..46c317c29 100644 --- a/lib/extract4.f90 +++ b/lib/extract4.f90 @@ -57,7 +57,7 @@ subroutine extract4(sym0,ncount,decoded) read(c72,1102) data4 1102 format(12b6) - call unpackmsg(data4,decoded) + call unpackmsg(data4,decoded,.false.,' ') if(decoded(1:6).eq.'000AAA') then ! decoded='***WRONG MODE?***' decoded=' ' diff --git a/lib/fsk4hf/genft8.f90 b/lib/fsk4hf/genft8.f90 index 9c7962b98..1b1352ea6 100644 --- a/lib/fsk4hf/genft8.f90 +++ b/lib/fsk4hf/genft8.f90 @@ -6,10 +6,9 @@ subroutine genft8(msg,mygrid,bcontest,msgsent,msgbits,itone) use packjt include 'ft8_params.f90' character*22 msg,msgsent - character*6 mygrid,g1,g2,g3,g4 + character*6 mygrid character*87 cbits - logical*1 bcontest - logical isgrid + logical bcontest integer*4 i4Msg6BitWords(12) !72-bit message as 6-bit words integer*1 msgbits(KK),codeword(3*ND) integer*1, target:: i1Msg8BitBytes(11) @@ -17,41 +16,8 @@ subroutine genft8(msg,mygrid,bcontest,msgsent,msgbits,itone) integer icos7(0:6) data icos7/2,5,6,0,4,1,3/ !Costas 7x7 tone pattern - isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. & - g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. & - g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73' - - if(bcontest) then - i0=index(msg,' R ') + 3 !Check for ' R ' in message - g1=msg(i0:i0+3)//' ' - if(isgrid(g1)) then !Check for ' R grid' - call grid2deg(g1,dlong,dlat) - dlong=dlong+180.0 - if(dlong.gt.180.0) dlong=dlong-360.0 - dlat=-dlat - call deg2grid(dlong,dlat,g2) !g2=antipodes grid - msg=msg(1:i0-3)//g2(1:4) !Send message with g2 - endif - endif - - call packmsg(msg,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent - - if(bcontest) then - i1=index(msgsent(8:22),' ') + 8 - g3=msgsent(i1:i1+3)//' ' - if(isgrid(g3)) then - call azdist(mygrid,g3,0.d0,nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter) - if(ndkm.gt.10000) then - call grid2deg(g3,dlong,dlat) - dlong=dlong+180.0 - if(dlong.gt.180.0) dlong=dlong-360.0 - dlat=-dlat - call deg2grid(dlong,dlat,g4) - msgsent=msgsent(1:i1-1)//'R '//g4(1:4) - endif - endif - endif + call packmsg(msg,i4Msg6BitWords,itype,bcontest) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,bcontest,mygrid) !Unpack to get msgsent i3bit=0 !### temporary ### write(cbits,1000) i4Msg6BitWords,32*i3bit diff --git a/lib/fsk4hf/ldpcsim168.f90 b/lib/fsk4hf/ldpcsim168.f90 index 9191f7e27..a1aee3eba 100644 --- a/lib/fsk4hf/ldpcsim168.f90 +++ b/lib/fsk4hf/ldpcsim168.f90 @@ -66,8 +66,8 @@ allocate ( rxdata(N), llr(N) ) ! msg="K1JT K9AN EN50" msg="G4WJS K9AN EN50" - call packmsg(msg,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,'') !Unpack to get msgsent write(*,*) "message sent ",msgsent i4=0 diff --git a/lib/fsk4hf/ldpcsim174.f90 b/lib/fsk4hf/ldpcsim174.f90 index 9c4a72893..b8640f6d8 100644 --- a/lib/fsk4hf/ldpcsim174.f90 +++ b/lib/fsk4hf/ldpcsim174.f90 @@ -71,8 +71,8 @@ allocate ( rxdata(N), llr(N) ) msg="K1JT K9AN EN50" ! msg="G4WJS K9AN EN50" - call packmsg(msg,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,'') !Unpack to get msgsent write(*,*) "message sent ",msgsent i4=0 diff --git a/lib/gen4.f90 b/lib/gen4.f90 index dcf0feee6..7b06be8cb 100644 --- a/lib/gen4.f90 +++ b/lib/gen4.f90 @@ -26,8 +26,8 @@ subroutine gen4(msg0,ichk,msgsent,itone,itype) message=msg0 call fmtmsg(message,iz) - call packmsg(message,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent + call packmsg(message,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent if(ichk.ne.0) go to 999 call encode4(message,itone) !Encode the information bits i1=index(message,'-') diff --git a/lib/gen65.f90 b/lib/gen65.f90 index af036c2a9..ab61fd337 100644 --- a/lib/gen65.f90 +++ b/lib/gen65.f90 @@ -44,8 +44,8 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype) ntest=0 if(flip.lt.0.0) ntest=1 if(nspecial.eq.0) then - call packmsg(message,dgen,itype) !Pack message into 72 bits - call unpackmsg(dgen,msgsent) !Unpack to get message sent + call packmsg(message,dgen,itype,.false.) !Pack message into 72 bits + call unpackmsg(dgen,msgsent,.false.,' ') !Unpack to get message sent msgsent(20:22)=cok call fmtmsg(msgsent,iz) if(ichk.ne.0) go to 999 !Return if checking only diff --git a/lib/gen9.f90 b/lib/gen9.f90 index 144e646d8..503ef6d3d 100644 --- a/lib/gen9.f90 +++ b/lib/gen9.f90 @@ -37,8 +37,8 @@ subroutine gen9(msg0,ichk,msgsent,i4tone,itype) message=message(i+1:) enddo - call packmsg(message,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent + call packmsg(message,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent if(ichk.ne.0) go to 999 call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, make 8-bit bytes nsym2=206 diff --git a/lib/genmsk144.f90 b/lib/genmsk144.f90 index 7d4d200e7..62fc00a14 100644 --- a/lib/genmsk144.f90 +++ b/lib/genmsk144.f90 @@ -23,7 +23,7 @@ subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype) character*22 msg0 character*22 message !Message to be generated character*22 msgsent !Message as it will be received - character*6 mygrid,g1,g2,g3,g4 + character*6 mygrid integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words integer*4 i4tone(144) ! integer*1, target:: i1Msg8BitBytes(10) !80 bits represented in 10 bytes @@ -32,19 +32,15 @@ subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype) integer*1 bitseq(144) !Tone #s, data and sync (values 0-1) integer*1 i1hash(4) integer*1 s8(8) - logical*1 bcontest + logical bcontest real*8 pp(12) real*8 xi(864),xq(864),pi,twopi data s8/0,1,1,1,0,0,1,0/ equivalence (ihash,i1hash) - logical first,isgrid + logical first data first/.true./ save - isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. & - g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. & - g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73' - if(first) then first=.false. nsym=128 @@ -81,37 +77,8 @@ subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype) go to 999 endif - if(bcontest) then - i0=index(message,' R ') + 3 !Check for ' R ' in message - g1=message(i0:i0+3)//' ' - if(isgrid(g1)) then !Check for ' R grid' - call grid2deg(g1,dlong,dlat) - dlong=dlong+180.0 - if(dlong.gt.180.0) dlong=dlong-360.0 - dlat=-dlat - call deg2grid(dlong,dlat,g2) !g2=antipodes grid - message=message(1:i0-3)//g2(1:4) !Send message with g2 - endif - endif - - call packmsg(message,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent - - if(bcontest) then - i1=index(msgsent(8:22),' ') + 8 - g3=msgsent(i1:i1+3)//' ' - if(isgrid(g3)) then - call azdist(mygrid,g3,0.d0,nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter) - if(ndkm.gt.10000) then - call grid2deg(g3,dlong,dlat) - dlong=dlong+180.0 - if(dlong.gt.180.0) dlong=dlong-360.0 - dlat=-dlat - call deg2grid(dlong,dlat,g4) - msgsent=msgsent(1:i1-1)//'R '//g4(1:4) - endif - endif - endif + call packmsg(message,i4Msg6BitWords,itype,bcontest) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,bcontest,mygrid) !Unpack to get msgsent if(ichk.eq.1) go to 999 i4=0 diff --git a/lib/genqra64.f90 b/lib/genqra64.f90 index 4931342eb..819f13cc7 100644 --- a/lib/genqra64.f90 +++ b/lib/genqra64.f90 @@ -37,8 +37,8 @@ subroutine genqra64(msg0,ichk,msgsent,itone,itype) enddo call chkmsg(message,cok,nspecial,flip) - call packmsg(message,dgen,itype) !Pack message into 72 bits - call unpackmsg(dgen,msgsent) !Unpack to get message sent + call packmsg(message,dgen,itype,.false.) !Pack message into 72 bits + call unpackmsg(dgen,msgsent,.false.,' ') !Unpack to get message sent if(ichk.ne.0) go to 999 !Return if checking only call qra64_enc(dgen,sent) !Encode using QRA64 diff --git a/lib/hint65.f90 b/lib/hint65.f90 index 48e1f1847..3d1853306 100644 --- a/lib/hint65.f90 +++ b/lib/hint65.f90 @@ -88,7 +88,7 @@ subroutine hint65(s3,mrs,mrs2,nadd,nflip,mycall,hiscall,hisgrid,qual,decoded) if(m.eq.2) msg='CQ '//call2(i)//' '//grid2(i) endif call fmtmsg(msg,iz) - call packmsg(msg,dgen,itype) !Pack message into 72 bits + call packmsg(msg,dgen,itype,.false.) !Pack message into 72 bits call rs_encode(dgen,sym_rev) !RS encode sym(0:62)=sym_rev(62:0:-1) sym1(0:62,j)=sym diff --git a/lib/jt65code.f90 b/lib/jt65code.f90 index e20166b8a..4f2a4e037 100644 --- a/lib/jt65code.f90 +++ b/lib/jt65code.f90 @@ -61,7 +61,7 @@ program JT65code go to 10 endif - call packmsg(msg1,dgen,itype) !Pack message into 12 six-bit bytes + call packmsg(msg1,dgen,itype,.false.) !Pack message into 12 six-bit bytes msgtype="" if(itype.eq.1) msgtype="Std Msg" if(itype.eq.2) msgtype="Type 1 pfx" @@ -77,7 +77,7 @@ program JT65code call graycode(sent,63,-1,tmp) !Remove Gray code call interleave63(tmp,-1) !Remove interleaving call rs_decode(tmp,era,0,recd,nerr) !Decode the message - call unpackmsg(recd,decoded) !Unpack the user message + call unpackmsg(recd,decoded,.false.,' ') !Unpack the user message if(cok.eq."OOO") decoded(20:22)=cok call fmtmsg(decoded,iz) diff --git a/lib/jt65sim.f90 b/lib/jt65sim.f90 index 9101d185d..5f0a384f0 100644 --- a/lib/jt65sim.f90 +++ b/lib/jt65sim.f90 @@ -153,7 +153,7 @@ program jt65sim msg="K1ABC W9XYZ EN37" !### - call packmsg(msg,dgen,itype) !Pack message into 12 six-bit bytes + call packmsg(msg,dgen,itype,.false.) !Pack message into 12 six-bit bytes call rs_encode(dgen,sent) !Encode using RS(63,12) call interleave63(sent,1) !Interleave channel symbols call graycode65(sent,63,1) !Apply Gray code diff --git a/lib/jt9fano.f90 b/lib/jt9fano.f90 index 160c2e732..275e0e07c 100644 --- a/lib/jt9fano.f90 +++ b/lib/jt9fano.f90 @@ -84,7 +84,7 @@ subroutine jt9fano(i1SoftSymbols,limit,nlim,msg) enddo call unpackbits(i4DecodedBytes,nbytes,8,i1DecodedBits) call packbits(i1DecodedBits,12,6,i4Decoded6BitWords) - call unpackmsg(i4Decoded6BitWords,msg) !Unpack decoded msg + call unpackmsg(i4Decoded6BitWords,msg,.false.,' ') !Unpack decoded msg if(index(msg,'000AAA ').gt.0) msg=' ' endif diff --git a/lib/ldpcsim144.f90 b/lib/ldpcsim144.f90 index 70fa083fa..62c4838fd 100644 --- a/lib/ldpcsim144.f90 +++ b/lib/ldpcsim144.f90 @@ -53,8 +53,8 @@ allocate ( codeword(N), decoded(K), message(K) ) allocate ( lratio(N), rxdata(N), rxavgd(N), yy(N), llr(N) ) msg="K9AN K1JT EN50" - call packmsg(msg,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes - call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent + call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes + call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent write(*,*) "message sent ",msgsent i4=0 diff --git a/lib/packjt.f90 b/lib/packjt.f90 index 26a20cb94..f732f9806 100644 --- a/lib/packjt.f90 +++ b/lib/packjt.f90 @@ -392,7 +392,7 @@ subroutine packbits(dbits,nsymd,m0,sym) 900 return end subroutine unpackgrid - subroutine packmsg(msg0,dat,itype) + subroutine packmsg(msg0,dat,itype,bcontest) ! Packs a JT4/JT9/JT65 message into twelve 6-bit symbols @@ -413,10 +413,15 @@ subroutine packbits(dbits,nsymd,m0,sym) character*12 c1,c2 character*4 c3 character*6 grid6 - logical text1,text2,text3 + logical text1,text2,text3,bcontest - msg=msg0 itype=1 + if(bcontest) then + call to_contest_msg(msg0,msg) + else + msg=msg0 + end if + call fmtmsg(msg,iz) if(msg(1:6).eq.'CQ DX ') msg(3:3)='9' @@ -525,13 +530,13 @@ subroutine packbits(dbits,nsymd,m0,sym) return end subroutine packmsg - subroutine unpackmsg(dat,msg) + subroutine unpackmsg(dat,msg,bcontest,mygrid) parameter (NBASE=37*36*10*27*27*27) parameter (NGBASE=180*180) integer dat(:) - character c1*12,c2*12,grid*4,msg*22,grid6*6,psfx*4,junk2*4 - logical cqnnn + character c1*12,c2*12,grid*4,msg*22,grid6*6,psfx*4,junk2*4,mygrid*6 + logical cqnnn,bcontest cqnnn=.false. nc1=ishft(dat(1),22) + ishft(dat(2),16) + ishft(dat(3),10)+ & @@ -645,6 +650,8 @@ subroutine packbits(dbits,nsymd,m0,sym) msg(4:4).ge.'A' .and. msg(4:4).le.'Z' .and. & msg(5:5).eq.' ') msg='CQ '//msg(3:) + if(bcontest) call fix_contest_msg(mygrid,msg) + return end subroutine unpackmsg diff --git a/lib/qra64a.f90 b/lib/qra64a.f90 index 1090f8e1f..2f128ac0e 100644 --- a/lib/qra64a.f90 +++ b/lib/qra64a.f90 @@ -128,7 +128,7 @@ subroutine qra64a(dd,npts,nutc,nf1,nf2,nfqso,ntol,mode64,minsync,ndepth, & 10 decoded=' ' if(irc.ge.0) then - call unpackmsg(dat4,decoded) !Unpack the user message + call unpackmsg(dat4,decoded,.false.,' ') !Unpack the user message call fmtmsg(decoded,iz) if(index(decoded,"000AAA ").ge.1) then ! Suppress a certain type of garbage decode. diff --git a/lib/qra64code.f90 b/lib/qra64code.f90 index 629282240..0f9c16bfc 100644 --- a/lib/qra64code.f90 +++ b/lib/qra64code.f90 @@ -34,7 +34,7 @@ program QRA64code msg0=msg !Input message call chkmsg(msg,cok,nspecial,flip) !See if it includes "OOO" report msg1=msg !Message without "OOO" - call packmsg(msg1,dgen,itype) !Pack message into 12 six-bit bytes + call packmsg(msg1,dgen,itype,.false.) !Pack message into 12 six-bit bytes msgtype="" if(itype.eq.1) msgtype="Std Msg" if(itype.eq.2) msgtype="Type 1 pfx" @@ -45,7 +45,7 @@ program QRA64code call qra64_enc(dgen,sent) !Encode using QRA64 - call unpackmsg(dgen,decoded) !Unpack the user message + call unpackmsg(dgen,decoded,.false.,' ') !Unpack the user message call fmtmsg(decoded,iz) ii=imsg write(*,1020) ii,msg0,decoded,itype,msgtype diff --git a/lib/stdmsg.f90 b/lib/stdmsg.f90 index 97e842c1d..86666c8f2 100644 --- a/lib/stdmsg.f90 +++ b/lib/stdmsg.f90 @@ -1,11 +1,15 @@ -logical*1 function stdmsg(msg0) +function stdmsg(msg0,bcontest,mygrid) + use iso_c_binding, only: c_bool use packjt character*22 msg0,msg + character*6 mygrid integer dat(12) + logical(c_bool), value :: bcontest + logical(c_bool) :: stdmsg - call packmsg(msg0,dat,itype) - call unpackmsg(dat,msg) + call packmsg(msg0,dat,itype,logical(bcontest)) + call unpackmsg(dat,msg,logical(bcontest),mygrid) stdmsg=(msg.eq.msg0) .and. (itype.ge.0) .and. itype.ne.6 return diff --git a/lib/syncmsk.f90 b/lib/syncmsk.f90 index 32c36ce36..be28a3bbe 100644 --- a/lib/syncmsk.f90 +++ b/lib/syncmsk.f90 @@ -294,7 +294,7 @@ subroutine syncmsk(cdat,npts,jpk,ipk,idf,rmax,snr,metric,decoded) 1012 format(9b8.8) read(c72,1014) i4Msg6BitWords 1014 format(12b6.6) - call unpackmsg(i4Msg6BitWords,decoded) !Unpack to get msgsent + call unpackmsg(i4Msg6BitWords,decoded,.false.,' ') !Unpack to get msgsent endif if(decoded.ne.' ') exit enddo diff --git a/mainwindow.cpp b/mainwindow.cpp index abb2174ab..5fa713602 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1189,7 +1189,7 @@ void MainWindow::dataSink(qint64 frames) int ftol = ui->sbFtol->value (); freqcal_(&dec_data.d2[0],&k,&nkhz,&RxFreq,&ftol,&line[0],80); QString t=QString::fromLatin1(line); - DecodedText decodedtext {t}; + DecodedText decodedtext {t, false, m_config.my_grid ()}; ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), m_logBook,m_config.color_CQ(),m_config.color_MyCall(),m_config.color_DXCC(), m_config.color_NewCall()); @@ -1424,7 +1424,7 @@ void MainWindow::fastSink(qint64 frames) if(bmsk144 and (line[0]!=0)) { QString message {QString::fromLatin1 (line)}; - DecodedText decodedtext {message.replace (QChar::LineFeed, "")}; + DecodedText decodedtext {message.replace (QChar::LineFeed, ""), bcontest, m_config.my_grid ()}; ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), m_logBook,m_config.color_CQ(),m_config.color_MyCall(),m_config.color_DXCC(), m_config.color_NewCall()); @@ -2561,7 +2561,7 @@ void::MainWindow::fast_decode_done() if(narg[13]/8==narg[12]) message=message.trimmed().replace("<...>",m_calls); //Left (Band activity) window - DecodedText decodedtext {message.replace (QChar::LineFeed, "")}; + DecodedText decodedtext {message.replace (QChar::LineFeed, ""), "FT8" == m_mode && m_config.contestMode (), m_config.my_grid ()}; if(!m_bFastDone) { ui->decodedTextBrowser->displayDecodedText (decodedtext,m_baseCall,m_config.DXCC(), m_logBook,m_config.color_CQ(),m_config.color_MyCall(),m_config.color_DXCC(), @@ -2706,7 +2706,7 @@ void MainWindow::readFromStdout() //readFromStdout m_blankLine = false; } - DecodedText decodedtext {QString::fromUtf8 (t.constData ()).remove (QRegularExpression {"\r|\n"})}; + DecodedText decodedtext {QString::fromUtf8 (t.constData ()).remove (QRegularExpression {"\r|\n"}), "FT8" == m_mode && m_config.contestMode (), m_config.my_grid ()}; //Left (Band activity) window if(!bAvgMsg) { @@ -2807,6 +2807,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler && (REPLYING == m_QSOProgress || (!ui->tx1->isEnabled () && REPORT == m_QSOProgress)) && qAbs (ui->TxFreqSpinBox->value () - df) <= int (stop_tolerance) + && message_words.at (1) != "DE" && !message_words.at (1).contains (QRegularExpression {"(^(CQ|QRZ))|" + m_baseCall}) && message_words.at (2).contains (Radio::base_callsign (ui->dxCallEntry->text ()))) { // auto stop to avoid accidental QRM @@ -3642,7 +3643,7 @@ void MainWindow::doubleClickOnCall(bool alt, bool ctrl) cursor=ui->decodedTextBrowser2->textCursor(); } cursor.setPosition (cursor.selectionStart ()); - DecodedText message {cursor.block ().text ()}; + DecodedText message {cursor.block ().text (), ("MSK144" == m_mode || "FT8" == m_mode) && m_config.contestMode (), m_config.my_grid ()}; m_bDoubleClicked = true; processMessage (message, ctrl, alt); } @@ -3661,15 +3662,6 @@ void MainWindow::processMessage(DecodedText const& message, bool ctrl, bool alt) return; } - // QString t2a; - // int ntsec=3600*t2.mid(0,2).toInt() + 60*t2.mid(2,2).toInt(); - // if(m_bFastMode or m_mode=="FT8") { - // ntsec = ntsec + t2.mid(4,2).toInt(); - // t2a = t2.left (4) + t2.mid (6); //Change hhmmss to hhmm for the message parser - // } - //t2a = t2.left (44); // strip any quality info trailing the - // decoded message - if(m_bFastMode or m_mode=="FT8") { auto i1=message.string ().indexOf(" CQ "); if(i1>10) { @@ -3706,12 +3698,6 @@ void MainWindow::processMessage(DecodedText const& message, bool ctrl, bool alt) message.deCallAndGrid(/*out*/hiscall,hisgrid); auto is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size (); if (!is_73 && !message.isStandardMessage ()) - // && (!Radio::is_callsign (hiscall) // not interested if not from QSO partner - // && !(t4.size () == 7 // unless it is of the form - // && (t4.at (5) == m_baseCall // " 73" - // || t4.at (5).startsWith (m_baseCall + '/') - // || t4.at (5).endsWith ('/' + m_baseCall)) - // && t4.at (6) == "73"))) { qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid; return; @@ -3929,7 +3915,7 @@ void MainWindow::processMessage(DecodedText const& message, bool ctrl, bool alt) ui->decodedTextBrowser2->displayDecodedText(message, m_baseCall, false, m_logBook,m_config.color_CQ(), m_config.color_MyCall(), m_config.color_DXCC(),m_config.color_NewCall()); - m_QSOText = s1; + m_QSOText = s2; } if (hiscall != "73" @@ -4103,41 +4089,54 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional) t=hisBase + " " + my_callsign; msgtype(t, ui->tx1); } else { + t = "DE " + my_callsign + " "; switch (m_config.type_2_msg_gen ()) { case Configuration::type_2_msg_1_full: - t="DE " + my_callsign + " " + my_grid; - msgtype(t, ui->tx1); + msgtype(t + my_grid, ui->tx1); if (!eme_short_codes) { - t=t0 + "R" + rpt; - msgtype(t, ui->tx3); + if ((m_mode=="MSK144" || m_mode=="FT8") + && m_config.contestMode()) { + msgtype(t + "R " + my_grid, ui->tx3); + } + else { + msgtype(t + "R" + rpt, ui->tx3); + } if ((m_mode != "JT4" && m_mode != "QRA64") || !m_bShMsgs) { - t="DE " + my_callsign + " 73"; - msgtype(t, ui->tx5->lineEdit ()); + msgtype(t + "73", ui->tx5->lineEdit ()); } } break; case Configuration::type_2_msg_3_full: - t = t00 + my_grid; - msgtype(t, ui->tx1); - t="DE " + my_callsign + " R" + rpt; - msgtype(t, ui->tx3); + if ((m_mode=="MSK144" || m_mode=="FT8") + && m_config.contestMode()) { + msgtype(t + "R " + my_grid, ui->tx3); + msgtype(t + "RRR", ui->tx4); + } + else { + msgtype(t00 + my_grid, ui->tx1); + msgtype(t + "R" + rpt, ui->tx3); + } if (!eme_short_codes && ((m_mode != "JT4" && m_mode != "QRA64") || !m_bShMsgs)) { - t="DE " + my_callsign + " 73"; - msgtype(t, ui->tx5->lineEdit ()); + msgtype(t + "73", ui->tx5->lineEdit ()); } break; case Configuration::type_2_msg_5_only: - t = t00 + my_grid; - msgtype(t, ui->tx1); + msgtype(t00 + my_grid, ui->tx1); if (!eme_short_codes) { - t=t0 + "R" + rpt; - msgtype(t, ui->tx3); + if ((m_mode=="MSK144" || m_mode=="FT8") + && m_config.contestMode()) { + msgtype(t + "R " + my_grid, ui->tx3); + msgtype(t + "RRR", ui->tx4); + } + else { + t=t0 + "R" + rpt; + msgtype(t, ui->tx3); + } } - t="DE " + my_callsign + " 73"; - msgtype(t, ui->tx5->lineEdit ()); + msgtype(t + "73", ui->tx5->lineEdit ()); break; } } @@ -6110,7 +6109,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de position = ui->decodedTextBrowser->toPlainText().indexOf(QChar::LineFeed,position); m_bDoubleClicked = true; auto start = messages.left (position).lastIndexOf (QChar::LineFeed) + 1; - DecodedText message {messages.mid (start, position - start)}; + DecodedText message {messages.mid (start, position - start), ("MSK144" == m_mode || "FT8" == m_mode) && m_config.contestMode (), m_config.my_grid ()}; processMessage (message); tx_watchdog (false); QApplication::alert (this); diff --git a/mainwindow.ui b/mainwindow.ui index 04948d102..89b4469bd 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -1227,7 +1227,7 @@ QLabel[oob="true"] { - <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repititions will be required</p></body></html> + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html>