Merged from trunk:
------------------------------------------------------------------------ r7861 | k9an | 2017-07-12 22:49:39 +0100 (Wed, 12 Jul 2017) | 1 line Use quarter-symbol steps for time sync. Lower sync threshold. Implement subtraction and two pass decoding. Use osd2 only near nfqso. ------------------------------------------------------------------------ r7862 | k9an | 2017-07-13 01:28:57 +0100 (Thu, 13 Jul 2017) | 1 line Fix NHSYM. ------------------------------------------------------------------------ r7863 | k9an | 2017-07-13 01:31:52 +0100 (Thu, 13 Jul 2017) | 1 line Fix a comment. No code changes. ------------------------------------------------------------------------ r7864 | k9an | 2017-07-13 01:43:56 +0100 (Thu, 13 Jul 2017) | 1 line Fix another bounds error. ------------------------------------------------------------------------ r7879 | k1jt | 2017-07-14 17:02:01 +0100 (Fri, 14 Jul 2017) | 1 line Code cleanup and test ofFT8 decodes with erasures. Do not use on the air. ------------------------------------------------------------------------ r7881 | k1jt | 2017-07-14 19:19:48 +0100 (Fri, 14 Jul 2017) | 1 line Fix nutc in jt9; alternative sync value for late-start FT8 signals. ------------------------------------------------------------------------ r7882 | k9an | 2017-07-14 20:22:53 +0100 (Fri, 14 Jul 2017) | 1 line Move ft8apset to a separate file. ------------------------------------------------------------------------ r7884 | k9an | 2017-07-14 20:35:22 +0100 (Fri, 14 Jul 2017) | 1 line Add ft8apset.f90. ------------------------------------------------------------------------ r7885 | k9an | 2017-07-14 20:46:04 +0100 (Fri, 14 Jul 2017) | 1 line Update call to ft8b. ------------------------------------------------------------------------ r7886 | k9an | 2017-07-14 21:12:29 +0100 (Fri, 14 Jul 2017) | 1 line More work on ap. ------------------------------------------------------------------------ r7887 | k9an | 2017-07-14 23:09:50 +0100 (Fri, 14 Jul 2017) | 1 line More work on AP. Deep decode is unstable - not for use on the air. ------------------------------------------------------------------------ r7890 | k9an | 2017-07-15 01:33:25 +0100 (Sat, 15 Jul 2017) | 1 line Turn off ap. ------------------------------------------------------------------------ r7891 | k9an | 2017-07-15 02:49:44 +0100 (Sat, 15 Jul 2017) | 1 line Add some more items to the lun 81 diagnostics. ------------------------------------------------------------------------ r7892 | k9an | 2017-07-15 15:21:18 +0100 (Sat, 15 Jul 2017) | 1 line Properly calculate metrics for non-ap bits that reside in symbols that contain ap bits. ------------------------------------------------------------------------ r7893 | k9an | 2017-07-15 16:43:41 +0100 (Sat, 15 Jul 2017) | 1 line Use overlap and add to apply reference filter/amplitude equalization. ------------------------------------------------------------------------ r7894 | k9an | 2017-07-15 16:46:46 +0100 (Sat, 15 Jul 2017) | 1 line Improve a comment. ------------------------------------------------------------------------ r7895 | k9an | 2017-07-16 01:10:37 +0100 (Sun, 16 Jul 2017) | 1 line Make refspec filter causal for overlap and add. ------------------------------------------------------------------------ r7911 | k9an | 2017-07-16 16:56:06 +0100 (Sun, 16 Jul 2017) | 1 line More work on Deep decoding. ------------------------------------------------------------------------ r7917 | k9an | 2017-07-16 18:08:09 +0100 (Sun, 16 Jul 2017) | 1 line Properly round the printed snr. ------------------------------------------------------------------------ r7925 | k9an | 2017-07-18 02:12:11 +0100 (Tue, 18 Jul 2017) | 1 line Work on ap decoding. Diagnostic write enabled. ------------------------------------------------------------------------ r7926 | k9an | 2017-07-18 16:22:20 +0100 (Tue, 18 Jul 2017) | 1 line Fix a bug in AP decoding when iaptype=2. Decrease time-sync search range to +/- 1.5s. Fix a big with erasure decoding. ------------------------------------------------------------------------ r7927 | k1jt | 2017-07-20 00:23:20 +0100 (Thu, 20 Jul 2017) | 1 line Remove slider next to audio level meter. ------------------------------------------------------------------------ r7928 | k1jt | 2017-07-20 16:15:00 +0100 (Thu, 20 Jul 2017) | 6 lines 1. Alt+F8 arms "Call 1st" as if a CQ had been sent. 2. "Call 1st" label turns red when armed to respond to a caller. 3. Suppress some recognizable false decodes, send them to cumulative file "data_dir/false_decodes.txt". 4. Reduce sleep delay in decoder() to 10 ms. ------------------------------------------------------------------------ r7929 | k1jt | 2017-07-20 20:23:17 +0100 (Thu, 20 Jul 2017) | 1 line Fix wording in list of keyboard shortcuts. ------------------------------------------------------------------------ r7930 | k1jt | 2017-07-20 20:25:08 +0100 (Thu, 20 Jul 2017) | 2 lines Comment out diagnostic write. ------------------------------------------------------------------------ r7931 | k9an | 2017-07-20 22:08:36 +0100 (Thu, 20 Jul 2017) | 1 line Only print dupes if SNR is higher than what has already been printed. ------------------------------------------------------------------------ r7932 | k9an | 2017-07-21 23:02:06 +0100 (Fri, 21 Jul 2017) | 1 line Add to the list of allowed keywords in jtmsg.f90. ------------------------------------------------------------------------ r7933 | k9an | 2017-07-22 04:01:09 +0100 (Sat, 22 Jul 2017) | 1 line Add variables lapon and napwid to control ap decoding. Reconfigure the logic for AP decoding and ordered-statistics decoding. ------------------------------------------------------------------------ r7934 | k9an | 2017-07-22 14:21:03 +0100 (Sat, 22 Jul 2017) | 1 line Prevent a certain type of non-standard message from being flagged as a false decode. ------------------------------------------------------------------------ r7935 | k9an | 2017-07-22 18:12:48 +0100 (Sat, 22 Jul 2017) | 1 line More informative end-of-line annotation for AP decodes. ------------------------------------------------------------------------ r7936 | k9an | 2017-07-24 15:23:22 +0100 (Mon, 24 Jul 2017) | 1 line Bring msk144d2 more up to date. Runs now, but still needs more work. ------------------------------------------------------------------------ r7937 | k1jt | 2017-07-24 15:48:16 +0100 (Mon, 24 Jul 2017) | 2 lines Correct the spacing between marked lowest and highest FT8 tones for RxFreq (green) and TxFreq (red). ------------------------------------------------------------------------ r7938 | bsomervi | 2017-07-24 20:27:14 +0100 (Mon, 24 Jul 2017) | 4 lines Add double clickable push button and radio button widgets These emit doubleClicked signal when double-clicked, otherwise they are identical to their super-classes. ------------------------------------------------------------------------ r7939 | bsomervi | 2017-07-24 20:27:23 +0100 (Mon, 24 Jul 2017) | 42 lines Add the option to ALT+click a decoded CQ or QRZ message which only moves the Rx frequency to theirs, this facilitates calling a station who is busy and may have many callers on their frequency. Updated the corresponding mouse shortcuts help text. Allow for times with seconds when parsing fast mode and FT8 decodes. Exclude the RR73 grid square from and grid validation or matching, it is not a grid square any more as far as WSJT-X is concerned, it is an RRR substitute. Add a simple state machine for QSO progress such that replies and auto-sequencing can be better controlled. Get compound callsign edge cases working again and allow QSOs from and to compound callsign holders working in as many situations as possible including auto-sequencing and FT8 auto-reply mode. This does mean that a "DE W6/K1ABC DM93" type message close to a callers Tx or Rx frequency will be taken as a reply to a CQ call despite it not being explicitly addressed back to the CQ caller. Compound callsigns should work in MSK144 contest mode also as well as in short code modes with some minor restrictions (short codes will not be used where configuration demands that a message be used to send a full compound callsign). Auto sequencing has been made generic such that it can be used for more than one mode if desired. Allow the use of free text messages to sign off in auto sequenced QSOs without the message being overwritten by the sequencer. Double click actions have been added to the Tx5 radio and push buttons to revert back to the default standard 73 message. Make DisplayText class interface more idiomatic C++ and simplify a bit. Fixed some displayed widget arrangements for different modes and sub-modes so that they are consistent when starting up and when switching mode or sub-mode. This is a big change which has been extensively tested but no doubt there will also be some new defects introduced. ------------------------------------------------------------------------ r7940 | bsomervi | 2017-07-25 17:51:19 +0100 (Tue, 25 Jul 2017) | 1 line Fix issue with Tx5 not being generated with a new DX Call ------------------------------------------------------------------------ r7941 | bsomervi | 2017-07-25 17:51:27 +0100 (Tue, 25 Jul 2017) | 1 line Fix country name display that broke in r7939 ------------------------------------------------------------------------ r7942 | bsomervi | 2017-07-25 17:51:34 +0100 (Tue, 25 Jul 2017) | 1 line Ensure JT9 lowest decode frequency spin box is disabled when not available ------------------------------------------------------------------------ r7943 | bsomervi | 2017-07-25 17:51:42 +0100 (Tue, 25 Jul 2017) | 4 lines Pick up tail-enders when completing a call 1st QSO after re-enabling auto Tx Allow any message to start a QSO so long as we are not in an auto-reply QSO. ------------------------------------------------------------------------ r7944 | bsomervi | 2017-07-25 17:51:49 +0100 (Tue, 25 Jul 2017) | 1 line Exclude all decode quality markers from internal decode parsing and matching ------------------------------------------------------------------------ r7945 | k9an | 2017-07-25 20:06:05 +0100 (Tue, 25 Jul 2017) | 1 line Move '?' quality warning to message(22:22). ------------------------------------------------------------------------ r7946 | k9an | 2017-07-25 21:55:13 +0100 (Tue, 25 Jul 2017) | 1 line Reject candiates with fewer than 7 correct hard-decoded sync symbols. ------------------------------------------------------------------------ r7947 | bsomervi | 2017-07-26 02:38:37 +0100 (Wed, 26 Jul 2017) | 1 line Force Settings tab to Radio tab when navigating there from a rig error message ------------------------------------------------------------------------ r7948 | bsomervi | 2017-07-26 02:38:44 +0100 (Wed, 26 Jul 2017) | 1 line Correct the highlighting of the Call 1st check box label ------------------------------------------------------------------------ r7949 | bsomervi | 2017-07-26 02:38:57 +0100 (Wed, 26 Jul 2017) | 5 lines Option to skip using grid reply message Enable and disable by double-clicking the Tx1 button or the adjacent radio button. Tx1 message shows grayed out when the Tx1 message is elided. ------------------------------------------------------------------------ r7950 | bsomervi | 2017-07-26 02:39:04 +0100 (Wed, 26 Jul 2017) | 6 lines Option to use RR73 grid message as RRR message substitutes Enable or disable by double-clicking the Tx4 button or the adjacent radio button. Is auto disabled by a band change as it is expected that the user reassess the conditions to see if message repetitions are unlikely to be needed. ------------------------------------------------------------------------ r7951 | bsomervi | 2017-07-26 02:39:11 +0100 (Wed, 26 Jul 2017) | 1 line Fix highlighting of the call first check box label ------------------------------------------------------------------------ r7952 | bsomervi | 2017-07-26 02:39:23 +0100 (Wed, 26 Jul 2017) | 1 line Better behavior and tool tips for Txn buttons and radio buttons ------------------------------------------------------------------------ r7953 | bsomervi | 2017-07-26 02:39:30 +0100 (Wed, 26 Jul 2017) | 1 line Auto Tx stop when calling a CQer who answers another station on your Tx frequency ------------------------------------------------------------------------ r7954 | bsomervi | 2017-07-26 11:56:12 +0100 (Wed, 26 Jul 2017) | 1 line Add menu option to turn on AP decoding in FT8 mode ------------------------------------------------------------------------ r7955 | k9an | 2017-07-26 14:05:34 +0100 (Wed, 26 Jul 2017) | 1 line Enable AP for any decoding level. ------------------------------------------------------------------------ r7956 | k1jt | 2017-07-26 14:44:31 +0100 (Wed, 26 Jul 2017) | 1 line Remove obsolete test program. ------------------------------------------------------------------------ r7957 | bsomervi | 2017-07-26 22:18:59 +0100 (Wed, 26 Jul 2017) | 11 lines Use the low confidence decode quality marker to elide spots and pass info via UDP The UDP decode and reply message have been augmented with a boolean flag denoting a low confidence decode when set. Existing clients can safely use the reply message without passing the flag as the default value will still action messages that have high confidence. If low confidence decodes are to be passed back via the reply message then the low confidence flag must be included and correctly set to match the original decode. See NetworkMessage.hpp for message fields and meanings. ------------------------------------------------------------------------ r7958 | bsomervi | 2017-07-26 22:19:21 +0100 (Wed, 26 Jul 2017) | 3 lines Add QSO state machine state and tx audio offset to parameters passed to slow decoders Required to pick best AP masks in FT8 decoder ------------------------------------------------------------------------ r7959 | bsomervi | 2017-07-26 23:03:02 +0100 (Wed, 26 Jul 2017) | 1 line Extend grids looked up from CALL3.TXT from 4 to 6-digits if first 4 match ------------------------------------------------------------------------ r7960 | k9an | 2017-07-27 16:35:40 +0100 (Thu, 27 Jul 2017) | 1 line nQSOProgress now controls AP decoding. Needs testing - may not be stable with AP enabled. ------------------------------------------------------------------------ r7961 | k9an | 2017-07-27 19:07:54 +0100 (Thu, 27 Jul 2017) | 1 line Correct some logic so that AP is only on when selected and so that AP decodes of type 4 or greater are limited to the vicinity of nfqso or nftx. ------------------------------------------------------------------------ r7962 | k1jt | 2017-07-27 19:57:53 +0100 (Thu, 27 Jul 2017) | 2 lines Remove unused arguments from the call to fix_contest_msg(). ------------------------------------------------------------------------ r7963 | k1jt | 2017-07-27 21:17:30 +0100 (Thu, 27 Jul 2017) | 1 line Working on some features for NA VHF contests. Not finished! ------------------------------------------------------------------------ r7964 | bsomervi | 2017-07-28 01:00:42 +0100 (Fri, 28 Jul 2017) | 1 line Fix syntax error in statement function definition ------------------------------------------------------------------------ r7965 | bsomervi | 2017-07-28 02:20:22 +0100 (Fri, 28 Jul 2017) | 6 lines Revert "Extend grids looked up from CALL3.TXT from 4 to 6-digits if first 4 match" Bad idea, need to find a better way to extend grids to 6-digits from CALL3.TXT. This reverts commit r7959 ------------------------------------------------------------------------ r7968 | k9an | 2017-07-28 16:35:17 +0100 (Fri, 28 Jul 2017) | 1 line Comment out diagnostic write to lun 81. ------------------------------------------------------------------------ r7969 | k1jt | 2017-07-28 16:50:13 +0100 (Fri, 28 Jul 2017) | 2 lines Make 72-bit "contest mode" available in FT8 as well as MSK144. ------------------------------------------------------------------------ r7970 | bsomervi | 2017-07-29 00:25:32 +0100 (Sat, 29 Jul 2017) | 7 lines Change tolerances for auto stop and auto-sequence of some messages FT8 auto-stop will only react to messages within +/- 50Hz of our Tx frequency. Auto-sequence on "DE ..." and free text 73 messages will respond if they are within 25Hz of our Tx or Rx frequency. ------------------------------------------------------------------------ r7971 | bsomervi | 2017-07-31 02:28:25 +0100 (Mon, 31 Jul 2017) | 1 line Add extra hidden string length argument to genft8 interface ------------------------------------------------------------------------ r7972 | bsomervi | 2017-07-31 02:28:33 +0100 (Mon, 31 Jul 2017) | 5 lines Fix FT8 call first behaviour with "Lock Tx=Rx" Call first combined with "Lock Tx=Rx" (why would anyone consider doing that!) should continue on the Tx frequency of the station being worked and not be switched another calling station's frequency. ------------------------------------------------------------------------ r7973 | k1jt | 2017-08-01 19:01:27 +0100 (Tue, 01 Aug 2017) | 1 line Utility for generating figure for QST/RadCom article. ------------------------------------------------------------------------ r7974 | k1jt | 2017-08-01 19:16:01 +0100 (Tue, 01 Aug 2017) | 2 lines Tidy up some details for 72-bit contest mode in FT8. ------------------------------------------------------------------------ r7975 | k1jt | 2017-08-01 19:46:12 +0100 (Tue, 01 Aug 2017) | 2 lines Don't highlight FT8 contest-mode Tx3 message as a free-text message. ------------------------------------------------------------------------ r7976 | k1jt | 2017-08-01 20:32:54 +0100 (Tue, 01 Aug 2017) | 2 lines Fix the "F4" shortcut description; add usage advuice to "Lock Tx=Rx" tool tip. ------------------------------------------------------------------------ r7980 | k1jt | 2017-08-02 15:05:37 +0100 (Wed, 02 Aug 2017) | 2 lines Enable "nagain" for FT8, as in other modes. ------------------------------------------------------------------------ r7987 | k1jt | 2017-08-02 20:23:42 +0100 (Wed, 02 Aug 2017) | 2 lines Updates to the WSJT-X User Guide for Version 1.8. ------------------------------------------------------------------------ r7988 | k1jt | 2017-08-02 20:27:43 +0100 (Wed, 02 Aug 2017) | 2 lines Add several new screen shots. ------------------------------------------------------------------------ r7989 | k1jt | 2017-08-02 21:43:06 +0100 (Wed, 02 Aug 2017) | 2 lines Allow auto-seq in QRA64 mode; updates to User Guide. ------------------------------------------------------------------------ r7992 | bsomervi | 2017-08-03 12:23:07 +0100 (Thu, 03 Aug 2017) | 7 lines Fix an issue with VFO tuning while running Doppler correction Holding down the SHIFT key while tuning the rig should update the nominal sked frequency, not holding done the SHIFT key should not update the sked frequency. This is not yet perfect and sometimes a change to the nominal sked frequency can get through but it is a rare as yet unfound race condition. ------------------------------------------------------------------------ r7993 | k9an | 2017-08-03 15:46:21 +0100 (Thu, 03 Aug 2017) | 1 line 1. Use norder=3 for nagain, 2. Renumber aptypes. ------------------------------------------------------------------------ r7994 | k1jt | 2017-08-03 15:48:59 +0100 (Thu, 03 Aug 2017) | 2 lines Remove the "Weak" checkbox from GUI, it's not implemented. ------------------------------------------------------------------------ r7995 | k1jt | 2017-08-03 16:12:30 +0100 (Thu, 03 Aug 2017) | 2 lines More updates to the WSJT-X User Guide. ------------------------------------------------------------------------ git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx-1.8@7996 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
@ -260,6 +260,8 @@ set (wsjt_qt_CXXSRCS
|
||||
CallsignValidator.cpp
|
||||
SplashScreen.cpp
|
||||
EqualizationToolsDialog.cpp
|
||||
DoubleClickablePushButton.cpp
|
||||
DoubleClickableRadioButton.cpp
|
||||
)
|
||||
|
||||
set (wsjt_qtmm_CXXSRCS
|
||||
@ -376,6 +378,7 @@ set (wsjt_FSRCS
|
||||
lib/fsk4hf/chkcrc10.f90
|
||||
lib/fsk4hf/chkcrc12.f90
|
||||
lib/fsk4hf/chkcrc12a.f90
|
||||
lib/chkcall.f90
|
||||
lib/chkhist.f90
|
||||
lib/chkmsg.f90
|
||||
lib/chkss2.f90
|
||||
@ -433,6 +436,7 @@ set (wsjt_FSRCS
|
||||
lib/fqso_first.f90
|
||||
lib/freqcal.f90
|
||||
lib/fsk4hf/fsk4hf.f90
|
||||
lib/fsk4hf/ft8apset.f90
|
||||
lib/fsk4hf/ft8b.f90
|
||||
lib/fsk4hf/ft8_downsample.f90
|
||||
lib/fsk4hf/ft8sim.f90
|
||||
@ -473,6 +477,7 @@ set (wsjt_FSRCS
|
||||
lib/iscat.f90
|
||||
lib/jplsubs.f
|
||||
lib/jt9fano.f90
|
||||
lib/jtmsg.f90
|
||||
lib/ldpcsim144.f90
|
||||
lib/fsk4hf/ldpcsim120.f90
|
||||
lib/fsk4hf/ldpcsim168.f90
|
||||
|
@ -603,6 +603,7 @@ QDir Configuration::data_dir () const {return m_->data_dir_;}
|
||||
QDir Configuration::writeable_data_dir () const {return m_->writeable_data_dir_;}
|
||||
QDir Configuration::temp_dir () const {return m_->temp_dir_;}
|
||||
|
||||
void Configuration::select_tab (int index) {m_->ui_->configuration_tabs->setCurrentIndex (index);}
|
||||
int Configuration::exec () {return m_->exec ();}
|
||||
bool Configuration::is_active () const {return m_->isVisible ();}
|
||||
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
QWidget * parent = nullptr);
|
||||
~Configuration ();
|
||||
|
||||
void select_tab (int);
|
||||
int exec ();
|
||||
bool is_active () const;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>521</width>
|
||||
<width>536</width>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -188,6 +188,12 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
@ -237,6 +243,12 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@ -301,6 +313,12 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
@ -390,6 +408,12 @@ quiet period when decoding is done.</string>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@ -1882,6 +1906,12 @@ for assessing propagation and system performance.</string>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@ -2178,6 +2208,12 @@ Right click for insert and delete options.</string>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
@ -2198,6 +2234,12 @@ Right click for insert and delete options.</string>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@ -2300,7 +2342,7 @@ Right click for insert and delete options.</string>
|
||||
<string><html><head/><body><p>Exchange 4-character grid locators instead of reports. See User Guide for details.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MSK144 Contest Mode</string>
|
||||
<string>FT8 and MSK144 Contest Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2595,9 +2637,9 @@ soundcard changes</string>
|
||||
<buttongroup name="CAT_data_bits_button_group"/>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="TX_mode_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="TX_mode_button_group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
14
DoubleClickablePushButton.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "DoubleClickablePushButton.hpp"
|
||||
|
||||
#include "moc_DoubleClickablePushButton.cpp"
|
||||
|
||||
DoubleClickablePushButton::DoubleClickablePushButton (QWidget * parent)
|
||||
: QPushButton {parent}
|
||||
{
|
||||
}
|
||||
|
||||
void DoubleClickablePushButton::mouseDoubleClickEvent (QMouseEvent * event)
|
||||
{
|
||||
Q_EMIT doubleClicked ();
|
||||
QPushButton::mouseDoubleClickEvent (event);
|
||||
}
|
27
DoubleClickablePushButton.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef DOUBLE_CLICKABLE_PUSH_BUTTON_HPP_
|
||||
#define DOUBLE_CLICKABLE_PUSH_BUTTON_HPP_
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
//
|
||||
// DoubleClickablePushButton - QPushButton that emits a mouse double
|
||||
// click signal
|
||||
//
|
||||
// Clients should be aware of the QWidget::mouseDoubleClickEvent()
|
||||
// notes about receipt of mouse press and mouse release events.
|
||||
//
|
||||
class DoubleClickablePushButton
|
||||
: public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoubleClickablePushButton (QWidget * = nullptr);
|
||||
|
||||
Q_SIGNAL void doubleClicked ();
|
||||
|
||||
protected:
|
||||
void mouseDoubleClickEvent (QMouseEvent *) override;
|
||||
};
|
||||
|
||||
#endif
|
14
DoubleClickableRadioButton.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "DoubleClickableRadioButton.hpp"
|
||||
|
||||
#include "moc_DoubleClickableRadioButton.cpp"
|
||||
|
||||
DoubleClickableRadioButton::DoubleClickableRadioButton (QWidget * parent)
|
||||
: QRadioButton {parent}
|
||||
{
|
||||
}
|
||||
|
||||
void DoubleClickableRadioButton::mouseDoubleClickEvent (QMouseEvent * event)
|
||||
{
|
||||
Q_EMIT doubleClicked ();
|
||||
QRadioButton::mouseDoubleClickEvent (event);
|
||||
}
|
27
DoubleClickableRadioButton.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef DOUBLE_CLICKABLE_RADIO_BUTTON_HPP_
|
||||
#define DOUBLE_CLICKABLE_RADIO_BUTTON_HPP_
|
||||
|
||||
#include <QRadioButton>
|
||||
|
||||
//
|
||||
// DoubleClickableRadioButton - QRadioButton that emits a mouse double
|
||||
// click signal
|
||||
//
|
||||
// Clients should be aware of the QWidget::mouseDoubleClickEvent()
|
||||
// notes about receipt of mouse press and mouse release events.
|
||||
//
|
||||
class DoubleClickableRadioButton
|
||||
: public QRadioButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoubleClickableRadioButton (QWidget * = nullptr);
|
||||
|
||||
Q_SIGNAL void doubleClicked ();
|
||||
|
||||
protected:
|
||||
void mouseDoubleClickEvent (QMouseEvent *) override;
|
||||
};
|
||||
|
||||
#endif
|
@ -151,11 +151,13 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
||||
quint32 delta_frequency;
|
||||
QByteArray mode;
|
||||
QByteArray message;
|
||||
in >> time >> snr >> delta_time >> delta_frequency >> mode >> message;
|
||||
bool low_confidence {false};
|
||||
in >> time >> snr >> delta_time >> delta_frequency >> mode >> message >> low_confidence;
|
||||
if (check_status (in) != Fail)
|
||||
{
|
||||
Q_EMIT self_->reply (time, snr, delta_time, delta_frequency
|
||||
, QString::fromUtf8 (mode), QString::fromUtf8 (message));
|
||||
, QString::fromUtf8 (mode), QString::fromUtf8 (message)
|
||||
, low_confidence);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -366,13 +368,14 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con
|
||||
}
|
||||
|
||||
void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
, QString const& mode, QString const& message_text)
|
||||
, QString const& mode, QString const& message_text, bool low_confidence)
|
||||
{
|
||||
if (m_->server_port_ && !m_->server_string_.isEmpty ())
|
||||
{
|
||||
QByteArray message;
|
||||
NetworkMessage::Builder out {&message, NetworkMessage::Decode, m_->id_, m_->schema_};
|
||||
out << is_new << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 ();
|
||||
out << is_new << time << snr << delta_time << delta_frequency << mode.toUtf8 ()
|
||||
<< message_text.toUtf8 () << low_confidence;
|
||||
m_->send_message (out, message);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
, QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode
|
||||
, bool fast_mode);
|
||||
Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
, QString const& mode, QString const& message);
|
||||
, QString const& mode, QString const& message, bool low_confidence);
|
||||
Q_SLOT void WSPR_decode (bool is_new, QTime time, qint32 snr, float delta_time, Frequency
|
||||
, qint32 drift, QString const& callsign, QString const& grid, qint32 power);
|
||||
Q_SLOT void clear_decodes ();
|
||||
@ -70,7 +70,7 @@ public:
|
||||
// this signal is emitted if the server sends us a reply, the only
|
||||
// reply supported is reply to a prior CQ or QRZ message
|
||||
Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode
|
||||
, QString const& message_text);
|
||||
, QString const& message_text, bool low_confidence);
|
||||
|
||||
// this signal is emitted if the server has requested a replay of
|
||||
// all decodes
|
||||
|
@ -241,11 +241,14 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||
quint32 delta_frequency;
|
||||
QByteArray mode;
|
||||
QByteArray message;
|
||||
in >> is_new >> time >> snr >> delta_time >> delta_frequency >> mode >> message;
|
||||
bool low_confidence;
|
||||
in >> is_new >> time >> snr >> delta_time >> delta_frequency >> mode
|
||||
>> message >> low_confidence;
|
||||
if (check_status (in) != Fail)
|
||||
{
|
||||
Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency
|
||||
, QString::fromUtf8 (mode), QString::fromUtf8 (message));
|
||||
, QString::fromUtf8 (mode), QString::fromUtf8 (message)
|
||||
, low_confidence);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -396,14 +399,15 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a
|
||||
}
|
||||
}
|
||||
|
||||
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text)
|
||||
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence)
|
||||
{
|
||||
auto iter = m_->clients_.find (id);
|
||||
if (iter != std::end (m_->clients_))
|
||||
{
|
||||
QByteArray message;
|
||||
NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_};
|
||||
out << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 ();
|
||||
out << time << snr << delta_time << delta_frequency << mode.toUtf8 ()
|
||||
<< message_text.toUtf8 () << low_confidence;
|
||||
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
// note that the client is not obliged to take any action and only
|
||||
// takes any action if the decode is present and is a CQ or QRZ message
|
||||
Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
, QString const& mode, QString const& message);
|
||||
, QString const& mode, QString const& message, bool low_confidence);
|
||||
|
||||
// ask the client with identification 'id' to replay all decodes
|
||||
Q_SLOT void replay (QString const& id);
|
||||
@ -69,7 +69,8 @@ public:
|
||||
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode);
|
||||
Q_SIGNAL void client_closed (QString const& id);
|
||||
Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message);
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message
|
||||
, bool low_confidence);
|
||||
Q_SIGNAL void WSPR_decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time, Frequency
|
||||
, qint32 drift, QString const& callsign, QString const& grid, qint32 power);
|
||||
Q_SIGNAL void qso_logged (QString const& id, QDateTime timeOff, QString const& dx_call, QString const& dx_grid
|
||||
|
@ -156,13 +156,19 @@
|
||||
* Delta frequency (Hz) quint32
|
||||
* Mode utf8
|
||||
* Message utf8
|
||||
* Low confidence bool
|
||||
*
|
||||
* The decode message is sent when a new decode is completed, in
|
||||
* this case the 'New' field is true. It is also used in response
|
||||
* to a "Replay" message where each old decode in the "Band
|
||||
* activity" window, that has not been erased, is sent in order
|
||||
* as a one of these messages with the 'New' field set to
|
||||
* false. See the "Replay" message below for details of usage.
|
||||
* as a one of these messages with the 'New' field set to false.
|
||||
* See the "Replay" message below for details of usage. Low
|
||||
* confidence decodes are flagged in protocols where the decoder
|
||||
* has knows that a decode has a higher than normal probability
|
||||
* of being false, they should not be reported on publicly
|
||||
* accessible services without some attached warning or further
|
||||
* validation.
|
||||
*
|
||||
*
|
||||
* Clear Out 3 quint32
|
||||
@ -184,6 +190,7 @@
|
||||
* Delta frequency (Hz) quint32
|
||||
* Mode utf8
|
||||
* Message utf8
|
||||
* Low confidence bool
|
||||
*
|
||||
* In order for a server to provide a useful cooperative service
|
||||
* to WSJT-X it is possible for it to initiate a QSO by sending
|
||||
|
@ -244,7 +244,7 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const&
|
||||
|
||||
void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
|
||||
, float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/
|
||||
, QString const& /*message*/)
|
||||
, QString const& /*message*/, bool /*low_confidence*/)
|
||||
{
|
||||
if (client_id == id_)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode);
|
||||
Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr
|
||||
, float delta_time, quint32 delta_frequency, QString const& mode
|
||||
, QString const& message);
|
||||
, QString const& message, bool low_confidence);
|
||||
Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr
|
||||
, float delta_time, Frequency delta_frequency, qint32 drift
|
||||
, QString const& callsign, QString const& grid, qint32 power);
|
||||
|
@ -17,13 +17,19 @@ namespace
|
||||
QT_TRANSLATE_NOOP ("DecodesModel", "DF"),
|
||||
QT_TRANSLATE_NOOP ("DecodesModel", "Md"),
|
||||
QT_TRANSLATE_NOOP ("DecodesModel", "Message"),
|
||||
QT_TRANSLATE_NOOP ("DecodesModel", "Confidence"),
|
||||
};
|
||||
|
||||
QString confidence_string (bool low_confidence)
|
||||
{
|
||||
return low_confidence ? QT_TRANSLATE_NOOP ("DecodesModel", "low") : QT_TRANSLATE_NOOP ("DecodesModel", "high");
|
||||
}
|
||||
|
||||
QFont text_font {"Courier", 10};
|
||||
|
||||
QList<QStandardItem *> make_row (QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message
|
||||
, bool is_fast)
|
||||
, bool low_confidence, bool is_fast)
|
||||
{
|
||||
auto time_item = new QStandardItem {time.toString (is_fast || "~" == mode ? "hh:mm:ss" : "hh:mm")};
|
||||
time_item->setData (time);
|
||||
@ -44,8 +50,11 @@ namespace
|
||||
auto md = new QStandardItem {mode};
|
||||
md->setTextAlignment (Qt::AlignHCenter);
|
||||
|
||||
auto confidence = new QStandardItem {confidence_string (low_confidence)};
|
||||
confidence->setTextAlignment (Qt::AlignHCenter);
|
||||
|
||||
QList<QStandardItem *> row {
|
||||
new QStandardItem {client_id}, time_item, snr_item, dt, df, md, new QStandardItem {message}};
|
||||
new QStandardItem {client_id}, time_item, snr_item, dt, df, md, new QStandardItem {message}, confidence};
|
||||
Q_FOREACH (auto& item, row)
|
||||
{
|
||||
item->setEditable (false);
|
||||
@ -57,7 +66,7 @@ namespace
|
||||
}
|
||||
|
||||
DecodesModel::DecodesModel (QObject * parent)
|
||||
: QStandardItemModel {0, 7, parent}
|
||||
: QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent}
|
||||
{
|
||||
int column {0};
|
||||
for (auto const& heading : headings)
|
||||
@ -68,7 +77,7 @@ DecodesModel::DecodesModel (QObject * parent)
|
||||
|
||||
void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message
|
||||
, bool is_fast)
|
||||
, bool low_confidence, bool is_fast)
|
||||
{
|
||||
if (!is_new)
|
||||
{
|
||||
@ -83,7 +92,8 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time
|
||||
&& item (row, 3)->data ().toFloat () == delta_time
|
||||
&& item (row, 4)->data ().toUInt () == delta_frequency
|
||||
&& data (index (row, 5)).toString () == mode
|
||||
&& data (index (row, 6)).toString () == message)
|
||||
&& data (index (row, 6)).toString () == message
|
||||
&& data (index (row, 7)).toString () == confidence_string (low_confidence))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -96,12 +106,12 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time
|
||||
if (target_row >= 0)
|
||||
{
|
||||
insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode
|
||||
, message, is_fast));
|
||||
, message, low_confidence, is_fast));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, is_fast));
|
||||
appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, low_confidence, is_fast));
|
||||
}
|
||||
|
||||
void DecodesModel::clear_decodes (QString const& client_id)
|
||||
@ -124,7 +134,8 @@ void DecodesModel::do_reply (QModelIndex const& source)
|
||||
, item (row, 3)->data ().toFloat ()
|
||||
, item (row, 4)->data ().toInt ()
|
||||
, data (index (row, 5)).toString ()
|
||||
, data (index (row, 6)).toString ());
|
||||
, data (index (row, 6)).toString ()
|
||||
, confidence_string (true) == data (index (row, 7)).toString ());
|
||||
}
|
||||
|
||||
#include "moc_DecodesModel.cpp"
|
||||
|
@ -32,12 +32,13 @@ public:
|
||||
explicit DecodesModel (QObject * parent = nullptr);
|
||||
|
||||
Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message, bool is_fast);
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message
|
||||
, bool low_confidence, bool is_fast);
|
||||
Q_SLOT void clear_decodes (QString const& client_id);
|
||||
Q_SLOT void do_reply (QModelIndex const& source);
|
||||
|
||||
Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
, QString const& mode, QString const& message);
|
||||
, QString const& mode, QString const& message, bool low_confidence);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -91,9 +91,9 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
|
||||
connect (server_, &MessageServer::decode, [this] (bool is_new, QString const& id, QTime time
|
||||
, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode
|
||||
, QString const& message) {
|
||||
, QString const& message, bool low_confidence) {
|
||||
decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message
|
||||
, dock_widgets_[id]->fast_mode ());});
|
||||
, low_confidence, dock_widgets_[id]->fast_mode ());});
|
||||
connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot);
|
||||
connect (server_, &MessageServer::clear_decodes, decodes_model_, &DecodesModel::clear_decodes);
|
||||
connect (server_, &MessageServer::clear_decodes, beacons_model_, &BeaconsModel::clear_decodes);
|
||||
|
@ -69,13 +69,13 @@ public:
|
||||
|
||||
Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime time, qint32 snr
|
||||
, float delta_time, quint32 delta_frequency, QString const& mode
|
||||
, QString const& message)
|
||||
, QString const& message, bool low_confidence)
|
||||
{
|
||||
if (client_id == id_)
|
||||
{
|
||||
qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr
|
||||
<< "Dt:" << delta_time << "Df:" << delta_frequency
|
||||
<< "mode:" << mode;
|
||||
<< "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high");
|
||||
std::cout << tr ("%1: Decoded %2").arg (id_).arg (message).toStdString () << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,10 @@ extern struct dec_data {
|
||||
int nutc; //UTC as integer, HHMM
|
||||
bool ndiskdat; //true ==> data read from *.wav file
|
||||
int ntrperiod; //TR period (seconds)
|
||||
int nQSOProgress; /* QSO state machine state */
|
||||
int nfqso; //User-selected QSO freq (kHz)
|
||||
int nftx; /* Transmit audio offset where
|
||||
replies might be expected */
|
||||
bool newdat; //true ==> new data, must do long FFT
|
||||
int npts8; //npts for c0() array
|
||||
int nfa; //Low decode limit (Hz)
|
||||
@ -38,6 +41,8 @@ extern struct dec_data {
|
||||
int nsubmode;
|
||||
bool nagain;
|
||||
int ndepth;
|
||||
bool lapon;
|
||||
int napwid;
|
||||
int ntxmode;
|
||||
int nmode;
|
||||
int minw;
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
|
||||
|
||||
extern "C" {
|
||||
bool stdmsg_(const char* msg, int len);
|
||||
}
|
||||
|
||||
QString DecodedText::CQersCall()
|
||||
{
|
||||
// extract the CQer's call TODO: does this work with all call formats?
|
||||
@ -37,12 +42,12 @@ QString DecodedText::CQersCall()
|
||||
|
||||
bool DecodedText::isJT65()
|
||||
{
|
||||
return _string.indexOf("#") == column_mode;
|
||||
return _string.indexOf("#") == column_mode + padding_;
|
||||
}
|
||||
|
||||
bool DecodedText::isJT9()
|
||||
{
|
||||
return _string.indexOf("@") == column_mode;
|
||||
return _string.indexOf("@") == column_mode + padding_;
|
||||
}
|
||||
|
||||
bool DecodedText::isTX()
|
||||
@ -51,9 +56,14 @@ bool DecodedText::isTX()
|
||||
return (i >= 0 && i < 15); // TODO guessing those numbers. Does Tx ever move?
|
||||
}
|
||||
|
||||
bool DecodedText::isLowConfidence ()
|
||||
{
|
||||
return QChar {'?'} == _string.mid (padding_ + column_qsoText + 21, 1);
|
||||
}
|
||||
|
||||
int DecodedText::frequencyOffset()
|
||||
{
|
||||
return _string.mid(column_freq,4).toInt();
|
||||
return _string.mid(column_freq + padding_,4).toInt();
|
||||
}
|
||||
|
||||
int DecodedText::snr()
|
||||
@ -64,7 +74,7 @@ int DecodedText::snr()
|
||||
|
||||
float DecodedText::dt()
|
||||
{
|
||||
return _string.mid(column_dt,5).toFloat();
|
||||
return _string.mid(column_dt + padding_,5).toFloat();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -79,7 +89,7 @@ float DecodedText::dt()
|
||||
// find and extract any report. Returns true if this is a standard message
|
||||
bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report)
|
||||
{
|
||||
QString msg=_string.mid(column_qsoText).trimmed();
|
||||
QString msg=_string.mid(column_qsoText + padding_).trimmed();
|
||||
if(msg.length() < 1) return false;
|
||||
msg = msg.left (22).remove (QRegularExpression {"[<>]"});
|
||||
int i1=msg.indexOf('\r');
|
||||
@ -124,7 +134,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
|
||||
QString DecodedText::call()
|
||||
{
|
||||
auto call = _string;
|
||||
call = call.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText);
|
||||
call = call.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText + padding_);
|
||||
int i = call.indexOf(" ");
|
||||
return call.mid(0,i);
|
||||
}
|
||||
@ -134,7 +144,7 @@ void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid)
|
||||
{
|
||||
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);
|
||||
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 (" ");
|
||||
|
106
decodedtext.h
@ -15,79 +15,79 @@
|
||||
|
||||
/*
|
||||
0123456789012345678901234567890123456789
|
||||
^ ^ ^ ^ ^ ^
|
||||
2343 -11 0.8 1259 # YV6BFE F6GUU R-08
|
||||
2343 -19 0.3 718 # VE6WQ SQ2NIJ -14
|
||||
2343 -7 0.3 815 # KK4DSD W7VP -16
|
||||
2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02
|
||||
^ ^ ^ ^ ^ ^
|
||||
2343 -11 0.8 1259 # YV6BFE F6GUU R-08
|
||||
2343 -19 0.3 718 # VE6WQ SQ2NIJ -14
|
||||
2343 -7 0.3 815 # KK4DSD W7VP -16
|
||||
2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02
|
||||
|
||||
0605 Tx 1259 # CQ VK3ACF QF22
|
||||
0605 Tx 1259 # CQ VK3ACF QF22
|
||||
*/
|
||||
|
||||
class DecodedText
|
||||
{
|
||||
public:
|
||||
// These define the columns in the decoded text where fields are to be found.
|
||||
// We rely on these columns being the same in the fortran code (lib/decoder.f90) that formats the decoded text
|
||||
enum Columns { column_time = 0,
|
||||
column_snr = 5,
|
||||
column_dt = 9,
|
||||
column_freq = 14,
|
||||
column_mode = 19,
|
||||
column_qsoText = 22 };
|
||||
void operator=(const QString &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
|
||||
};
|
||||
void operator=(const QByteArray &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
|
||||
};
|
||||
|
||||
void operator=(const QString &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
};
|
||||
void operator=(const QByteArray &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
};
|
||||
void operator+=(const QString &rhs)
|
||||
{
|
||||
_string += rhs;
|
||||
};
|
||||
|
||||
void operator+=(const QString &rhs)
|
||||
{
|
||||
_string += rhs;
|
||||
};
|
||||
QString string() { return _string; };
|
||||
|
||||
QString string() { return _string; };
|
||||
int indexOf(QString s) { return _string.indexOf(s); };
|
||||
int indexOf(QString s, int i) { return _string.indexOf(s,i); };
|
||||
QString mid(int f, int t) { return _string.mid(f,t); };
|
||||
QString left(int i) { return _string.left(i); };
|
||||
|
||||
int indexOf(QString s) { return _string.indexOf(s); };
|
||||
int indexOf(QString s, int i) { return _string.indexOf(s,i); };
|
||||
QString mid(int f, int t) { return _string.mid(f,t); };
|
||||
QString left(int i) { return _string.left(i); };
|
||||
void clear() { _string.clear(); };
|
||||
|
||||
void clear() { _string.clear(); };
|
||||
QString CQersCall();
|
||||
|
||||
QString CQersCall();
|
||||
bool isJT65();
|
||||
bool isJT9();
|
||||
bool isTX();
|
||||
bool isLowConfidence ();
|
||||
int frequencyOffset(); // hertz offset from the tuned dial or rx frequency, aka audio frequency
|
||||
int snr();
|
||||
float dt();
|
||||
|
||||
bool isJT65();
|
||||
bool isJT9();
|
||||
bool isTX();
|
||||
int frequencyOffset(); // hertz offset from the tuned dial or rx frequency, aka audio frequency
|
||||
int snr();
|
||||
float dt();
|
||||
|
||||
// find and extract any report. Returns true if this is a standard message
|
||||
// find and extract any report. Returns true if this is a standard message
|
||||
bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report);
|
||||
|
||||
// get the first text word, usually the call
|
||||
QString call();
|
||||
// get the first message text word, usually the call
|
||||
QString call();
|
||||
|
||||
// get the second word, most likely the de call and the third word, most likely grid
|
||||
void deCallAndGrid(/*out*/QString& call, QString& grid);
|
||||
// get the second word, most likely the de call and the third word, most likely grid
|
||||
void deCallAndGrid(/*out*/QString& call, QString& grid);
|
||||
|
||||
int timeInSeconds();
|
||||
int timeInSeconds();
|
||||
|
||||
// returns a string of the SNR field with a leading + or - followed by two digits
|
||||
QString report();
|
||||
// returns a string of the SNR field with a leading + or - followed by two digits
|
||||
QString report();
|
||||
|
||||
private:
|
||||
QString _string;
|
||||
|
||||
// These define the columns in the decoded text where fields are to be found.
|
||||
// We rely on these columns being the same in the fortran code (lib/decoder.f90) that formats the decoded text
|
||||
enum Columns {column_time = 0,
|
||||
column_snr = 5,
|
||||
column_dt = 9,
|
||||
column_freq = 14,
|
||||
column_mode = 19,
|
||||
column_qsoText = 22 };
|
||||
|
||||
QString _string;
|
||||
int padding_;
|
||||
};
|
||||
|
||||
|
||||
extern "C" { bool stdmsg_(const char* msg, int len); }
|
||||
|
||||
#endif // DECODEDTEXT_H
|
||||
|
@ -40,8 +40,8 @@ void DisplayText::setContentFont(QFont const& font)
|
||||
void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
{
|
||||
bool ctrl = (e->modifiers() & Qt::ControlModifier);
|
||||
bool shift = (e->modifiers() & Qt::ShiftModifier);
|
||||
emit(selectCallsign(shift,ctrl));
|
||||
bool alt = (e->modifiers() & Qt::AltModifier);
|
||||
emit(selectCallsign(alt,ctrl));
|
||||
QTextEdit::mouseDoubleClickEvent(e);
|
||||
}
|
||||
|
||||
@ -72,24 +72,24 @@ void DisplayText::appendText(QString const& text, QString const& bg)
|
||||
}
|
||||
|
||||
|
||||
void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
|
||||
QString DisplayText::_appendDXCCWorkedB4(QString message, QString const& callsign, QString * bg,
|
||||
LogBook logBook, QColor color_CQ,
|
||||
QColor color_DXCC,
|
||||
QColor color_NewCall)
|
||||
{
|
||||
QString call = t1.CQersCall ();
|
||||
QString call = callsign;
|
||||
QString countryName;
|
||||
bool callWorkedBefore;
|
||||
bool countryWorkedBefore;
|
||||
|
||||
if(call.length()==2) {
|
||||
int i0=t1.indexOf("CQ "+call);
|
||||
call=t1.mid(i0+6,-1);
|
||||
int i0=message.indexOf("CQ "+call);
|
||||
call=message.mid(i0+6,-1);
|
||||
i0=call.indexOf(" ");
|
||||
call=call.mid(0,i0);
|
||||
}
|
||||
if(call.length()<3) return;
|
||||
if(!call.contains(QRegExp("[0-9]|[A-Z]"))) return;
|
||||
if(call.length()<3) return message;
|
||||
if(!call.contains(QRegExp("[0-9]|[A-Z]"))) return message;
|
||||
|
||||
logBook.match(/*in*/call,/*out*/countryName,callWorkedBefore,countryWorkedBefore);
|
||||
int charsAvail = 48;
|
||||
@ -97,31 +97,31 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
|
||||
// the decoder (seems) to always generate 41 chars. For a normal CQ call, the last five are spaces
|
||||
// TODO this magic 37 characters is also referenced in MainWindow::doubleClickOnCall()
|
||||
int nmin=37;
|
||||
int i=t1.indexOf(" CQ ");
|
||||
int k=t1.string().mid(i+4,3).toInt();
|
||||
int i=message.indexOf(" CQ ");
|
||||
int k=message.mid(i+4,3).toInt();
|
||||
if(k>0 and k<999) nmin += 4;
|
||||
int s3 = t1.indexOf(" ",nmin);
|
||||
int s3 = message.indexOf(" ",nmin);
|
||||
if (s3 < nmin) s3 = nmin; // always want at least the characters to position 35
|
||||
s3 += 1; // convert the index into a character count
|
||||
t1 = t1.left(s3); // reduce trailing white space
|
||||
message = message.left(s3); // reduce trailing white space
|
||||
charsAvail -= s3;
|
||||
if (charsAvail > 4)
|
||||
{
|
||||
if (!countryWorkedBefore) // therefore not worked call either
|
||||
{
|
||||
t1 += "!";
|
||||
bg=color_DXCC.name();
|
||||
message += "!";
|
||||
*bg = color_DXCC.name();
|
||||
}
|
||||
else
|
||||
if (!callWorkedBefore) // but have worked the country
|
||||
{
|
||||
t1 += "~";
|
||||
bg=color_NewCall.name();
|
||||
message += "~";
|
||||
*bg = color_NewCall.name();
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 += " "; // have worked this call before
|
||||
bg=color_CQ.name();
|
||||
message += " "; // have worked this call before
|
||||
*bg = color_CQ.name();
|
||||
}
|
||||
charsAvail -= 1;
|
||||
|
||||
@ -155,8 +155,9 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
|
||||
countryName.replace ("Guantanamo Bay", "U.S.A.");
|
||||
}
|
||||
|
||||
t1 += countryName;
|
||||
message += countryName;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
|
||||
@ -181,11 +182,13 @@ void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
|
||||
or decodedText.indexOf (" " + myCall + ">") >= 0)) {
|
||||
bg=color_MyCall.name();
|
||||
}
|
||||
// if enabled add the DXCC entity and B4 status to the end of the preformated text line t1
|
||||
// if enabled add the DXCC entity and B4 status to the end of the
|
||||
// preformated text line t1
|
||||
auto message = decodedText.string ();
|
||||
if (displayDXCCEntity && CQcall)
|
||||
_appendDXCCWorkedB4(/*mod*/decodedText,bg,logBook,color_CQ,
|
||||
color_DXCC,color_NewCall);
|
||||
appendText(decodedText.string(),bg);
|
||||
message = _appendDXCCWorkedB4 (message, decodedText.CQersCall (), &bg, logBook, color_CQ,
|
||||
color_DXCC, color_NewCall);
|
||||
appendText (message, bg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
void displayQSY(QString text);
|
||||
|
||||
signals:
|
||||
void selectCallsign(bool shift, bool ctrl);
|
||||
void selectCallsign(bool alt, bool ctrl);
|
||||
|
||||
public slots:
|
||||
void appendText(QString const& text, QString const& bg = "white");
|
||||
@ -32,7 +32,7 @@ protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent *e);
|
||||
|
||||
private:
|
||||
void _appendDXCCWorkedB4(/*mod*/DecodedText& t1, QString &bg, LogBook logBook,
|
||||
QString _appendDXCCWorkedB4(QString message, QString const& callsign, QString * bg, LogBook logBook,
|
||||
QColor color_CQ, QColor color_DXCC, QColor color_NewCall);
|
||||
|
||||
QTextCharFormat m_charFormat;
|
||||
|
@ -63,6 +63,7 @@ set (UG_IMGS
|
||||
images/170709_135615.wav.png
|
||||
images/AstroData_2.png
|
||||
images/Astronomical_data.png
|
||||
images/auto-seq.png
|
||||
images/band-settings.png
|
||||
images/colors.png
|
||||
images/config-menu.png
|
||||
@ -104,6 +105,7 @@ set (UG_IMGS
|
||||
images/setup-menu.png
|
||||
images/special-mouse-commands.png
|
||||
images/status-bar-a.png
|
||||
images/tools-menu.png
|
||||
images/traditional-msg-box.png
|
||||
images/tx-macros.png
|
||||
images/view-menu.png
|
||||
|
@ -1,46 +1,57 @@
|
||||
A text box entitled Astronomical Data provides information needed for
|
||||
tracking the sun or moon, compensating for EME Doppler shift, and
|
||||
estimating EME Doppler spread and path degradation. Toggle the
|
||||
*Astronomical data* on the *View* menu to display or hide this window.
|
||||
|
||||
image::AstroData_2.png[align="center",alt="Astronomical Data"]
|
||||
|
||||
Available information includes the current UTC *Date* and time; *Az*
|
||||
and *El*, azimuth and elevation of the moon at your own location, in
|
||||
degrees; *SelfDop*, *Width*, and *Delay*, the Doppler shift, full
|
||||
limb-to-limb Doppler spread in Hz, and delay of your own EME echoes in
|
||||
seconds; and *DxAz* and *DxEl*, *DxDop*, and *DxWid*, corresponding
|
||||
parameters for a station located at the *DX Grid* entered on the main
|
||||
window. These numbers are followed by *Dec*, the declination of the
|
||||
moon; *SunAz* and *SunEl*, the azimuth and elevation of the Sun;
|
||||
*Freq*, your stated operating frequency in MHz; *Tsky*, the estimated
|
||||
sky background temperature in the direction of the moon, scaled to the
|
||||
operating frequency; *Dpol*, the spatial polarization offset in
|
||||
degrees; *MNR*, the maximum non-reciprocity of the EME path in dB,
|
||||
owing to a combination of Faraday rotation and spatial polarization;
|
||||
and finally *Dgrd*, an estimate of the signal degradation in dB,
|
||||
relative to the best possible time with the moon at perigee in a cold
|
||||
part of the sky.
|
||||
|
||||
The state of the art for establishing three-dimensional locations of
|
||||
the sun, moon, and planets at a specified time is embodied in a
|
||||
numerical model of the solar system maintained at the Jet Propulsion
|
||||
Laboratory. The model has been numerically integrated to produce
|
||||
tabular data that can be interpolated with very high accuracy. For
|
||||
example, the celestial coordinates of the moon or a planet can be
|
||||
determined at a specified time to within about 0.0000003 degrees. The
|
||||
JPL ephemeris tables and interpolation routines have been incorporated
|
||||
into _WSJT-X_. Further details on accuracy, especially concerning
|
||||
calculated EME Doppler shifts, are described in {lunarEchoes} for
|
||||
November-December, 2016.
|
||||
|
||||
The sky background temperatures reported by _WSJT-X_ are derived from
|
||||
the all-sky 408 MHz map of Haslam et al. (Astronomy and Astrophysics
|
||||
Supplement Series, 47, 1, 1982), scaled by frequency to the -2.6
|
||||
power. This map has angular resolution of about 1 degree, and of
|
||||
course most amateur EME antennas have much broader beamwidths than
|
||||
this. Your antenna will therefore smooth out the hot spots
|
||||
considerably, and the observed extremes of sky temperature will be
|
||||
less. Unless you understand your sidelobes and ground reflections
|
||||
extremely well, it is unlikely that more accurate sky temperatures
|
||||
would be of much practical use.
|
||||
A text box entitled Astronomical Data provides information needed for
|
||||
tracking the sun or moon, compensating for EME Doppler shift, and
|
||||
estimating EME Doppler spread and path degradation. Toggle the
|
||||
*Astronomical data* on the *View* menu to display or hide this window.
|
||||
|
||||
image::AstroData_2.png[align="center",alt="Astronomical Data"]
|
||||
|
||||
Available information includes the current UTC *Date* and time; *Az*
|
||||
and *El*, azimuth and elevation of the moon at your own location, in
|
||||
degrees; *SelfDop*, *Width*, and *Delay*, the Doppler shift, full
|
||||
limb-to-limb Doppler spread in Hz, and delay of your own EME echoes in
|
||||
seconds; and *DxAz* and *DxEl*, *DxDop*, and *DxWid*, corresponding
|
||||
parameters for a station located at the *DX Grid* entered on the main
|
||||
window. These numbers are followed by *Dec*, the declination of the
|
||||
moon; *SunAz* and *SunEl*, the azimuth and elevation of the Sun;
|
||||
*Freq*, your stated operating frequency in MHz; *Tsky*, the estimated
|
||||
sky background temperature in the direction of the moon, scaled to the
|
||||
operating frequency; *Dpol*, the spatial polarization offset in
|
||||
degrees; *MNR*, the maximum non-reciprocity of the EME path in dB,
|
||||
owing to a combination of Faraday rotation and spatial polarization;
|
||||
and finally *Dgrd*, an estimate of the signal degradation in dB,
|
||||
relative to the best possible time with the moon at perigee in a cold
|
||||
part of the sky.
|
||||
|
||||
On the higher microwave bands, where Faraday rotation is minimal and
|
||||
linear polarization is often used, spatial offset will reduce signal
|
||||
levels. Some stations have implemented mechanical polarisation
|
||||
adjustment to overcome this loss, and the amount of rotation needed is
|
||||
predicted in real time by the value of *Dpol*. Positive Dpol means
|
||||
that the antenna should be rotated in a clockwise direction looking
|
||||
from behind the antenna towards the moon. For a dish antenna, the
|
||||
feed should similarly be rotated clockwise looking into the mouth of
|
||||
the feed. A negative value for Dpol means anticlockwise rotation.
|
||||
|
||||
|
||||
The state of the art for establishing three-dimensional locations of
|
||||
the sun, moon, and planets at a specified time is embodied in a
|
||||
numerical model of the solar system maintained at the Jet Propulsion
|
||||
Laboratory. The model has been numerically integrated to produce
|
||||
tabular data that can be interpolated with very high accuracy. For
|
||||
example, the celestial coordinates of the moon or a planet can be
|
||||
determined at a specified time to within about 0.0000003 degrees. The
|
||||
JPL ephemeris tables and interpolation routines have been incorporated
|
||||
into _WSJT-X_. Further details on accuracy, especially concerning
|
||||
calculated EME Doppler shifts, are described in {lunarEchoes} for
|
||||
November-December, 2016.
|
||||
|
||||
The sky background temperatures reported by _WSJT-X_ are derived from
|
||||
the all-sky 408 MHz map of Haslam et al. (Astronomy and Astrophysics
|
||||
Supplement Series, 47, 1, 1982), scaled by frequency to the -2.6
|
||||
power. This map has angular resolution of about 1 degree, and of
|
||||
course most amateur EME antennas have much broader beamwidths than
|
||||
this. Your antenna will therefore smooth out the hot spots
|
||||
considerably, and the observed extremes of sky temperature will be
|
||||
less. Unless you understand your sidelobes and ground reflections
|
||||
extremely well, it is unlikely that more accurate sky temperatures
|
||||
would be of much practical use.
|
||||
|
@ -18,16 +18,23 @@ double-clicking on decoded text or a signal in the waterfall. They
|
||||
can also be adjusted using the spinner controls.
|
||||
|
||||
* You can force Tx frequency to the current Rx frequency by clicking
|
||||
the *Tx<-Rx* button, and vice-versa for *Rx<-Tx*. Check the box *Lock
|
||||
Tx=Rx* to make the frequencies always track one another. The
|
||||
on-the-air frequency of your lowest JT9 or JT65 tone is the sum of
|
||||
dial frequency and audio Tx frequency.
|
||||
the *Tx<-Rx* button, and vice-versa for *Rx<-Tx*. The on-the-air
|
||||
frequency of your lowest JT9 or JT65 tone is the sum of dial frequency
|
||||
and audio Tx frequency.
|
||||
|
||||
* Check the box *Lock Tx=Rx* to make the frequencies always track one
|
||||
another.
|
||||
|
||||
TIP: In general we do not recommend using *Lock Tx=Rx* since it
|
||||
encourages poor radio etiquette when running a frequency. With *Lock
|
||||
Tx=Rx* checked, your own Tx frequency will move around following your
|
||||
encourages poor radio etiquette when running a frequency. With this
|
||||
box checked, your own Tx frequency will move around following your
|
||||
callers.
|
||||
|
||||
* For modes lacking a multi-decode feature, or when *Enable
|
||||
VHF/UHF/Microwave features* has been checked on the *Settings ->
|
||||
General* tab, the *F Tol* control sets a frequency toilerance range
|
||||
over which decoding will be attempted, centered on the Rx frequency.
|
||||
|
||||
* The *Report* control lets you change a signal report that has been
|
||||
inserted automatically. Typical reports for the various modes fall in
|
||||
the range –30 to +20 dB. Remember that JT65 reports saturate at an
|
||||
@ -37,13 +44,36 @@ TIP: Consider reducing power if your QSO partner reports your
|
||||
signal above -5 dB in one of the _WSJT-X_ slow modes. These are
|
||||
supposed to be weak signal modes!
|
||||
|
||||
* With *Split operation* activated on the *Settings -> Radio* tab, you
|
||||
can activate the spinner control *Tx CQ nnn* by checking the box to
|
||||
its right. The program will then generate something like `CQ nnn
|
||||
K1ABC FN42` for your CQ message, where `nnn` is the kHz portion of
|
||||
your current operating frequency. Your CQ message *Tx6* will then be
|
||||
transmitted at the calling frequency selected in the *Tx CQ nnn* spinner
|
||||
control. All other messages will be transmitted at your current
|
||||
operating frequency. On reception, when you double-click on a message
|
||||
like `CQ nnn K1ABC FN42` your rig will QSY to the specified frequency
|
||||
so you can call the station at his specified response frequency.
|
||||
* In some circumstances, especially on VHF and higher bands, you can
|
||||
select a supported submode of the active mode by using the *Submode*
|
||||
control. The *Sync* control sets a minimum threshold for establishing
|
||||
time and frequency synchronization with a received signal.
|
||||
|
||||
* Spinner control *T/R xx s* sets sequence lengths for transmission
|
||||
and reception in ISCAT, MSK144, and the fast JT9 modes.
|
||||
|
||||
* With *Split operation* activated on the *Settings -> Radio* tab, in
|
||||
MSK144 and the fast JT9 submodes you can activate the spinner control
|
||||
*Tx CQ nnn* by checking the box to its right. The program will then
|
||||
generate something like `CQ nnn K1ABC FN42` for your CQ message, where
|
||||
`nnn` is the kHz portion of your current operating frequency. Your CQ
|
||||
message *Tx6* will then be transmitted at the calling frequency
|
||||
selected in the *Tx CQ nnn* spinner control. All other messages will
|
||||
be transmitted at your current operating frequency. On reception,
|
||||
when you double-click on a message like `CQ nnn K1ABC FN42` your rig
|
||||
will QSY to the specified frequency so you can call the station at his
|
||||
specified response frequency.
|
||||
|
||||
* Checkboxes at bottom center of the main window control special
|
||||
features for particular operating modes:
|
||||
|
||||
** *Sh* enables shorthand messages in JT4, JT65, and MSK144 modes
|
||||
|
||||
** *Fast* enables fast JT9 submodes
|
||||
|
||||
** *Auto Seq* enables auto-sequencing of Tx messages
|
||||
|
||||
** *Call 1st* enables automatic response to the first decoded
|
||||
responder to your CQ
|
||||
|
||||
** *Tx6* toggles between two types of shorthand messages in JT4 mode
|
@ -18,10 +18,9 @@ recognized ADIF format, for example 630m, 20m, or 70cm. The band-name
|
||||
format works only if a working frequency has been set for that band
|
||||
and mode, in which case the first such match is selected.
|
||||
|
||||
TIP: You can also enter a frequency increment in kHz above the
|
||||
currently displayed integer MHz. For example, if the displayed
|
||||
frequency is 10,368.100, enter `165k` (don't forget the `k`!) to QSY
|
||||
to 10,368.165.
|
||||
* You can also enter a frequency increment in kHz above the currently
|
||||
displayed integer MHz. For example, if the displayed frequency is
|
||||
10,368.100, enter `165k` (don't forget the `k`!) to QSY to 10,368.165.
|
||||
|
||||
* A small colored circle appears in green if the CAT control is
|
||||
activated and functional. The green circle contains the character S
|
||||
@ -34,10 +33,6 @@ split transmit frequency. When using _WSJT-X_ with such radios you
|
||||
should not change the current VFO, split status or dial frequency
|
||||
using controls on the radio.
|
||||
|
||||
* The slider adjacent to the level meter can be used to adjust the
|
||||
signal level sent to the Fast Graph. If *Flatten* is not checked,
|
||||
the same is true for the Wide Graph.
|
||||
|
||||
* If *DX Grid* contains a valid Maidenhead locator, the corresponding
|
||||
great-circle azimuth and distance from your location are displayed.
|
||||
|
||||
|
@ -24,7 +24,7 @@ Many users prefer to create and use entries on the *Configurations*
|
||||
menu for switching between modes. Simply *Clone* the *Default* entry,
|
||||
*Rename* it as desired, and then make all desired settings for that
|
||||
configuration. These settings will be restored whenever you select
|
||||
that entry.
|
||||
that configuration.
|
||||
|
||||
[[VIEW_MENU]]
|
||||
==== View Menu
|
||||
@ -43,6 +43,9 @@ image::decode-menu.png[align="left",alt="Decode Menu"]
|
||||
==== Save Menu
|
||||
image::save-menu.png[align="left",alt="Save Menu"]
|
||||
|
||||
==== Tools Menu
|
||||
image::tools-menu.png[align="left",alt="Tools Menu"]
|
||||
|
||||
[[HELP_MENU]]
|
||||
==== Help Menu
|
||||
image::help-menu.png[align="left",alt="Help Menu"]
|
||||
|
@ -29,6 +29,12 @@ pre-stored messages entered on the *Settings | Tx Macros* tab.
|
||||
Pressing *Enter* on a modified message #5 automatically adds that
|
||||
message to the stored macros.
|
||||
|
||||
* In some circumstances it may be desirable to make your QSOs as
|
||||
shiort as possible. To configure the program to start contacts with
|
||||
message #2, disable message #1 by double-clicking on its round
|
||||
radio-button or rectangular *Tx 1* button. Similarly, to send RR73
|
||||
rather than RRR for message #4, double-click on one of its buttons.
|
||||
|
||||
The second arrangement of controls for generating and selecting
|
||||
Tx messages appears on *Tab 2* of the Message Control Panel:
|
||||
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 34 KiB |
BIN
doc/user_guide/en/images/HotA.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 151 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
BIN
doc/user_guide/en/images/auto-seq.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 18 KiB |
BIN
doc/user_guide/en/images/tools-menu.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.4 KiB |
@ -47,6 +47,26 @@ compound callsign. It should be obvious that the JT4, JT9, and JT65
|
||||
protocols are not designed or well suited for extensive conversations
|
||||
or rag-chewing.
|
||||
|
||||
=== Auto-Sequencing
|
||||
|
||||
The slow modes JT4, JT9, JT65, and QRA64 allow nearly 10 seconds at
|
||||
the end of each one-minute receiving sequence in which you can inspect
|
||||
decoded messages and decide how to reply. With its 15-second T/R
|
||||
cycles, FT8 allows only about two seconds for this task. For this
|
||||
reason a basic auto-sequencing feature is offered. Check *Auto Seq*
|
||||
on the main window to enable this feature:
|
||||
|
||||
image::auto-seq.png[align="center",alt="AutoSeq"]
|
||||
|
||||
When calling CQ you may also choose to check the box *Call 1st*.
|
||||
_WSJT-X_ will then respond automatically to the first decoded
|
||||
responder to your CQ.
|
||||
|
||||
TIP: When *Auto-Seq* is enabled the program will de-activate *Enable
|
||||
Tx* at the end of each QSO. We do not want _WSJT-X_ to make fully
|
||||
automated QSOs.
|
||||
|
||||
|
||||
[[COMP-CALL]]
|
||||
=== Compound Callsigns
|
||||
|
||||
|
@ -3,7 +3,9 @@
|
||||
For quick reference, here's a short list of features and capabilities
|
||||
added to _WSJT-X_ since Version 1.7.0:
|
||||
|
||||
- New modes: *FT8* and *FreqCal*
|
||||
- New mode *FT8* designed for fast QSOs
|
||||
|
||||
- New tool *FreqCal* for accurate frequency calibration of your radio
|
||||
|
||||
- Improved decoding performance for JT65, QRA64, and MSK144
|
||||
|
||||
@ -11,18 +13,19 @@ added to _WSJT-X_ since Version 1.7.0:
|
||||
|
||||
- Experimental amplitude and phase equalization for MSK144
|
||||
|
||||
- Options to minimize screen space used by the *Main* and *Wide Graph*
|
||||
- Options to minimize screen space used by *Main* and *Wide Graph*
|
||||
windows
|
||||
|
||||
- New set of suggested default frequencies specific to the three IARU
|
||||
Regions.
|
||||
|
||||
- Enhanced scheme for managing table of default operating frequencies
|
||||
- Enhanced scheme for managing table of suggested default operating
|
||||
frequencies
|
||||
|
||||
- Improved CAT control for many rigs, including those controlled
|
||||
- Improved CAT control for many radios, including those controlled
|
||||
through Commander or OmniRig.
|
||||
|
||||
- Bug fixes and tweaks to the user interface
|
||||
- Bug fixes and tweaks to user interface
|
||||
|
||||
=== Documentation Conventions
|
||||
|
||||
|
@ -1,3 +1,55 @@
|
||||
=== AP Decoding
|
||||
|
||||
With the QRA64 decoder Nico Palermo, IV3NWV, introduced a technique
|
||||
for decoding with the aid of information that naturally accumulates
|
||||
during a minimal QSO. This _a priori_ (AP) information can be
|
||||
used to increase the sensitivity of the decoder.
|
||||
|
||||
When an operator decides to answer a CQ, he already knows his own
|
||||
callsign and that of his potential QSO partner. He therefore knows
|
||||
what to expect for at least 56 of the 72 message bits in a
|
||||
standard-format response to his call. The _WSJT-X_ decoders for QRA64
|
||||
and FT8 can use these AP bits to decode messages containing them with
|
||||
higher sensitivity than otherwise possible.
|
||||
|
||||
We have implemented AP decoding in slightly different ways in QRA64
|
||||
and FT8. To provide some explicit examples for users, we provide here
|
||||
a brief description of the FT8 behavior.
|
||||
|
||||
The FT8 decoder always tries first to decode a signal without using
|
||||
any AP information. If this attempt fails, and if *Enable AP* is
|
||||
checked on the *Decode* menu, a second attempt hypothesizes that the
|
||||
message contains callsigns MyCall and DxCall. If the QSO has
|
||||
progressed to the point where signal reports have been exchanged, a
|
||||
third attempt hypothesizes that the message contains the known
|
||||
callsigns followed by RRR, RR73, or 73.
|
||||
|
||||
AP decoding attempts effectively set the AP bits to the hypothesized
|
||||
values, as if they had been received perfectly. The decoder then
|
||||
proceeds to determine whether the remaining message and parity bits
|
||||
are consistent with the hypothesized AP bits. If a codeword is found
|
||||
that the decoder judges to have high (but not overwhelmingly high)
|
||||
probability of being correct, a ? character is appended when the
|
||||
decoded message is displayed.
|
||||
|
||||
Successful AP decodes are always labeled with an end-of-line indicator
|
||||
of the form aP, where P is one of the single-digit AP decoding types
|
||||
listed in Table 1. For example, an a2 designator says that the
|
||||
successful decode used MyCall as hypothetically known information.
|
||||
|
||||
[[AP_INFO_TABLE]]
|
||||
.AP information types
|
||||
[width="25%",cols="h10,<m20",frame=topbot,options="header"]
|
||||
|===============================================
|
||||
|P | Message components
|
||||
|1 | CQ     ?     ?
|
||||
|2 | MyCall     ?     ?
|
||||
|3 | MyCall DxCall     ?
|
||||
|4 | MyCall DxCall RRR
|
||||
|5 | MyCall DxCall 73
|
||||
|6 | MyCall DxCall RR73
|
||||
|===============================================
|
||||
|
||||
=== Decoded Lines
|
||||
|
||||
Displayed information accompanying decoded messages generally includes UTC,
|
||||
@ -14,7 +66,7 @@ summarized in the following Table:
|
||||
[width="50%",cols="h,3*^",frame=topbot,options="header"]
|
||||
|===========================================
|
||||
|Mode |Mode character|Sync character|End of line information
|
||||
|FT8 | ~ | |
|
||||
|FT8 | ~ | | aP
|
||||
|JT4 | $ | *, # | f, fN, dNC
|
||||
|JT9 | @ | |
|
||||
|JT65 | # | |
|
||||
@ -28,14 +80,18 @@ Sync character::
|
||||
`#` - Alternate sync
|
||||
|
||||
End of line information::
|
||||
`a` - Decoded with aid of some a priori (AP) information
|
||||
`C` - Confidence indicator [ISCAT and Deep Search; (0-9,*)] +
|
||||
`d` - Deep Search algorithm +
|
||||
`f` - Franke-Taylor or Fano algorithm +
|
||||
`M` - Message length (characters) +
|
||||
`N` - Number of Rx intervals or frames averaged +
|
||||
`P` - Number indicating type of AP information (Table 1, above) +
|
||||
`R` - Return code from QRA64 decoder +
|
||||
`T` - Length of analyzed region (s)
|
||||
|
||||
|
||||
|
||||
=== Reference Spectrum
|
||||
|
||||
WSJT-X provides a tool that can be used to determine the detailed
|
||||
|
@ -11,9 +11,9 @@ purposes a good setting is 6 or 7.
|
||||
decodes using Deep Search. Higher numbers will display results
|
||||
with lower confidence levels.
|
||||
|
||||
- Check *MSK144 Contest Mode* to cause generation and auto-sequencing
|
||||
of MSK144 messages with four-character grid locators in place of signal
|
||||
reports.
|
||||
- Check *FT8 and MSK144 Contest Mode* to enable generation and
|
||||
auto-sequencing of MSK144 messages with four-character grid locators
|
||||
in place of signal reports.
|
||||
|
||||
- Check *Two-pass decoding* to enable a second decoding pass after
|
||||
signals producing first-pass decodes have been subtracted from the
|
||||
|
@ -3,8 +3,11 @@
|
||||
image::settings-general.png[align="center",alt="Settings Window"]
|
||||
|
||||
Select the *General* tab on the *Settings* window. Under _Station
|
||||
Details_, enter your callsign and 4-digit or preferably 6-digit grid
|
||||
locator. This information will be sufficient for initial tests.
|
||||
Details_ enter your callsign, grid locator (preferably the 6-character
|
||||
locator) and IARU Region number. Region 1 is Europe, Africa, the
|
||||
Middle East, and Northern Asia; Region 2 the Americas; and Region 3
|
||||
Southern Asia and the Pacific. This information will be sufficient
|
||||
for initial tests.
|
||||
|
||||
Meanings of remaining options on the *General* tab should be
|
||||
self-explanatory after you have made some QSOs using _WSJT-X_. You
|
||||
|
@ -21,14 +21,13 @@ about 5 kHz. This choice has the desirable effect of allowing the
|
||||
JT65 and JT9 sub-bands simultaneously on most HF bands. Further
|
||||
details are provided in the <<TUTORIAL,Basic Operating Tutorial>>. A
|
||||
wider displayed bandwidth may also be helpful at VHF and above, where
|
||||
JT4, JT65, and QRA64 signals are found over much wider ranges of
|
||||
frequencies.
|
||||
FT8, JT4, JT65, and QRA64 signals may be found over much wider ranges
|
||||
of frequencies.
|
||||
|
||||
- If you have only a standard SSB filter you won’t be able to display
|
||||
more than about 2.7 kHz bandwidth. Depending on the exact dial
|
||||
frequency setting, on HF bands you can display the full sub-band
|
||||
generally used for one mode (JT65 or JT9) and part of the sub-band for
|
||||
the other mode.
|
||||
generally used for one mode.
|
||||
|
||||
- Of course, you might prefer to concentrate on one mode at a time,
|
||||
setting your dial frequency to (say) 14.074 for FT8, 14.076 for JT65,
|
||||
|
@ -6,22 +6,45 @@
|
||||
|
||||
.Wide Graph Settings:
|
||||
|
||||
- *Bins/Pixel* = 4
|
||||
- *Bins/Pixel* = 4, *Start* = 200 Hz, *N Avg* = 2
|
||||
- Adjust the width of the Wide Graph window so that the upper
|
||||
frequency limit is approximately 2500 Hz.
|
||||
frequency limit is approximately 2600 Hz.
|
||||
|
||||
.Open a Wave File:
|
||||
|
||||
- Select *File | Open* and navigate to +...\save\samples\FT8\170709_135615.wav+.
|
||||
The waterfall should look something like this:
|
||||
- Select *File | Open* and navigate to
|
||||
+...\save\samples\FT8\170709_135615.wav+. The waterfall and decoded
|
||||
text window should look something like the following screen shots:
|
||||
|
||||
[[X15]]
|
||||
image::170709_135615.wav.png[align="left",alt="Wide Graph Decode 170709_135615"]
|
||||
|
||||
- You should see decodes of the three FT8 signals in the *Band Activity*
|
||||
text box, as shown below:
|
||||
|
||||
image::ft8_decodes.png[align="left"]
|
||||
|
||||
- Click with the mouse anywhere on the waterfall display. The green Rx
|
||||
frequency marker will jump to your selected frequency, and the Rx
|
||||
frequency control on the main window will be updated accordingly.
|
||||
|
||||
- Do the same thing with the Shift key held down. Now the red Tx
|
||||
frequency marker and its associated control on the main window will
|
||||
follow your frequency selections.
|
||||
|
||||
- Do the same thing with the Ctrl key held down. Now the both colored
|
||||
markers and both spinner controls will follow your selections.
|
||||
|
||||
- Double-clicking at any frequency on the waterfall does all the
|
||||
things just described and also invokes the decoder in a small range
|
||||
around that frequency.
|
||||
|
||||
- Now double-click on any of the the lines of decoded text in the main
|
||||
window. Unless you have *My Call* set to K1JT or KY7M on the
|
||||
*Settings -> General* tab, all three lines will show the same
|
||||
behavior, setting both RxFreq and TxFreq to the frequency of the
|
||||
selected message. However, if MyCall is set to K1JT then clicking on
|
||||
a message directed to K1JT will move only the Rx frequency setting.
|
||||
This behavior is desirable so that you will not inadvertently change
|
||||
your Tx frequency to that of a tail-ender who called you somewhere
|
||||
else in the FT8 subband.
|
||||
|
||||
IMPORTANT: When finished with this Tutorial, don’t forget to re-enter
|
||||
your own callsign as *My Call* on the *Settings | General* tab.
|
||||
|
@ -1,9 +1,6 @@
|
||||
_WSJT-X_ v1.8 suppports a number of features designed for use
|
||||
on the VHF and higher bands. These features now include:
|
||||
|
||||
- *FT8*, a mode optimized for weak, fading signals such as those often
|
||||
encountered with multi-hop sporadic E propagation on 50 MHz.
|
||||
|
||||
- *JT4*, a mode particularly useful for EME on the microwave bands
|
||||
|
||||
- *JT9* fast modes, useful for scatter propagation on VHF bands
|
||||
@ -24,9 +21,6 @@ propagation
|
||||
- *Doppler tracking*, which becomes increasingly important for EME
|
||||
on bands above 1.2 GHz.
|
||||
|
||||
- *Auto-sequencing* of transmitted messages for FT8 and the fast modes
|
||||
with forward error control
|
||||
|
||||
[[VHF_SETUP]]
|
||||
=== VHF Setup
|
||||
|
||||
@ -114,7 +108,11 @@ is generally used for EME on the 5.7 and 10 GHz bands.
|
||||
|
||||
- For EME QSOs some operators use short-form JT4 messages consisting
|
||||
of a single tone. To activate automatic generation of these messages,
|
||||
check the box labeled *Sh*.
|
||||
check the box labeled *Sh*. This also enables the generation of a
|
||||
single tone at 1000Hz by selecting Tx6, to assist in finding signals
|
||||
initially. The box labeled *Tx6* toggles the Tx6 message from 1000Hz
|
||||
to 1250Hz to indicate to the other station that you are ready to
|
||||
receive messages.
|
||||
|
||||
- Select *Deep* from the *Decode* menu. You may also choose to
|
||||
*Enable averaging* over successive transmissions and/or *Enable deep
|
||||
@ -157,15 +155,15 @@ image::JT65B.png[align="center",alt="JT65B"]
|
||||
|
||||
=== QRA64
|
||||
|
||||
QRA64 is an experimental mode in Version 1.7 of _WSJT-X_. The mode is
|
||||
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 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 red curve shows that the
|
||||
decoder has achieved synchronization with a signal at approximately
|
||||
967 Hz.
|
||||
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"]
|
||||
|
||||
@ -183,12 +181,19 @@ most likely value for each of the message's 12 six-bit information
|
||||
symbols. A decode is declared only when the total probability for all
|
||||
12 symbols has converged to an unambiguous value very close to 1.
|
||||
|
||||
TIP: In _WSJT-X_ Version 1.7 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. A multi-decoder like those for JT65 and JT9 has not
|
||||
yet been written.
|
||||
For EME QSOs some operators use short-form QRA64 messages consisting
|
||||
of a single tone. To activate automatic generation of these messages,
|
||||
check the box labeled *Sh*. This also enables the generation of a
|
||||
single tone at 1000Hz by selecting Tx6, to assist in finding signals
|
||||
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.
|
||||
|
||||
=== ISCAT
|
||||
|
||||
@ -207,7 +212,7 @@ longer at distances close to the upper limit. But with patience, 100
|
||||
Watts or more, and a single yagi it can usually be done. The
|
||||
following screen shot shows two 15-second MSK144 transmissions from
|
||||
W5ADD during a 50 MHz QSO with K1JT, at a distance of about 1800 km
|
||||
(1100 mi). The decoded segments have been encircled on the *Fast
|
||||
(1100 mi). The decoded segments have been marked on the *Fast
|
||||
Graph* spectral display.
|
||||
|
||||
image::MSK144.png[align="center",alt="MSK144"]
|
||||
|
@ -9,26 +9,32 @@ subroutine addit(itone,nfsample,nsym,nsps,ifreq,sig,dat)
|
||||
fsample=12000.d0 !Sample rate (Hz)
|
||||
dt=1.d0/fsample !Sample interval (s)
|
||||
twopi=8.d0*atan(1.d0)
|
||||
dphi=0.
|
||||
|
||||
f=ifreq
|
||||
phi=0.
|
||||
k=12000 !Start audio at t = 1.0 s
|
||||
ntot=nsym*tsym/dt
|
||||
t=0.
|
||||
isym0=-1
|
||||
do i=1,ntot
|
||||
t=t+dt
|
||||
isym=nint(t/tsym) + 1
|
||||
if(isym.ne.isym0) then
|
||||
freq=f + itone(isym)*baud
|
||||
dphi=twopi*freq*dt
|
||||
isym0=isym
|
||||
endif
|
||||
phi=phi + dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
xphi=phi
|
||||
k=k+1
|
||||
dat(k)=dat(k) + sig*sin(xphi)
|
||||
iters=1
|
||||
if(nsym.eq.79) iters=2
|
||||
do iter=1,iters
|
||||
f=ifreq
|
||||
phi=0.
|
||||
ntot=nsym*tsym/dt
|
||||
k=12000 !Start audio at t = 1.0 s
|
||||
t=0.
|
||||
if(nsym.eq.79) k=12000 + (iter-1)*12000*30 !Special case for FT8
|
||||
isym0=-1
|
||||
do i=1,ntot
|
||||
t=t+dt
|
||||
isym=nint(t/tsym) + 1
|
||||
if(isym.ne.isym0) then
|
||||
freq=f + itone(isym)*baud
|
||||
dphi=twopi*freq*dt
|
||||
isym0=isym
|
||||
endif
|
||||
phi=phi + dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
xphi=phi
|
||||
k=k+1
|
||||
dat(k)=dat(k) + sig*sin(xphi)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
return
|
||||
|
@ -11,8 +11,10 @@ program allsim
|
||||
integer*2 iwave(NMAX) !Generated waveform (no noise)
|
||||
integer itone(206) !Channel symbols (values 0-8)
|
||||
integer icw(250)
|
||||
integer*1 msgbits(87)
|
||||
logical*1 bcontest
|
||||
real*4 dat(NMAX)
|
||||
character message*22,msgsent*22,arg*8
|
||||
character message*22,msgsent*22,arg*8,mygrid*6
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.1) then
|
||||
@ -24,6 +26,8 @@ program allsim
|
||||
read(arg,*) snrdb !S/N in dB (2500 hz reference BW)
|
||||
|
||||
message='CQ KA2ABC FN20'
|
||||
mygrid='FN20 '
|
||||
bcontest=.false.
|
||||
rmsdb=25.
|
||||
rms=10.0**(0.05*rmsdb)
|
||||
sig=10.0**(0.05*snrdb)
|
||||
@ -56,11 +60,14 @@ program allsim
|
||||
call gen4(message,0,msgsent,itone,itype)
|
||||
call addit(itone,11025,206,2520,1200,sig,dat) !JT4
|
||||
|
||||
call genft8(message,mygrid,bcontest,msgsent,msgbits,itone)
|
||||
call addit(itone,12000,79,1920,1400,sig,dat) !FT8
|
||||
|
||||
call genqra64(message,0,msgsent,itone,itype)
|
||||
call addit(itone,12000,84,6912,1400,sig,dat) !QRA64
|
||||
call addit(itone,12000,84,6912,1600,sig,dat) !QRA64
|
||||
|
||||
call gen65(message,0,msgsent,itone,itype)
|
||||
call addit(itone,11025,126,4096,1600,sig,dat) !JT65
|
||||
call addit(itone,11025,126,4096,1800,sig,dat) !JT65
|
||||
|
||||
iwave(1:npts)=nint(rms*dat(1:npts))
|
||||
|
||||
|
58
lib/chkcall.f90
Normal file
@ -0,0 +1,58 @@
|
||||
subroutine chkcall(w,bc,cok)
|
||||
|
||||
! Check "w" to see if it could be a valid standard callsign or a valid
|
||||
! compound callsign.
|
||||
! Return base call "bc" and a logical "cok" indicator.
|
||||
|
||||
character w*13 !A putative callsign
|
||||
character bc*6 !Base call (tentative)
|
||||
character c*1
|
||||
logical cok,isdigit,isletter
|
||||
|
||||
isdigit(c)=(ichar(c).ge.ichar('0')) .and. (ichar(c).le.ichar('9'))
|
||||
isletter(c)=(ichar(c).ge.ichar('A')) .and. (ichar(c).le.ichar('Z'))
|
||||
|
||||
cok=.true.
|
||||
bc=w(1:6)
|
||||
n1=len_trim(w)
|
||||
if(n1.gt.11) go to 100
|
||||
if(index(w,'.').ge.1) go to 100
|
||||
if(index(w,'+').ge.1) go to 100
|
||||
if(index(w,'-').ge.1) go to 100
|
||||
if(index(w,'?').ge.1) go to 100
|
||||
if(n1.gt.6 .and. index(w,'/').le.0) go to 100
|
||||
|
||||
i0=index(w,'/')
|
||||
if(max(i0-1,n1-i0).gt.6) go to 100 !Base call must be < 7 characters
|
||||
if(i0.ge.2 .and. i0.le.n1-1) then !Extract base call from compound call
|
||||
if(i0-1.le.n1-i0) bc=w(i0+1:n1)//' '
|
||||
if(i0-1.gt.n1-i0) bc=w(1:i0-1)//' '
|
||||
endif
|
||||
|
||||
nbc=len_trim(bc)
|
||||
if(nbc.gt.6) go to 100 !Base call should have no more than 6 characters
|
||||
|
||||
! One of first two characters (c1 or c2) must be a letter
|
||||
if((.not.isletter(bc(1:1))) .and. (.not.isletter(bc(2:2)))) go to 100
|
||||
if(bc(1:1).eq.'Q') go to 100 !Calls don't start with Q
|
||||
|
||||
! Must have a digit in 2nd or 3rd position
|
||||
i1=0
|
||||
if(isdigit(bc(2:2))) i1=2
|
||||
if(isdigit(bc(3:3))) i1=3
|
||||
if(i1.eq.0) go to 100
|
||||
|
||||
! Callsign must have a suffix of 1-3 letters
|
||||
if(i1.eq.nbc) go to 100
|
||||
n=0
|
||||
do i=i1+1,nbc
|
||||
j=ichar(bc(i:i))
|
||||
if(j.lt.ichar('A') .or. j.gt.ichar('Z')) go to 100
|
||||
n=n+1
|
||||
enddo
|
||||
if(n.ge.1 .and. n.le.3) go to 200
|
||||
|
||||
100 cok=.false.
|
||||
|
||||
200 return
|
||||
end subroutine chkcall
|
91
lib/contest72.f90
Normal file
@ -0,0 +1,91 @@
|
||||
program contest72
|
||||
|
||||
use packjt
|
||||
integer dat(12)
|
||||
logical text,bcontest,ok
|
||||
character*22 msg,msg0,msg1
|
||||
character*72 ct1,ct2
|
||||
character*12 callsign1,callsign2
|
||||
character*1 c0
|
||||
character*42 c
|
||||
character*6 mygrid
|
||||
data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ +-./?'/
|
||||
data bcontest/.true./
|
||||
data mygrid/"EM48 "/
|
||||
|
||||
! 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
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.eq.0) open(10,file='contest_msgs.txt',status='old')
|
||||
|
||||
nn=0
|
||||
do imsg=1,9999
|
||||
if(nargs.eq.1) then
|
||||
if(imsg.gt.1) exit
|
||||
call getarg(1,msg0)
|
||||
else
|
||||
read(10,1001,end=999) msg0
|
||||
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)
|
||||
ok=msg1.eq.msg0
|
||||
if(msg0.eq.' ') then
|
||||
write(*,1002)
|
||||
else
|
||||
if(jt_c2(1:1).eq.'W') msg0=' '//msg0(1:20)
|
||||
nn=nn+1
|
||||
write(*,1002) nn,msg0,ok,jt_itype,jt_nc1,jt_nc2,jt_ng,jt_k1,jt_k2
|
||||
1002 format(i1,'. ',a22,L2,i2,2i10,i6,2i8)
|
||||
if(index(msg1,' 73 ').gt.4) nn=0
|
||||
endif
|
||||
if(.not.ok) print*,msg0,msg1
|
||||
if(itype.lt.0 .or. itype.eq.6) cycle
|
||||
|
||||
if(msg(1:3).eq.'CQ ') then
|
||||
m=2
|
||||
write(ct1,1010) dat
|
||||
1010 format(12b6.6)
|
||||
! write(*,1014) ct1
|
||||
1014 format(a72)
|
||||
cycle
|
||||
endif
|
||||
|
||||
i1=index(msg,'<')
|
||||
if(i1.eq.1) then
|
||||
m=0
|
||||
cycle
|
||||
endif
|
||||
|
||||
if(i.ge.5) then
|
||||
m=3
|
||||
cycle
|
||||
endif
|
||||
|
||||
if(msg(1:6).eq.'73 CQ ') then
|
||||
m=4
|
||||
cycle
|
||||
endif
|
||||
|
||||
call packmsg(msg,dat,itype)
|
||||
write(ct1,1010) dat
|
||||
call packtext(msg,nc1,nc2,ng)
|
||||
! write(ct2,1012) nc1,nc2,ng+32768
|
||||
!1012 format(2b28.28,b16.16)
|
||||
! write(*,1014) ct1
|
||||
! write(*,1014) ct2
|
||||
! write(*,1014)
|
||||
enddo
|
||||
|
||||
999 end program contest72
|
@ -61,7 +61,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
if(ios.ne.0) then
|
||||
nfail=nfail+1
|
||||
if(nfail.le.3) then
|
||||
call sleep_msec(100)
|
||||
call sleep_msec(10)
|
||||
go to 10
|
||||
endif
|
||||
endif
|
||||
@ -70,11 +70,11 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
! We're in FT8 mode
|
||||
call timer('decft8 ',0)
|
||||
newdat=params%newdat
|
||||
call my_ft8%decode(ft8_decoded,id2,params%nfqso, &
|
||||
newdat,params%nutc,params%nfa, &
|
||||
params%nfb,logical(params%nagain), &
|
||||
params%ndepth,params%nsubmode, &
|
||||
params%mycall,params%hiscall,params%hisgrid)
|
||||
call my_ft8%decode(ft8_decoded,id2,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nexp_decode,params%ndepth,logical(params%nagain), &
|
||||
logical(params%lapon),params%napwid,params%mycall, &
|
||||
params%mygrid,params%hiscall,params%hisgrid)
|
||||
call timer('decft8 ',1)
|
||||
go to 800
|
||||
endif
|
||||
@ -390,7 +390,7 @@ contains
|
||||
end select
|
||||
end subroutine jt9_decoded
|
||||
|
||||
subroutine ft8_decoded (this,sync,snr,dt,freq,nbadcrc,decoded)
|
||||
subroutine ft8_decoded (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
use ft8_decode
|
||||
implicit none
|
||||
|
||||
@ -399,17 +399,24 @@ contains
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
real, intent(in) :: freq
|
||||
integer, intent(in) :: nbadcrc
|
||||
character(len=22), intent(in) :: decoded
|
||||
|
||||
if(nbadcrc.eq.0) then
|
||||
write(*,1000) params%nutc,snr,dt,nint(freq),decoded
|
||||
1000 format(i6.6,i4,f5.1,i5,' ~ ',1x,a22)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,0,decoded
|
||||
1002 format(i6.6,i4,i5,f6.1,f8.0,i4,3x,a22,' FT8')
|
||||
call flush(6)
|
||||
call flush(13)
|
||||
integer, intent(in) :: nap
|
||||
real, intent(in) :: qual
|
||||
character*2 annot
|
||||
character*22 decoded0
|
||||
|
||||
decoded0=decoded
|
||||
annot=' '
|
||||
if(nap.ne.0) then
|
||||
write(annot,'(a1,i1)') 'a',nap
|
||||
if(qual.lt.0.17) decoded0(22:22)='?'
|
||||
endif
|
||||
write(*,1000) params%nutc,snr,dt,nint(freq),decoded0,annot
|
||||
1000 format(i6.6,i4,f5.1,i5,' ~ ',1x,a22,1x,a2)
|
||||
write(13,1002) params%nutc,nint(sync),snr,dt,freq,0,decoded0
|
||||
1002 format(i6.6,i4,i5,f6.1,f8.0,i4,3x,a22,' FT8')
|
||||
call flush(6)
|
||||
call flush(13)
|
||||
|
||||
select type(this)
|
||||
type is (counting_ft8_decoder)
|
||||
|
@ -1,16 +1,20 @@
|
||||
subroutine fix_contest_msg(mycall,mygrid,hiscall,msg)
|
||||
subroutine fix_contest_msg(mygrid,msg)
|
||||
|
||||
! If msg is "mycall hiscall grid1" and distance from mygrid to grid1 is more
|
||||
! thsn 10000 km, change "grid1" to "R grid2" where grid2 is the antipodes
|
||||
! of grid1.
|
||||
! If distance from mygrid to grid1 is more thsn 10000 km, change "grid1"
|
||||
! to "R grid2" where grid2 is the antipodes of grid1.
|
||||
|
||||
character*6 mycall,mygrid,hiscall
|
||||
character*6 mygrid
|
||||
character*22 msg
|
||||
character*6 g1,g2
|
||||
logical isgrid
|
||||
|
||||
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'
|
||||
|
||||
n=len(trim(msg))
|
||||
if(n.lt.4) return
|
||||
|
||||
g1=msg(n-3:n)//' '
|
||||
if(isgrid(g1)) then
|
||||
call azdist(mygrid,g1,0.d0,nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter)
|
||||
|
@ -1,4 +1,4 @@
|
||||
subroutine bpdecode174(llr,apmask,maxiterations,decoded,cw,nharderror)
|
||||
subroutine bpdecode174(llr,apmask,maxiterations,decoded,cw,nharderror,iter)
|
||||
!
|
||||
! A log-domain belief propagation decoder for the (174,87) code.
|
||||
!
|
||||
|
@ -7,5 +7,6 @@ parameter (NSPS=1920) !Samples per symbol at 12000 S/s
|
||||
parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680)
|
||||
parameter (NMAX=15*12000) !Samples in iwave (180,000)
|
||||
parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra
|
||||
parameter (NHSYM=2*NMAX/NH1-1) !Number of symbol spectra (1/2-sym steps)
|
||||
parameter (NSTEP=NSPS/4) !Rough time-sync step size
|
||||
parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps)
|
||||
parameter (NDOWN=60) !Downsample factor
|
||||
|
30
lib/fsk4hf/ft8apset.f90
Normal file
@ -0,0 +1,30 @@
|
||||
subroutine ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype)
|
||||
parameter(NAPM=4,KK=87)
|
||||
character*12 mycall12,hiscall12
|
||||
character*22 msg,msgsent
|
||||
character*6 mycall,hiscall
|
||||
character*6 mygrid6,hisgrid6
|
||||
character*4 hisgrid
|
||||
logical bcontest
|
||||
integer apsym(KK)
|
||||
integer*1 msgbits(KK)
|
||||
integer itone(KK)
|
||||
|
||||
mycall=mycall12(1:6)
|
||||
hiscall=hiscall12(1:6)
|
||||
hisgrid=hisgrid6(1:4)
|
||||
if(len_trim(hiscall).eq.0) then
|
||||
iaptype=1
|
||||
hiscall="K9AN"
|
||||
else
|
||||
iaptype=2
|
||||
endif
|
||||
hisgrid=hisgrid6(1:4)
|
||||
! if(len_trim(hisgrid).eq.0) hisgrid="EN50"
|
||||
if(index(hisgrid," ").eq.0) hisgrid="EN50"
|
||||
msg=mycall//' '//hiscall//' '//hisgrid
|
||||
call genft8(msg,mygrid6,bcontest,msgsent,msgbits,itone)
|
||||
apsym=2*msgbits-1
|
||||
|
||||
return
|
||||
end subroutine ft8apset
|
@ -1,29 +1,75 @@
|
||||
subroutine ft8b(dd0,newdat,nfqso,ndepth,icand,sync0,f1,xdt,apsym,nharderrors, &
|
||||
dmin,nbadcrc,message,xsnr)
|
||||
subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,napwid, &
|
||||
lsubtract,nagain,iaptype,mygrid6,bcontest,sync0,f1,xdt,apsym,nharderrors,&
|
||||
dmin,nbadcrc,ipass,iera,message,xsnr)
|
||||
|
||||
use timer_module, only: timer
|
||||
include 'ft8_params.f90'
|
||||
parameter(NRECENT=10,NP2=2812)
|
||||
character message*22,msgsent*22
|
||||
character*12 recent_calls(NRECENT)
|
||||
character*6 mygrid6
|
||||
logical bcontest
|
||||
real a(5)
|
||||
real s1(0:7,ND),s2(0:7,NN)
|
||||
real ps(0:7)
|
||||
real rxdata(3*ND),llr(3*ND),llrap(3*ND) !Soft symbols
|
||||
real rxdata(3*ND),rxdatap(3*ND)
|
||||
real llr(3*ND),llra(3*ND),llr0(3*ND),llrap(3*ND) !Soft symbols
|
||||
real dd0(15*12000)
|
||||
integer*1 decoded(KK),apmask(3*ND),cw(3*ND)
|
||||
integer*1 msgbits(KK)
|
||||
integer apsym(KK),rr73(11)
|
||||
integer apsym(KK)
|
||||
integer mcq(28),mde(28),mrrr(16),m73(16),mrr73(16)
|
||||
integer itone(NN)
|
||||
integer icos7(0:6),ip(1)
|
||||
integer nappasses(0:5) ! the number of decoding passes to use for each QSO state
|
||||
integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
|
||||
complex cd0(3200)
|
||||
complex ctwk(32)
|
||||
complex csymb(32)
|
||||
logical newdat
|
||||
data rr73/-1,1,1,1,1,1,1,-1,1,1,-1/
|
||||
logical first,newdat,lsubtract,lapon,nagain
|
||||
data icos7/2,5,6,0,4,1,3/
|
||||
data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/
|
||||
data mrrr/0,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1/
|
||||
data m73/0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0/
|
||||
data mde/1,1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1/
|
||||
data mrr73/0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1/
|
||||
data first/.true./
|
||||
save nappasses,naptypes
|
||||
|
||||
max_iterations=40
|
||||
norder=2
|
||||
if(ndepth.eq.3 .and. abs(nfqso-f1).lt.10.0) norder=3
|
||||
if(first) then
|
||||
mcq=2*mcq-1
|
||||
mde=2*mde-1
|
||||
mrrr=2*mrrr-1
|
||||
m73=2*m73-1
|
||||
mrr73=2*mrr73-1
|
||||
nappasses(0)=2
|
||||
nappasses(1)=2
|
||||
nappasses(2)=2
|
||||
nappasses(3)=4
|
||||
nappasses(4)=4
|
||||
nappasses(5)=3
|
||||
|
||||
! iaptype
|
||||
!------------------------
|
||||
! 1 CQ ??? ???
|
||||
! 2 MyCall ??? ???
|
||||
! 3 MyCall DxCall ???
|
||||
! 4 MyCall DxCall RRR
|
||||
! 5 MyCall DxCall 73
|
||||
! 6 MyCall DxCall RR73
|
||||
! 7 ??? DxCall ???
|
||||
|
||||
naptypes(0,1:4)=(/1,2,0,0/)
|
||||
naptypes(1,1:4)=(/2,3,0,0/)
|
||||
naptypes(2,1:4)=(/2,3,0,0/)
|
||||
naptypes(3,1:4)=(/3,4,5,6/)
|
||||
naptypes(4,1:4)=(/3,4,5,6/)
|
||||
naptypes(5,1:4)=(/3,1,2,0/) !?
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
max_iterations=30
|
||||
nharderrors=-1
|
||||
fs2=12000.0/NDOWN
|
||||
dt2=1.0/fs2
|
||||
twopi=8.0*atan(1.0)
|
||||
@ -34,9 +80,9 @@ subroutine ft8b(dd0,newdat,nfqso,ndepth,icand,sync0,f1,xdt,apsym,nharderrors,
|
||||
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||
call timer('ft8_down',1)
|
||||
|
||||
i0=nint(xdt*fs2) !Initial guess for start of signal
|
||||
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
|
||||
smax=0.0
|
||||
do idt=i0-16,i0+16 !Search over +/- half a symbol
|
||||
do idt=i0-8,i0+8 !Search over +/- one quarter symbol
|
||||
call sync8d(cd0,idt,ctwk,0,sync)
|
||||
if(sync.gt.smax) then
|
||||
smax=sync
|
||||
@ -78,6 +124,26 @@ subroutine ft8b(dd0,newdat,nfqso,ndepth,icand,sync0,f1,xdt,apsym,nharderrors,
|
||||
call four2a(csymb,32,1,-1,1)
|
||||
s2(0:7,k)=abs(csymb(1:8))
|
||||
enddo
|
||||
|
||||
! sync quality check
|
||||
is1=0
|
||||
is2=0
|
||||
is3=0
|
||||
do k=1,7
|
||||
ip=maxloc(s2(:,k))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||
ip=maxloc(s2(:,k+36))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||
ip=maxloc(s2(:,k+72))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||
enddo
|
||||
! hard sync sum - max is 21
|
||||
nsync=is1+is2+is3
|
||||
if(nsync .le. 6) then ! bail out
|
||||
nbadcrc=1
|
||||
return
|
||||
endif
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
if(k.le.7) cycle
|
||||
@ -93,9 +159,54 @@ subroutine ft8b(dd0,newdat,nfqso,ndepth,icand,sync0,f1,xdt,apsym,nharderrors,
|
||||
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
|
||||
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
|
||||
r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
|
||||
rxdata(3*j-2)=r4
|
||||
rxdata(3*j-1)=r2
|
||||
rxdata(3*j)=r1
|
||||
i4=3*j-2
|
||||
i2=3*j-1
|
||||
i1=3*j
|
||||
rxdata(i4)=r4
|
||||
rxdata(i2)=r2
|
||||
rxdata(i1)=r1
|
||||
rxdatap(i4)=r4
|
||||
rxdatap(i2)=r2
|
||||
rxdatap(i1)=r1
|
||||
|
||||
if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then
|
||||
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
|
||||
if(j.eq.39) then ! take care of bits that live in symbol 39
|
||||
if(apsym(28).lt.0) then
|
||||
rxdatap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
rxdatap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
else
|
||||
rxdatap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
|
||||
rxdatap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with ap bits 116 and 117. Take care of metric for bit 115.
|
||||
! if(j.eq.39) then ! take care of bit 115
|
||||
! iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
|
||||
! if(iii.eq.0) rxdatap(i4)=ps(4)-ps(0)
|
||||
! if(iii.eq.1) rxdatap(i4)=ps(5)-ps(1)
|
||||
! if(iii.eq.2) rxdatap(i4)=ps(6)-ps(2)
|
||||
! if(iii.eq.3) rxdatap(i4)=ps(7)-ps(3)
|
||||
! endif
|
||||
|
||||
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
|
||||
! take care of metrics for bits 142 and 143
|
||||
if(j.eq.48) then ! bit 144 is always 1
|
||||
rxdatap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
|
||||
rxdatap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
|
||||
endif
|
||||
|
||||
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
|
||||
! take care of metrics for bits 155 and 156
|
||||
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
|
||||
rxdatap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
rxdatap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
endif
|
||||
|
||||
enddo
|
||||
|
||||
rxav=sum(rxdata)/(3.0*ND)
|
||||
@ -107,84 +218,141 @@ subroutine ft8b(dd0,newdat,nfqso,ndepth,icand,sync0,f1,xdt,apsym,nharderrors,
|
||||
rxsig=sqrt(rx2av)
|
||||
endif
|
||||
rxdata=rxdata/rxsig
|
||||
ss=0.84
|
||||
llr=2.0*rxdata/(ss*ss)
|
||||
! Let's just assume that rxsig is OK for rxdatap too...
|
||||
rxdatap=rxdatap/rxsig
|
||||
|
||||
! do iap=0,3
|
||||
do iap=0,0 !### Temporary ###
|
||||
if(iap.eq.0) then
|
||||
apmask=0
|
||||
apmask(160:162)=1
|
||||
llrap=llr
|
||||
llrap(160:162)=5.0*apsym(73:75)/ss
|
||||
elseif(iap.eq.1) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=0.0
|
||||
llrap(88:115)=5.0*apsym(1:28)/ss
|
||||
llrap(160:162)=5.0*apsym(73:75)/ss
|
||||
where(apmask.eq.0) llrap=llr
|
||||
elseif(iap.eq.2) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=0.0
|
||||
llrap(88:143)=5.0*apsym(1:56)/ss
|
||||
llrap(160:162)=5.0*apsym(73:75)/ss
|
||||
where(apmask.eq.0) llrap=llr
|
||||
elseif(iap.eq.3) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144:154)=1 ! RRR or 73
|
||||
apmask(160:162)=1 ! 3 extra bits
|
||||
llrap=0.0
|
||||
llrap(88:143)=5.0*apsym(1:56)/ss
|
||||
llrap(144:154)=5.0*rr73/ss
|
||||
llrap(160:162)=5.0*apsym(73:75)/ss
|
||||
where(apmask.eq.0) llrap=llr
|
||||
endif
|
||||
cw=0
|
||||
call timer('bpd174 ',0)
|
||||
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors)
|
||||
call timer('bpd174 ',1)
|
||||
dmin=0.0
|
||||
if(nharderrors.lt.0 .and. ndepth.ge.2) then
|
||||
call timer('osd174 ',0)
|
||||
call osd174(llrap,norder,decoded,cw,nharderrors,dmin)
|
||||
call timer('osd174 ',1)
|
||||
endif
|
||||
nbadcrc=1
|
||||
message=' '
|
||||
xsnr=-99.0
|
||||
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||
if( nharderrors.ge.0 .and. dmin.le.30.0 .and. nharderrors .lt. 30) then
|
||||
call chkcrc12a(decoded,nbadcrc)
|
||||
else
|
||||
nharderrors=-1
|
||||
cycle
|
||||
endif
|
||||
if(nbadcrc.eq.0) then
|
||||
call extractmessage174(decoded,message,ncrcflag,recent_calls,nrecent)
|
||||
call genft8(message,msgsent,msgbits,itone)
|
||||
! call subtractft8(dd0,itone,f1,xdt2)
|
||||
xsig=0.0
|
||||
xnoi=0.0
|
||||
do i=1,79
|
||||
xsig=xsig+s2(itone(i),i)**2
|
||||
ios=mod(itone(i)+4,7)
|
||||
xnoi=xnoi+s2(ios,i)**2
|
||||
enddo
|
||||
xsnr=0.001
|
||||
if( xnoi.gt.0 .and. xnoi.lt.xsig ) xsnr=xsig/xnoi-1.0
|
||||
xsnr=10.0*log10(xsnr)-27.0
|
||||
if( xsnr .lt. -24.0 ) xsnr=-24.0
|
||||
! write(50,3050) icand,sync0,f1,xdt,nharderrors,dmin,message,iap
|
||||
!3050 format(i3,3f10.3,i5,f10.3,2x,a22,i3)
|
||||
return
|
||||
endif
|
||||
ss=0.84
|
||||
llr0=2.0*rxdata/(ss*ss)
|
||||
llra=2.0*rxdatap/(ss*ss) ! llr's for use with ap
|
||||
apmag=4.0
|
||||
|
||||
! pass #
|
||||
!------------------------------
|
||||
! 1 regular decoding
|
||||
! 2 erase 24
|
||||
! 3 erase 48
|
||||
! 4 ap pass 1
|
||||
! 5 ap pass 2
|
||||
! 6 ap pass 3
|
||||
! 7 ap pass 4, etc.
|
||||
|
||||
if(lapon) then
|
||||
npasses=3+nappasses(nQSOProgress)
|
||||
else
|
||||
npasses=3
|
||||
endif
|
||||
|
||||
do ipass=1,npasses
|
||||
|
||||
llr=llr0
|
||||
if(ipass.ne.2 .and. ipass.ne.3) nblank=0
|
||||
if(ipass.eq.2) nblank=24
|
||||
if(ipass.eq.3) nblank=48
|
||||
if(nblank.gt.0) llr(1:nblank)=0.
|
||||
|
||||
if(ipass.le.3) then
|
||||
apmask=0
|
||||
llrap=llr
|
||||
iaptype=0
|
||||
endif
|
||||
|
||||
if(ipass .gt. 3) then
|
||||
iaptype=naptypes(nQSOProgress,ipass-3)
|
||||
if(iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
||||
if(iaptype.eq.1 .or. iaptype.eq.2 ) then ! AP,???,???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! first 28 bits are AP
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
if(iaptype.eq.1) llrap(88:115)=apmag*mcq/ss
|
||||
if(iaptype.eq.2) llrap(88:115)=apmag*apsym(1:28)/ss
|
||||
llrap(116:117)=llra(116:117)
|
||||
llrap(142:143)=llra(142:143)
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
if(iaptype.eq.3) then ! mycall, dxcall, ???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144:159)=1 ! RRR or 73 or RR73
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)/ss
|
||||
if(iaptype.eq.4) llrap(144:159)=apmag*mrrr/ss
|
||||
if(iaptype.eq.5) llrap(144:159)=apmag*m73/ss
|
||||
if(iaptype.eq.6) llrap(144:159)=apmag*mrr73/ss
|
||||
endif
|
||||
if(iaptype.eq.7) then ! ???, dxcall, ???
|
||||
apmask=0
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(115)=llra(115)
|
||||
llrap(116:143)=apmag*apsym(29:56)/ss
|
||||
llrap(144)=-apmag/ss
|
||||
endif
|
||||
endif
|
||||
|
||||
cw=0
|
||||
call timer('bpd174 ',0)
|
||||
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, &
|
||||
niterations)
|
||||
call timer('bpd174 ',1)
|
||||
dmin=0.0
|
||||
if(ndepth.eq.3 .and. nharderrors.lt.0) then
|
||||
norder=1
|
||||
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then
|
||||
if(ipass.le.3 .and. .not.nagain) then
|
||||
norder=2
|
||||
else ! norder=3 for nagain and AP decodes
|
||||
norder=3
|
||||
endif
|
||||
endif
|
||||
call timer('osd174 ',0)
|
||||
call osd174(llrap,apmask,norder,decoded,cw,nharderrors,dmin)
|
||||
call timer('osd174 ',1)
|
||||
endif
|
||||
nbadcrc=1
|
||||
message=' '
|
||||
xsnr=-99.0
|
||||
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||
if(any(decoded(75:75).ne.0)) cycle !Reject if any of the 3 extra bits are nonzero
|
||||
if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. &
|
||||
.not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. &
|
||||
.not.(ipass.gt.1 .and. nharderrors.gt.39) .and. &
|
||||
.not.(ipass.eq.3 .and. nharderrors.gt.30) &
|
||||
) then
|
||||
call chkcrc12a(decoded,nbadcrc)
|
||||
else
|
||||
nharderrors=-1
|
||||
cycle
|
||||
endif
|
||||
if(nbadcrc.eq.0) then
|
||||
call extractmessage174(decoded,message,ncrcflag,recent_calls,nrecent)
|
||||
call genft8(message,mygrid6,bcontest,msgsent,msgbits,itone)
|
||||
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
|
||||
xsig=0.0
|
||||
xnoi=0.0
|
||||
do i=1,79
|
||||
xsig=xsig+s2(itone(i),i)**2
|
||||
ios=mod(itone(i)+4,7)
|
||||
xnoi=xnoi+s2(ios,i)**2
|
||||
enddo
|
||||
xsnr=0.001
|
||||
if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0
|
||||
xsnr=10.0*log10(xsnr)-27.0
|
||||
if(xsnr .lt. -24.0) xsnr=-24.0
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine ft8b
|
||||
|
@ -8,19 +8,23 @@ program ft8sim
|
||||
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
|
||||
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" sorm f0 DT fdop del nfiles snr'
|
||||
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*,'sorm: "s" for single signal at 1500 Hz, "m" for 25 signals'
|
||||
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
|
||||
@ -48,6 +52,8 @@ program ft8sim
|
||||
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)
|
||||
@ -60,7 +66,8 @@ program ft8sim
|
||||
if(snrdb.gt.90.0) sig=1.0
|
||||
txt=NN*NSPS/12000.0
|
||||
|
||||
call genft8(msg,msgsent,msgbits,itone) !Source-encode, then get itone()
|
||||
! 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)
|
||||
|
@ -1,4 +1,4 @@
|
||||
subroutine genft8(msg,msgsent,msgbits,itone)
|
||||
subroutine genft8(msg,mygrid,bcontest,msgsent,msgbits,itone)
|
||||
|
||||
! Encode an FT8 message, producing array itone().
|
||||
|
||||
@ -6,8 +6,10 @@ subroutine genft8(msg,msgsent,msgbits,itone)
|
||||
use packjt
|
||||
include 'ft8_params.f90'
|
||||
character*22 msg,msgsent
|
||||
character*6 mygrid,g1,g2,g3,g4
|
||||
character*87 cbits
|
||||
! logical checksumok
|
||||
logical*1 bcontest
|
||||
logical isgrid
|
||||
integer*4 i4Msg6BitWords(12) !72-bit message as 6-bit words
|
||||
integer*1 msgbits(KK),codeword(3*ND)
|
||||
integer*1, target:: i1Msg8BitBytes(11)
|
||||
@ -15,8 +17,42 @@ subroutine genft8(msg,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
|
||||
|
||||
i3bit=0 !### temporary ###
|
||||
write(cbits,1000) i4Msg6BitWords,32*i3bit
|
||||
1000 format(12b6.6,b8.8)
|
||||
|
@ -1,9 +1,10 @@
|
||||
subroutine osd174(llr,norder,decoded,cw,nhardmin,dmin)
|
||||
subroutine osd174(llr,apmask,norder,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)
|
||||
@ -36,6 +37,8 @@ endif
|
||||
|
||||
! re-order received vector to place systematic msg bits at the end
|
||||
rx=llr(colorder+1)
|
||||
apmaskr=apmask(colorder+1)
|
||||
|
||||
|
||||
! hard decode the received word
|
||||
hdec=0
|
||||
@ -71,7 +74,7 @@ do id=1,K ! diagonal element indices
|
||||
endif
|
||||
do ii=1,K
|
||||
if( ii .ne. id .and. genmrb(ii,id) .eq. 1 ) then
|
||||
genmrb(ii,1:N)=mod(genmrb(ii,1:N)+genmrb(id,1:N),2)
|
||||
genmrb(ii,1:N)=ieor(genmrb(ii,1:N),genmrb(id,1:N))
|
||||
endif
|
||||
enddo
|
||||
exit
|
||||
@ -91,6 +94,7 @@ 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)
|
||||
|
||||
s1=sum(absrx(1:K))
|
||||
s2=sum(absrx(K+1:N))
|
||||
@ -110,22 +114,24 @@ do iorder=1,norder
|
||||
mi(K-iorder+1:K)=1
|
||||
iflag=0
|
||||
do while(iflag .ge. 0 )
|
||||
dpat=sum(mi*absrx(1:K))
|
||||
nt=nt+1
|
||||
if( dpat .lt. thresh ) then ! reject unlikely error patterns
|
||||
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)
|
||||
thresh=rho*dmin
|
||||
if(all(iand(apmaskr(1:K),mi).eq.0)) then ! reject patterns with ap bits
|
||||
dpat=sum(mi*absrx(1:K))
|
||||
nt=nt+1
|
||||
if( dpat .lt. thresh ) then ! reject unlikely error patterns
|
||||
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)
|
||||
thresh=rho*dmin
|
||||
endif
|
||||
else
|
||||
nrejected=nrejected+1
|
||||
endif
|
||||
else
|
||||
nrejected=nrejected+1
|
||||
endif
|
||||
endif
|
||||
! get the next test error pattern, iflag will go negative
|
||||
! when the last pattern with weight iorder has been generated
|
||||
call nextpat(mi,k,iorder,iflag)
|
||||
|
@ -10,7 +10,7 @@ subroutine subtractft8(dd,itone,f0,dt)
|
||||
use timer_module, only: timer
|
||||
|
||||
parameter (NMAX=15*12000,NFRAME=1920*79)
|
||||
parameter (NFFT=NMAX,NFILT=400)
|
||||
parameter (NFFT=NMAX,NFILT=1400)
|
||||
real*4 dd(NMAX), window(-NFILT/2:NFILT/2)
|
||||
complex cref,camp,cfilt,cw
|
||||
integer itone(79)
|
||||
|
@ -1,7 +1,8 @@
|
||||
subroutine sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand)
|
||||
|
||||
include 'ft8_params.f90'
|
||||
parameter (JZ=31) !DT up to +/- 2.5 s
|
||||
! Search over +/- 1.5s relative to 0.5s TX start time.
|
||||
parameter (JZ=38)
|
||||
complex cx(0:NH1)
|
||||
real s(NH1,NHSYM)
|
||||
real savg(NH1)
|
||||
@ -18,16 +19,13 @@ subroutine sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
data icos7/2,5,6,0,4,1,3/ !Costas 7x7 tone pattern
|
||||
equivalence (x,cx)
|
||||
|
||||
! Compute symbol spectra at half-symbol steps.
|
||||
! Compute symbol spectra, stepping by NSTEP steps.
|
||||
savg=0.
|
||||
istep=NSPS/2 !960
|
||||
tstep=istep/12000.0 !0.08 s
|
||||
tstep=NSTEP/12000.0
|
||||
df=12000.0/NFFT1 !3.125 Hz
|
||||
|
||||
! Compute symbol spectra at half-symbol steps
|
||||
fac=1.0/300.0
|
||||
do j=1,NHSYM
|
||||
ia=(j-1)*istep + 1
|
||||
ia=(j-1)*NSTEP + 1
|
||||
ib=ia+NSPS-1
|
||||
x(1:NSPS)=fac*dd(ia:ib)
|
||||
x(NSPS+1:)=0.
|
||||
@ -45,25 +43,41 @@ subroutine sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
|
||||
ia=max(1,nint(nfa/df))
|
||||
ib=nint(nfb/df)
|
||||
nssy=NSPS/NSTEP ! # steps per symbol
|
||||
nfos=NFFT1/NSPS ! # frequency bin oversampling factor
|
||||
jstrt=0.5/tstep
|
||||
|
||||
do i=ia,ib
|
||||
do j=-JZ,JZ
|
||||
t=0.
|
||||
t0=0.
|
||||
do j=-JZ,+JZ
|
||||
ta=0.
|
||||
tb=0.
|
||||
tc=0.
|
||||
t0a=0.
|
||||
t0b=0.
|
||||
t0c=0.
|
||||
do n=0,6
|
||||
k=j+2*n
|
||||
if(k.ge.1) then
|
||||
t=t + s(i+2*icos7(n),k)
|
||||
t0=t0 + sum(s(i:i+12:2,k))
|
||||
k=j+jstrt+nssy*n
|
||||
if(k.ge.1.and.k.le.NHSYM) then
|
||||
ta=ta + s(i+nfos*icos7(n),k)
|
||||
t0a=t0a + sum(s(i:i+nfos*6:nfos,k))
|
||||
endif
|
||||
t=t + s(i+2*icos7(n),k+72)
|
||||
t0=t0 + sum(s(i:i+12:2,k+72))
|
||||
if(k+144.le.NHSYM) then
|
||||
t=t + s(i+2*icos7(n),k+144)
|
||||
t0=t0 + sum(s(i:i+12:2,k+144))
|
||||
tb=tb + s(i+nfos*icos7(n),k+nssy*36)
|
||||
t0b=t0b + sum(s(i:i+nfos*6:nfos,k+nssy*36))
|
||||
if(k+nssy*72.le.NHSYM) then
|
||||
tc=tc + s(i+nfos*icos7(n),k+nssy*72)
|
||||
t0c=t0c + sum(s(i:i+nfos*6:nfos,k+nssy*72))
|
||||
endif
|
||||
enddo
|
||||
t=ta+tb+tc
|
||||
t0=t0a+t0b+t0c
|
||||
t0=(t0-t)/6.0
|
||||
sync2d(i,j)=t/t0
|
||||
sync_abc=t/t0
|
||||
|
||||
t=tb+tc
|
||||
t0=t0b+t0c
|
||||
t0=(t0-t)/6.0
|
||||
sync_bc=t/t0
|
||||
sync2d(i,j)=max(sync_abc,sync_bc)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
@ -84,8 +98,7 @@ subroutine sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
|
||||
candidate0=0.
|
||||
k=0
|
||||
syncmin=2.0
|
||||
do i=1,100
|
||||
do i=1,200
|
||||
n=ia + indx(iz+1-i) - 1
|
||||
if(red(n).lt.syncmin) exit
|
||||
if(k.lt.200) k=k+1
|
||||
@ -115,13 +128,21 @@ subroutine sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
fac=20.0/maxval(s)
|
||||
s=fac*s
|
||||
|
||||
! Sort by sync
|
||||
! call indexx(candidate0(3,1:ncand),ncand,indx)
|
||||
! Sort by frequency
|
||||
call indexx(candidate0(1,1:ncand),ncand,indx)
|
||||
k=1
|
||||
! do i=ncand,1,-1
|
||||
do i=1,ncand
|
||||
j=indx(i)
|
||||
candidate(1,i)=abs(candidate0(1,j))
|
||||
candidate(2,i)=candidate0(2,j)
|
||||
candidate(3,i)=candidate0(3,j)
|
||||
if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then
|
||||
candidate(1,k)=abs(candidate0(1,j))
|
||||
candidate(2,k)=candidate0(2,j)
|
||||
candidate(3,k)=candidate0(3,j)
|
||||
k=k+1
|
||||
endif
|
||||
enddo
|
||||
|
||||
ncand=k-1
|
||||
return
|
||||
end subroutine sync8
|
||||
|
@ -7,7 +7,7 @@ module ft8_decode
|
||||
end type ft8_decoder
|
||||
|
||||
abstract interface
|
||||
subroutine ft8_decode_callback (this,sync,snr,dt,freq,nbadcrc,decoded)
|
||||
subroutine ft8_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
import ft8_decoder
|
||||
implicit none
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
@ -15,93 +15,125 @@ module ft8_decode
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
real, intent(in) :: freq
|
||||
integer, intent(in) :: nbadcrc
|
||||
character(len=22), intent(in) :: decoded
|
||||
integer, intent(in) :: nap
|
||||
real, intent(in) :: qual
|
||||
end subroutine ft8_decode_callback
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine decode(this,callback,iwave,nfqso,newdat,nutc,nfa, &
|
||||
nfb,nagain,ndepth,nsubmode,mycall12,hiscall12,hisgrid6)
|
||||
!use wavhdr
|
||||
subroutine decode(this,callback,iwave,nQSOProgress,nfqso,nftx,newdat, &
|
||||
nutc,nfa,nfb,nexp_decode,ndepth,nagain,lapon,napwid,mycall12, &
|
||||
mygrid6,hiscall12,hisgrid6)
|
||||
! use wavhdr
|
||||
use timer_module, only: timer
|
||||
include 'fsk4hf/ft8_params.f90'
|
||||
!type(hdr) h
|
||||
! type(hdr) h
|
||||
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
procedure(ft8_decode_callback) :: callback
|
||||
real s(NH1,NHSYM)
|
||||
real candidate(3,200)
|
||||
real dd(15*12000)
|
||||
logical, intent(in) :: newdat, nagain
|
||||
logical, intent(in) :: lapon,nagain
|
||||
logical newdat,lsubtract,ldupe,bcontest
|
||||
character*12 mycall12, hiscall12
|
||||
character*6 hisgrid6
|
||||
character*6 mygrid6,hisgrid6
|
||||
integer*2 iwave(15*12000)
|
||||
integer apsym(KK)
|
||||
character datetime*13,message*22
|
||||
character*22 allmessages(100)
|
||||
integer allsnrs(100)
|
||||
save s,dd
|
||||
|
||||
bcontest=iand(nexp_decode,128).ne.0
|
||||
this%callback => callback
|
||||
write(datetime,1001) nutc !### TEMPORARY ###
|
||||
1001 format("000000_",i6.6)
|
||||
|
||||
if(index(hisgrid6," ").eq.0) hisgrid6="EN50"
|
||||
call ft8apset(mycall12,hiscall12,hisgrid6,apsym)
|
||||
|
||||
call ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype)
|
||||
dd=iwave
|
||||
call timer('sync8 ',0)
|
||||
call sync8(dd,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
call timer('sync8 ',1)
|
||||
ndecodes=0
|
||||
allmessages=' '
|
||||
allsnrs=0
|
||||
ifa=nfa
|
||||
ifb=nfb
|
||||
if(nagain) then
|
||||
ifa=nfqso-10
|
||||
ifb=nfqso+10
|
||||
endif
|
||||
|
||||
syncmin=2.0
|
||||
do icand=1,ncand
|
||||
sync=candidate(3,icand)
|
||||
if(sync.lt.syncmin) cycle
|
||||
f1=candidate(1,icand)
|
||||
xdt=candidate(2,icand)
|
||||
nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ###
|
||||
call timer('ft8b ',0)
|
||||
call ft8b(dd,newdat,nfqso,ndepth,icand,sync,f1,xdt,apsym,nharderrors, &
|
||||
dmin,nbadcrc,message,xsnr)
|
||||
nsnr=xsnr
|
||||
xdt=xdt-0.6
|
||||
call timer('ft8b ',1)
|
||||
if (associated(this%callback)) call this%callback(sync,nsnr,xdt, &
|
||||
f1,nbadcrc,message)
|
||||
! write(*,'(f7.2,i5,f7.2,f9.1,i5,f7.2,2x,a22)') sync,nsnr,xdt,f1,nharderrors,dmin,message
|
||||
! write(13,1110) datetime,0,nsnr,xdt,f1,nharderrors,dmin,message
|
||||
!1110 format(a13,2i4,f6.2,f7.1,i4,' ~ ',f6.2,2x,a22,' FT8')
|
||||
! write(51,3051) xdt,f1,sync,dmin,nsnr,nharderrors,nbadcrc,message
|
||||
!3051 format(4f9.1,3i5,2x,a22)
|
||||
! flush(51)
|
||||
enddo
|
||||
!h=default_header(12000,NMAX)
|
||||
!open(10,file='subtract.wav',status='unknown',access='stream')
|
||||
!iwave=nint(dd)
|
||||
!write(10) h,iwave
|
||||
!close(10)
|
||||
return
|
||||
! For now:
|
||||
! ndepth=1: no subtraction, 1 pass, belief propagation only
|
||||
! ndepth=2: subtraction, 2 passes, belief propagation only
|
||||
! ndepth=3: subtraction, 2 passes, bp+osd2 at and near nfqso
|
||||
if(ndepth.eq.1) npass=1
|
||||
if(ndepth.ge.2) npass=2
|
||||
do ipass=1,npass
|
||||
newdat=.true. ! Is this a problem? I hijacked newdat.
|
||||
if(ipass.eq.1) then
|
||||
lsubtract=.true.
|
||||
if(ndepth.eq.1) lsubtract=.false.
|
||||
syncmin=1.5
|
||||
else
|
||||
lsubtract=.false.
|
||||
syncmin=1.5
|
||||
endif
|
||||
call timer('sync8 ',0)
|
||||
call sync8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand)
|
||||
call timer('sync8 ',1)
|
||||
do icand=1,ncand
|
||||
sync=candidate(3,icand)
|
||||
f1=candidate(1,icand)
|
||||
xdt=candidate(2,icand)
|
||||
nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ###
|
||||
call timer('ft8b ',0)
|
||||
call ft8b(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,napwid, &
|
||||
lsubtract,nagain,iaptype,mygrid6,bcontest,sync,f1,xdt,apsym, &
|
||||
nharderrors,dmin,nbadcrc,iappass,iera,message,xsnr)
|
||||
nsnr=nint(xsnr)
|
||||
xdt=xdt-0.5
|
||||
hd=nharderrors+dmin
|
||||
call timer('ft8b ',1)
|
||||
if(nbadcrc.eq.0) then
|
||||
call jtmsg(message,iflag)
|
||||
if(bcontest) call fix_contest_msg(mygrid6,message)
|
||||
if(iand(iflag,16).ne.0) message(22:22)='?'
|
||||
if(iand(iflag,15).eq.0) then
|
||||
ldupe=.false.
|
||||
do id=1,ndecodes
|
||||
if(message.eq.allmessages(id).and.nsnr.le.allsnrs(id)) ldupe=.true.
|
||||
enddo
|
||||
if(.not.ldupe) then
|
||||
ndecodes=ndecodes+1
|
||||
allmessages(ndecodes)=message
|
||||
allsnrs(ndecodes)=nsnr
|
||||
endif
|
||||
! write(81,1004) nutc,ncand,icand,ipass,iaptype,iappass, &
|
||||
! iflag,nharderrors,dmin,hd,min(sync,999.0),nint(xsnr), &
|
||||
! xdt,nint(f1),message
|
||||
! flush(81)
|
||||
if(.not.ldupe .and. associated(this%callback)) then
|
||||
qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0]
|
||||
call this%callback(sync,nsnr,xdt,f1,message,iaptype,qual)
|
||||
endif
|
||||
else
|
||||
write(19,1004) nutc,ncand,icand,ipass,iaptype,iappass, &
|
||||
iflag,nharderrors,dmin,hd,min(sync,999.0),nint(xsnr), &
|
||||
xdt,nint(f1),message
|
||||
1004 format(i6.6,2i4,3i2,2i3,3f6.1,i4,f6.2,i5,2x,a22)
|
||||
flush(19)
|
||||
endif
|
||||
endif
|
||||
enddo
|
||||
! h=default_header(12000,NMAX)
|
||||
! open(10,file='subtract.wav',status='unknown',access='stream')
|
||||
! iwave=nint(dd)
|
||||
! write(10) h,iwave
|
||||
! close(10)
|
||||
enddo
|
||||
return
|
||||
end subroutine decode
|
||||
|
||||
end module ft8_decode
|
||||
|
||||
subroutine ft8apset(mycall12,hiscall12,hisgrid6,apsym)
|
||||
parameter(NAPM=4,KK=87)
|
||||
character*12 mycall12,hiscall12
|
||||
character*22 msg,msgsent
|
||||
character*6 mycall,hiscall
|
||||
character*6 hisgrid6
|
||||
character*4 hisgrid
|
||||
integer apsym(KK)
|
||||
integer*1 msgbits(KK)
|
||||
integer itone(KK)
|
||||
|
||||
mycall=mycall12(1:6)
|
||||
hiscall=hiscall12(1:6)
|
||||
hisgrid=hisgrid6(1:4)
|
||||
msg=mycall//' '//hiscall//' '//hisgrid
|
||||
call genft8(msg,msgsent,msgbits,itone)
|
||||
apsym=2*msgbits-1
|
||||
return
|
||||
end subroutine ft8apset
|
||||
|
@ -41,13 +41,17 @@ subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype)
|
||||
data first/.true./
|
||||
save
|
||||
|
||||
if( first ) then
|
||||
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
|
||||
pi=4.*atan(1.0)
|
||||
pi=4.0*atan(1.0)
|
||||
twopi=8.*atan(1.0)
|
||||
do i=1,12
|
||||
pp(i)=sin( (i-1)*pi/12 )
|
||||
pp(i)=sin((i-1)*pi/12)
|
||||
enddo
|
||||
endif
|
||||
|
||||
@ -174,14 +178,3 @@ subroutine genmsk144(msg0,mygrid,ichk,bcontest,msgsent,i4tone,itype)
|
||||
|
||||
999 return
|
||||
end subroutine genmsk144
|
||||
|
||||
logical function isgrid(g1)
|
||||
|
||||
character*4 g1
|
||||
|
||||
isgrid=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'
|
||||
|
||||
return
|
||||
end function isgrid
|
||||
|
12
lib/jt9.f90
@ -161,6 +161,8 @@ program jt9
|
||||
! Import FFTW wisdom, if available
|
||||
wisfile=trim(data_dir)//'/jt9_wisdom.dat'// C_NULL_CHAR
|
||||
iret=fftwf_import_wisdom_from_filename(wisfile)
|
||||
open(19,file=trim(data_dir)//'/false_decodes.txt',status='unknown', &
|
||||
position='append')
|
||||
|
||||
ntry65a=0
|
||||
ntry65b=0
|
||||
@ -187,7 +189,7 @@ program jt9
|
||||
if(infile(i1-5:i1-5).eq.'_') then
|
||||
read(infile(i1-4:i1-1),*,err=1) nutc
|
||||
else
|
||||
read(infile(i1-6:i1-3),*,err=1) nutc
|
||||
read(infile(i1-6:i1-1),*,err=1) nutc
|
||||
endif
|
||||
go to 2
|
||||
1 nutc=0
|
||||
@ -238,8 +240,8 @@ program jt9
|
||||
ingain=0
|
||||
call timer('symspec ',0)
|
||||
nminw=1
|
||||
call symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s,df3, &
|
||||
ihsym,npts8,pxdbmax)
|
||||
call symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb, &
|
||||
s,df3,ihsym,npts8,pxdbmax)
|
||||
call timer('symspec ',1)
|
||||
endif
|
||||
nhsym0=nhsym
|
||||
@ -260,9 +262,11 @@ program jt9
|
||||
shared_data%params%kin=64800
|
||||
shared_data%params%nzhsym=181
|
||||
shared_data%params%ndepth=ndepth
|
||||
shared_data%params%lapon=.true.
|
||||
shared_data%params%napwid=75
|
||||
shared_data%params%dttol=3.
|
||||
|
||||
shared_data%params%minsync=0 !### TEST ONLY
|
||||
! shared_data%params%minsync=0 !### TEST ONLY
|
||||
! shared_data%params%nfqso=1500 !### TEST ONLY
|
||||
! mycall="G3WDG " !### TEST ONLY
|
||||
! hiscall="VK7MO " !### TEST ONLY
|
||||
|
@ -9,7 +9,9 @@
|
||||
integer(c_int) :: nutc
|
||||
logical(c_bool) :: ndiskdat
|
||||
integer(c_int) :: ntr
|
||||
integer(c_int) :: nQSOProgress ! See MainWindow::m_QSOProgress for values
|
||||
integer(c_int) :: nfqso
|
||||
integer(c_int) :: nftx
|
||||
logical(c_bool) :: newdat
|
||||
integer(c_int) :: npts8
|
||||
integer(c_int) :: nfa
|
||||
@ -21,6 +23,8 @@
|
||||
integer(c_int) :: nsubmode
|
||||
logical(c_bool) :: nagain
|
||||
integer(c_int) :: ndepth
|
||||
logical(c_bool) :: lapon
|
||||
integer(c_int) :: napwid
|
||||
integer(c_int) :: ntxmode
|
||||
integer(c_int) :: nmode
|
||||
integer(c_int) :: minw
|
||||
|
131
lib/jtmsg.f90
Normal file
@ -0,0 +1,131 @@
|
||||
subroutine jtmsg(msg,iflag)
|
||||
|
||||
! Attempts to identify false decodes in JT-style messages.
|
||||
|
||||
! Returns iflag with sum of bits as follows:
|
||||
! ------------------------------------------
|
||||
! 1 Grid/Report invalid
|
||||
! 2 Second callsign invalid
|
||||
! 4 First callsign invalid
|
||||
! 8 Very unlikely free text
|
||||
! 16 Questionable free text
|
||||
! 0 Message is probably OK
|
||||
! ------------------------------------------
|
||||
|
||||
character*22 msg,t
|
||||
character*13 w1,w2,w3,w
|
||||
character*6 bc1,bc2,bc3
|
||||
character*1 c
|
||||
logical c1ok,c2ok,c3ok,isdigit,isletter,isgrid4
|
||||
|
||||
! Statement functions
|
||||
isdigit(c)=(ichar(c).ge.ichar('0')) .and. (ichar(c).le.ichar('9'))
|
||||
isletter(c)=(ichar(c).ge.ichar('A')) .and. (ichar(c).le.ichar('Z'))
|
||||
isgrid4(w)=(len_trim(w).eq.4 .and. &
|
||||
ichar(w(1:1)).ge.ichar('A') .and. ichar(w(1:1)).le.ichar('R') .and. &
|
||||
ichar(w(2:2)).ge.ichar('A') .and. ichar(w(2:2)).le.ichar('R') .and. &
|
||||
ichar(w(3:3)).ge.ichar('0') .and. ichar(w(3:3)).le.ichar('9') .and. &
|
||||
ichar(w(4:4)).ge.ichar('0') .and. ichar(w(4:4)).le.ichar('9'))
|
||||
|
||||
t=trim(msg) !Temporary copy of msg
|
||||
nt=len_trim(t)
|
||||
|
||||
! Check for standard messages
|
||||
! Insert underscore in "CQ AA " to "CQ ZZ ", "CQ nnn " to make them one word.
|
||||
if(t(1:3).eq.'CQ ' .and. isletter(t(4:4)) .and. &
|
||||
isletter(t(5:5)) .and. t(6:6).eq.' ') t(3:3)='_'
|
||||
if(t(1:3).eq.'CQ ' .and. isdigit(t(4:4)) .and. &
|
||||
isdigit(t(5:5)) .and. isdigit(t(6:6)) .and. t(7:7).eq.' ') t(3:3)='_'
|
||||
|
||||
! Parse first three words
|
||||
w1=' '
|
||||
w2=' '
|
||||
w3=' '
|
||||
i1=index(t,' ')
|
||||
if(i1.gt.0) w1(1:i1-1)=t(1:i1-1)
|
||||
t=t(i1+1:)
|
||||
i2=index(t,' ')
|
||||
if(i2.gt.0) w2(1:i2-1)=t(1:i2-1)
|
||||
t=t(i2+1:)
|
||||
i3=index(t,' ')
|
||||
if(i3.gt.0) w3(1:i3-1)=t(1:i3-1)
|
||||
|
||||
if(w1(1:3).eq.'CQ ' .or. w1(1:3).eq.'CQ_' .or. w1(1:3).eq.'DE ' .or. &
|
||||
w1(1:4).eq.'QRZ ') then
|
||||
! CQ/DE/QRZ: Should have one good callsign in w2 and maybe a grid/rpt in w3
|
||||
call chkcall(w2,bc2,c2ok)
|
||||
iflag=0
|
||||
if(.not.c2ok) iflag=iflag+2
|
||||
if(len_trim(w3).ne.0 .and. (.not.isgrid4(w3))) iflag=iflag+1
|
||||
if(w1(1:3).eq.'DE ' .and. c2ok) iflag=0
|
||||
if(iflag.eq.0) return
|
||||
endif
|
||||
|
||||
! Check for two calls and maybe a grid, rpt, R+rpr, RRR, or 73
|
||||
iflag=0
|
||||
call chkcall(w1,bc1,c1ok)
|
||||
call chkcall(w2,bc2,c2ok)
|
||||
if(.not.c1ok) iflag=iflag+4
|
||||
if(.not.c2ok) iflag=iflag+2
|
||||
if(len_trim(w3).ne.0 .and. (.not.isgrid4(w3)) .and. &
|
||||
w3(1:1).ne.'+' .and. w3(1:1).ne.'-' .and. &
|
||||
w3(1:2).ne.'R+' .and. w3(1:2).ne.'R-' .and. &
|
||||
w3(1:3).ne.'73 ' .and. w3(1:4).ne.'RRR ') iflag=iflag+1
|
||||
call chkcall(w3,bc3,c3ok)
|
||||
! Allow(?) non-standard messages of the form CQ AS OC K1JT
|
||||
if(w1(1:3).eq.'CQ_'.and.isletter(w2(1:1)).and.isletter(w2(2:2)).and. &
|
||||
w2(3:3).eq.' '.and.c3ok) iflag=0
|
||||
if(iflag.eq.0 .or. nt.gt.13) return
|
||||
|
||||
! Check for plausible free text
|
||||
|
||||
nc=0
|
||||
np=0
|
||||
do i=1,13
|
||||
c=msg(i:i)
|
||||
if(c.ne.' ') nc=nc+1 !Number of non-blank characters
|
||||
if(c.eq.'+') np=np+1 !Number of punctuation characters
|
||||
if(c.eq.'-') np=np+1
|
||||
if(c.eq.'.') np=np+1
|
||||
if(c.eq.'/') np=np+1
|
||||
if(c.eq.'?') np=np+1
|
||||
enddo
|
||||
nb=13-nc !Number of blanks
|
||||
iflag=16 !Mark as potentially questionable
|
||||
if(nc.ge.12 .or. (nc.ge.11 .and. np.gt.0)) then
|
||||
iflag=8 !Unlikely free text, flag it
|
||||
endif
|
||||
|
||||
! Save messages containing some common words
|
||||
if(msg(1:3).eq.'CQ ') iflag=0
|
||||
if(index(msg,'DE ').gt.0) iflag=0
|
||||
if(index(msg,'TU ').gt.0) iflag=0
|
||||
if(index(msg,' TU').gt.0) iflag=0
|
||||
if(index(msg,'73 ').gt.0) iflag=0
|
||||
if(index(msg,' 73').gt.0) iflag=0
|
||||
if(index(msg,'TNX').gt.0) iflag=0
|
||||
if(index(msg,'THX').gt.0) iflag=0
|
||||
if(index(msg,'EQSL').gt.0) iflag=0
|
||||
if(index(msg,'LOTW').gt.0) iflag=0
|
||||
if(index(msg,'DECOD').gt.0) iflag=0
|
||||
if(index(msg,'CHK').gt.0) iflag=0
|
||||
if(index(msg,'CLK').gt.0) iflag=0
|
||||
if(index(msg,'CLOCK').gt.0) iflag=0
|
||||
if(index(msg,'LOG').gt.0) iflag=0
|
||||
if(index(msg,'QRM').gt.0) iflag=0
|
||||
if(index(msg,'QSY').gt.0) iflag=0
|
||||
if(index(msg,'TEST').gt.0) iflag=0
|
||||
if(index(msg,'CQDX').gt.0) iflag=0
|
||||
if(index(msg,'CALL').gt.0) iflag=0
|
||||
if(index(msg,'QRZ').gt.0) iflag=0
|
||||
if(index(msg,'AUTO').gt.0) iflag=0
|
||||
if(index(msg,'PHOTO').gt.0) iflag=0
|
||||
if(index(msg,'HYBRID').gt.0) iflag=0
|
||||
|
||||
if(c1ok .and. w1(1:6).eq.bc1) iflag=0
|
||||
if(c2ok .and. w2(1:6).eq.bc2) iflag=0
|
||||
|
||||
if(nb.ge.4) iflag=0
|
||||
|
||||
return
|
||||
end subroutine jtmsg
|
@ -9,6 +9,7 @@ program msk144d2
|
||||
|
||||
character c
|
||||
character*80 line
|
||||
character*512 datadir
|
||||
character*500 infile
|
||||
character*12 mycall,hiscall
|
||||
character*6 mygrid
|
||||
@ -17,7 +18,7 @@ program msk144d2
|
||||
logical :: display_help=.false.
|
||||
logical*1 bShMsgs
|
||||
logical*1 bcontest
|
||||
logical*1 brxequal
|
||||
logical*1 btrain
|
||||
logical*1 bswl
|
||||
|
||||
type(wav_header) :: wav
|
||||
@ -25,6 +26,8 @@ program msk144d2
|
||||
integer*2 id2(30*12000)
|
||||
integer*2 ichunk(7*1024)
|
||||
|
||||
real*8 pcoeffs(5)
|
||||
|
||||
type (option) :: long_options(9) = [ &
|
||||
option ('ndepth',.true.,'c','ndepth',''), &
|
||||
option ('dxcall',.true.,'d','hiscall',''), &
|
||||
@ -45,8 +48,10 @@ program msk144d2
|
||||
hiscall=''
|
||||
bShMsgs=.false.
|
||||
bcontest=.false.
|
||||
brxequal=.false.
|
||||
btrain=.false.
|
||||
bswl=.false.
|
||||
datadir='.'
|
||||
pcoeffs=0.d0
|
||||
|
||||
do
|
||||
call getopt('c:d:ef:hm:n:rs',long_options,c,optarg,narglen,nstat,noffset,nremain,.true.)
|
||||
@ -69,7 +74,7 @@ program msk144d2
|
||||
case ('n')
|
||||
read (optarg(:narglen), *) ntol
|
||||
case ('r')
|
||||
brxequal=.true.
|
||||
btrain=.true.
|
||||
case ('s')
|
||||
bShMsgs=.true.
|
||||
end select
|
||||
@ -111,7 +116,7 @@ program msk144d2
|
||||
tt=sum(float(abs(id2(i:i+7*512-1))))
|
||||
if( tt .ne. 0.0 ) then
|
||||
call mskrtd(ichunk,nutc,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall,bShMsgs, &
|
||||
bcontest,brxequal,bswl,line)
|
||||
bcontest,btrain,pcoeffs,bswl,datadir,line)
|
||||
if( index(line,"&") .ne. 0 .or. &
|
||||
index(line,"^") .ne. 0 .or. &
|
||||
index(line,"!") .ne. 0 .or. &
|
||||
|
@ -209,7 +209,7 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
|
||||
if(.not. bshdecode) then
|
||||
call update_hasharray(recent_calls,nrecent,nhasharray)
|
||||
! Should we call fix_contest_msg() only if bcontest is true?
|
||||
call fix_contest_msg(mycall(1:6),mygrid,hiscall(1:6),msgreceived)
|
||||
call fix_contest_msg(mygrid,msgreceived)
|
||||
endif
|
||||
write(line,1020) nutc0,nsnr,tdec,nint(fest),decsym,msgreceived, &
|
||||
navg,ncorrected,eyeopening,char(0)
|
||||
|
@ -1,5 +1,9 @@
|
||||
module packjt
|
||||
|
||||
! These variables are accessible from outside via "use packjt":
|
||||
integer jt_itype,jt_nc1,jt_nc2,jt_ng,jt_k1,jt_k2
|
||||
character*6 jt_c1,jt_c2,jt_c3
|
||||
|
||||
contains
|
||||
|
||||
subroutine packbits(dbits,nsymd,m0,sym)
|
||||
@ -494,8 +498,17 @@ subroutine packbits(dbits,nsymd,m0,sym)
|
||||
ng=ng+32768
|
||||
|
||||
! Encode data into 6-bit words
|
||||
20 continue
|
||||
20 continue
|
||||
if(itype.ne.6) itype=max(nv2a,nv2b)
|
||||
jt_itype=itype
|
||||
jt_c1=c1
|
||||
jt_c2=c2
|
||||
jt_c3=c3
|
||||
jt_k1=k1
|
||||
jt_k2=k2
|
||||
jt_nc1=nc1
|
||||
jt_nc2=nc2
|
||||
jt_ng=ng
|
||||
dat(1)=iand(ishft(nc1,-22),63) !6 bits
|
||||
dat(2)=iand(ishft(nc1,-16),63) !6 bits
|
||||
dat(3)=iand(ishft(nc1,-10),63) !6 bits
|
||||
|
@ -1,17 +1,14 @@
|
||||
subroutine refspectrum(id2,id2b,kk,bclear,brefspec,buseref,fname)
|
||||
subroutine refspectrum(id2,bclear,brefspec,buseref,fname)
|
||||
|
||||
! Input:
|
||||
! id2 i*2 Raw 16-bit integer data, 12000 Hz sample rate
|
||||
! brefspec logical True when accumulating a reference spectrum
|
||||
|
||||
parameter (NFFT=6912,NH=NFFT/2,NPOLYLOW=400,NPOLYHIGH=2600)
|
||||
integer*2 id2(NFFT),id2b(120*12000)
|
||||
integer*2 id2(NFFT)
|
||||
logical*1 bclear,brefspec,buseref,blastuse
|
||||
|
||||
real x0(0:NH-1) !Input samples
|
||||
real x1(0:NH-1) !Output samples (delayed by one block)
|
||||
real x0s(0:NH-1) !Saved upper half of input samples
|
||||
real x1s(0:NH-1) !Saved upper half of output samples
|
||||
real xs(0:NH-1) !Saved upper half of input chunk convolved with h(t)
|
||||
real x(0:NFFT-1) !Work array
|
||||
real*4 w(0:NFFT-1) !Window function
|
||||
real*4 s(0:NH) !Average spectrum
|
||||
@ -19,6 +16,7 @@ subroutine refspectrum(id2,id2b,kk,bclear,brefspec,buseref,fname)
|
||||
real*8 xfit(1500),yfit(1500),sigmay(1500),a(5),chisqr !Polyfit arrays
|
||||
logical first
|
||||
complex cx(0:NH) !Complex frequency-domain work array
|
||||
complex cfil(0:NH)
|
||||
character*(*) fname
|
||||
common/spectra/syellow(6827),ref(0:NH),filter(0:NH)
|
||||
equivalence(x,cx)
|
||||
@ -34,8 +32,7 @@ subroutine refspectrum(id2,id2b,kk,bclear,brefspec,buseref,fname)
|
||||
nsave=0
|
||||
s=0.0
|
||||
filter=1.0
|
||||
x0s=0.
|
||||
x1s=0.
|
||||
xs=0.
|
||||
first=.false.
|
||||
endif
|
||||
if(bclear) s=0.
|
||||
@ -134,21 +131,27 @@ subroutine refspectrum(id2,id2b,kk,bclear,brefspec,buseref,fname)
|
||||
30 do i=1,NH
|
||||
read(16,1005,err=100,end=100) freq,s(i),ref(i),fil(i),filter(i)
|
||||
enddo
|
||||
! Make the filter causal for overlap and add.
|
||||
cx(0)=0.0
|
||||
cx(1:NH)=fil(1:NH)/NFFT
|
||||
call four2a(x,NFFT,1,1,-1)
|
||||
x=cshift(x,-400)
|
||||
x(800:NH)=0.0
|
||||
call four2a(cx,NFFT,1,-1,0)
|
||||
cfil=cx
|
||||
100 close(16)
|
||||
110 continue
|
||||
endif
|
||||
x0=id2(1:NH)
|
||||
x(0:NH-1)=x0s !Previous 2nd half to new 1st half
|
||||
x(NH:NFFT-1)=x0 !New 2nd half
|
||||
x0s=x0 !Save the new 2nd half
|
||||
x=w*x !Apply window
|
||||
call four2a(x,NFFT,1,-1,0) !r2c FFT (to frequency domain)
|
||||
cx=fil*cx
|
||||
call four2a(cx,NFFT,1,1,-1) !c2r FFT (back to time domain)
|
||||
x1=x1s + x(0:NH-1) !Add previous segment's 2nd half
|
||||
! id2(1:NH)=nint(x1)
|
||||
if(kk.ge.6912) id2b(kk-6192+1:kk-6192+NH)=nint(x1)
|
||||
x1s=x(NH:NFFT-1) !Save the new 2nd half
|
||||
! Use overlap and add method to apply causal reference filter.
|
||||
x(0:NH-1)=id2(1:NH)
|
||||
x(NH:NFFT-1)=0.0
|
||||
x=x/NFFT
|
||||
call four2a(x,NFFT,1,-1,0)
|
||||
cx=cfil*cx
|
||||
call four2a(cx,NFFT,1,1,-1)
|
||||
x(0:NH-1)=x(0:NH-1)+xs
|
||||
xs=x(NH:NFFT-1)
|
||||
id2(1:NH)=nint(x(0:NH-1))
|
||||
endif
|
||||
blastuse=buseref
|
||||
|
||||
|
76
lib/t3.f90
@ -1,76 +0,0 @@
|
||||
program t3
|
||||
|
||||
parameter (NBLK=3456,NZ=10*NBLK)
|
||||
real x0(NZ)
|
||||
real x1(NZ)
|
||||
|
||||
twopi=8.0*atan(1.0)
|
||||
dphi=twopi*1000.0/12000.0
|
||||
phi=0.
|
||||
do i=1,NZ
|
||||
phi=phi+dphi
|
||||
x0(i)=sin(phi)
|
||||
if(mod(i,10007).eq.100) x0(i)=2.0
|
||||
enddo
|
||||
|
||||
do j=1,10
|
||||
ib=j*NBLK
|
||||
ia=ib-NBLK+1
|
||||
call filter(x0(ia:ib),x1(ia:ib))
|
||||
enddo
|
||||
|
||||
x1(1:NZ-NBLK)=x1(NBLK+1:NZ)
|
||||
do i=1,NZ-NBLK
|
||||
write(13,1001) i,x0(i),x1(i),x1(i)-x0(i)
|
||||
1001 format(i6,3f13.9)
|
||||
enddo
|
||||
|
||||
end program t3
|
||||
|
||||
subroutine filter(x0,x1)
|
||||
|
||||
! Process time-domain data sequentially, optionally using a frequency-domain
|
||||
! filter to alter the spectrum.
|
||||
|
||||
! NB: uses a sin^2 window with 50% overlap.
|
||||
|
||||
parameter (NFFT=6912,NH=NFFT/2)
|
||||
real x0(0:NH-1) !Input samples
|
||||
real x1(0:NH-1) !Output samples (delayed by one block)
|
||||
real x0s(0:NH-1) !Saved upper half of input samples
|
||||
real x1s(0:NH-1) !Saved upper half of output samples
|
||||
real x(0:NFFT-1) !Work array
|
||||
real*4 w(0:NFFT-1) !Window function
|
||||
real f(0:NH) !Filter to be applied
|
||||
real*4 s(0:NH) !Average spectrum
|
||||
logical first
|
||||
complex cx(0:NH) !Complex frequency-domain work array
|
||||
equivalence (x,cx)
|
||||
data first/.true./
|
||||
save
|
||||
|
||||
if(first) then
|
||||
pi=4.0*atan(1.0)
|
||||
do i=0,NFFT-1
|
||||
ww=sin(i*pi/NFFT)
|
||||
w(i)=ww*ww/NFFT
|
||||
enddo
|
||||
s=0.0
|
||||
f=1.0
|
||||
x0s=0.
|
||||
x1s=0.
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
x(0:NH-1)=x0s !Previous 2nd half to new 1st half
|
||||
x(NH:NFFT-1)=x0 !New 2nd half
|
||||
x0s=x0 !Save the new 2nd half
|
||||
x=w*x !Apply window
|
||||
call four2a(x,NFFT,1,-1,0) !r2c FFT (to frequency domain)
|
||||
cx=f*cx
|
||||
call four2a(cx,NFFT,1,1,-1) !c2r FFT (back to time domain)
|
||||
x1=x1s + x(0:NH-1) !Add previous segment's 2nd half
|
||||
x1s=x(NH:NFFT-1) !Save the new 2nd half
|
||||
|
||||
return
|
||||
end subroutine filter
|
27
lib/to_contest_msg.f90
Normal file
@ -0,0 +1,27 @@
|
||||
subroutine to_contest_msg(msg0,msg)
|
||||
|
||||
! If the message has "R grid4" istead of "grid4", remove the "R "
|
||||
! and substitute the diametrically opposite grid.
|
||||
|
||||
character*6 g1,g2
|
||||
character*22 msg0,msg
|
||||
logical isgrid
|
||||
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'
|
||||
|
||||
i0=index(msg0,' R ') + 3 !Check for ' R ' in message
|
||||
g1=msg0(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=msg0(1:i0-3)//g2(1:4) !Send message with g2
|
||||
else
|
||||
msg=msg0
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine to_contest_msg
|
997
mainwindow.cpp
26
mainwindow.h
@ -156,16 +156,22 @@ private slots:
|
||||
void set_dateTimeQSO(int m_ntx);
|
||||
void set_ntx(int n);
|
||||
void on_txrb1_toggled(bool status);
|
||||
void on_txrb1_doubleClicked ();
|
||||
void on_txrb2_toggled(bool status);
|
||||
void on_txrb3_toggled(bool status);
|
||||
void on_txrb4_toggled(bool status);
|
||||
void on_txrb4_doubleClicked ();
|
||||
void on_txrb5_toggled(bool status);
|
||||
void on_txrb5_doubleClicked ();
|
||||
void on_txrb6_toggled(bool status);
|
||||
void on_txb1_clicked();
|
||||
void on_txb1_doubleClicked ();
|
||||
void on_txb2_clicked();
|
||||
void on_txb3_clicked();
|
||||
void on_txb4_clicked();
|
||||
void on_txb4_doubleClicked ();
|
||||
void on_txb5_clicked();
|
||||
void on_txb5_doubleClicked ();
|
||||
void on_txb6_clicked();
|
||||
void on_lookupButton_clicked();
|
||||
void on_addButton_clicked();
|
||||
@ -184,7 +190,6 @@ private slots:
|
||||
void on_actionQuickDecode_toggled (bool);
|
||||
void on_actionMediumDecode_toggled (bool);
|
||||
void on_actionDeepestDecode_toggled (bool);
|
||||
void on_inGain_valueChanged(int n);
|
||||
void bumpFqso(int n);
|
||||
void on_actionErase_ALL_TXT_triggered();
|
||||
void on_actionErase_wsjtx_log_adi_triggered();
|
||||
@ -239,7 +244,6 @@ private slots:
|
||||
void on_cbTx6_toggled(bool b);
|
||||
void on_cbMenus_toggled(bool b);
|
||||
void on_cbFirst_toggled(bool b);
|
||||
void on_cbWeak_toggled(bool b);
|
||||
void on_cbAutoSeq_toggled(bool b);
|
||||
void networkError (QString const&);
|
||||
void on_ClrAvgButton_clicked();
|
||||
@ -300,7 +304,7 @@ private:
|
||||
private:
|
||||
void astroUpdate ();
|
||||
void writeAllTxt(QString message);
|
||||
void FT8_AutoSeq(QString message);
|
||||
void auto_sequence (QString const& message, unsigned start_tolerance, unsigned stop_tolerance);
|
||||
void hideMenus(bool b);
|
||||
|
||||
NetworkAccessManager m_network_manager;
|
||||
@ -364,6 +368,7 @@ private:
|
||||
qint32 m_waterfallAvg;
|
||||
qint32 m_ntx;
|
||||
bool m_gen_message_is_cq;
|
||||
bool m_send_RR73;
|
||||
qint32 m_timeout;
|
||||
qint32 m_XIT;
|
||||
qint32 m_setftx;
|
||||
@ -447,6 +452,17 @@ private:
|
||||
bool m_bQRAsyncWarned;
|
||||
bool m_bDoubleClicked;
|
||||
bool m_bCallingCQ;
|
||||
bool m_bAutoReply;
|
||||
enum
|
||||
{
|
||||
CALLING,
|
||||
REPLYING,
|
||||
REPORT,
|
||||
ROGER_REPORT,
|
||||
ROGERS,
|
||||
SIGNOFF
|
||||
}
|
||||
m_QSOProgress;
|
||||
|
||||
int m_ihsym;
|
||||
int m_nzap;
|
||||
@ -558,7 +574,7 @@ private:
|
||||
void writeSettings();
|
||||
void createStatusBar();
|
||||
void updateStatusBar();
|
||||
void genStdMsgs(QString rpt);
|
||||
void genStdMsgs(QString rpt, bool unconditional = false);
|
||||
void genCQMsg();
|
||||
void clearDX ();
|
||||
void lookup();
|
||||
@ -574,7 +590,7 @@ private:
|
||||
void pskPost(DecodedText decodedtext);
|
||||
void displayDialFrequency ();
|
||||
void transmitDisplay (bool);
|
||||
void processMessage(QString const& messages, qint32 position, bool ctrl);
|
||||
void processMessage(QString const& messages, qint32 position, bool ctrl = false, bool alt = false);
|
||||
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
|
||||
void replayDecodes ();
|
||||
void postDecode (bool is_new, QString const& message);
|
||||
|
@ -761,16 +761,6 @@ QLabel[oob="true"] {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbWeak">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Call the weakest decoded responder to my CQ.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Weak</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbTx6">
|
||||
<property name="enabled">
|
||||
@ -838,7 +828,7 @@ QLabel[oob="true"] {
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbTxLock">
|
||||
<property name="toolTip">
|
||||
<string>Tx frequency tracks Rx frequency</string>
|
||||
<string><html><head/><body><p>Tx frequency tracks Rx frequency. </p><p>Not recommeded for general use!</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Lock Tx=Rx</string>
|
||||
@ -975,7 +965,7 @@ QLabel[oob="true"] {
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="txFirstCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Check to Tx in even minutes, uncheck for odd minutes</string>
|
||||
<string><html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tx even/1st</string>
|
||||
@ -1097,9 +1087,9 @@ QLabel[oob="true"] {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="QRadioButton" name="txrb1">
|
||||
<widget class="DoubleClickableRadioButton" name="txrb1">
|
||||
<property name="toolTip">
|
||||
<string>Send this message in next Tx interval</string>
|
||||
<string><html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -1113,7 +1103,7 @@ QLabel[oob="true"] {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="txb1">
|
||||
<widget class="DoubleClickablePushButton" name="txb1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
@ -1121,7 +1111,7 @@ QLabel[oob="true"] {
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Switch to this Tx message NOW</string>
|
||||
<string><html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station</p></body></html></string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
@ -1235,9 +1225,9 @@ QLabel[oob="true"] {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="QRadioButton" name="txrb4">
|
||||
<widget class="DoubleClickableRadioButton" name="txrb4">
|
||||
<property name="toolTip">
|
||||
<string>Send this message in next Tx interval</string>
|
||||
<string><html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4</p><p>RR73 messages should only be used when you are reasonably confident that no message repititions will be required</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -1251,7 +1241,7 @@ QLabel[oob="true"] {
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="txb4">
|
||||
<widget class="DoubleClickablePushButton" name="txb4">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
@ -1259,7 +1249,7 @@ QLabel[oob="true"] {
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Switch to this Tx message NOW</string>
|
||||
<string><html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4</p><p>RR73 messages should only be used when you are reasonably confident that no message repititions will be required</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tx &4</string>
|
||||
@ -1292,9 +1282,9 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="QRadioButton" name="txrb5">
|
||||
<widget class="DoubleClickableRadioButton" name="txrb5">
|
||||
<property name="toolTip">
|
||||
<string>Send this message in next Tx interval</string>
|
||||
<string><html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -1308,7 +1298,7 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="txb5">
|
||||
<widget class="DoubleClickablePushButton" name="txb5">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
@ -1316,7 +1306,7 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Switch to this Tx message NOW</string>
|
||||
<string><html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tx &5</string>
|
||||
@ -1935,28 +1925,6 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" rowspan="2">
|
||||
<widget class="QSlider" name="inGain">
|
||||
<property name="toolTip">
|
||||
<string>Digital gain for graph windows</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-50</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QWidget" name="DX_controls_widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
@ -2409,6 +2377,7 @@ QPushButton[state="ok"] {
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionInclude_averaging"/>
|
||||
<addaction name="actionInclude_correlation"/>
|
||||
<addaction name="actionEnable_AP"/>
|
||||
<addaction name="actionEnable_AP_DXcall"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuSave">
|
||||
@ -2943,9 +2912,6 @@ QPushButton[state="ok"] {
|
||||
<property name="text">
|
||||
<string>Enable AP for DX Call</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string/>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFreqCal">
|
||||
<property name="checkable">
|
||||
@ -3011,6 +2977,14 @@ QPushButton[state="ok"] {
|
||||
<string>FT8</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnable_AP">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable AP</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
@ -3040,6 +3014,16 @@ QPushButton[state="ok"] {
|
||||
<extends>QSpinBox</extends>
|
||||
<header>RestrictedSpinBox.hpp</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DoubleClickableRadioButton</class>
|
||||
<extends>QRadioButton</extends>
|
||||
<header>DoubleClickableRadioButton.hpp</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DoubleClickablePushButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>DoubleClickablePushButton.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>logQSOButton</tabstop>
|
||||
@ -3051,7 +3035,6 @@ QPushButton[state="ok"] {
|
||||
<tabstop>autoButton</tabstop>
|
||||
<tabstop>stopTxButton</tabstop>
|
||||
<tabstop>tuneButton</tabstop>
|
||||
<tabstop>inGain</tabstop>
|
||||
<tabstop>dxCallEntry</tabstop>
|
||||
<tabstop>dxGridEntry</tabstop>
|
||||
<tabstop>lookupButton</tabstop>
|
||||
|
@ -18,7 +18,10 @@
|
||||
locator to Dx Grid; change Rx and Tx frequencies to<br/>
|
||||
decoded signal's frequency; generate standard messages.<br/>
|
||||
If first callsign is your own, Tx frequency is not<br/>
|
||||
changed unless Ctrl is held down when double-clicking.
|
||||
changed unless Ctrl is held down when double-clicking.<br/>
|
||||
<br/>
|
||||
Hold down Alt to only move the Rx frequency when<br/>
|
||||
double-clicking to reply to a CQ or QRZ caller.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -361,7 +361,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
|
||||
float bw=9.0*12000.0/m_nsps; //JT9
|
||||
|
||||
if(m_mode=="FT8") bw=8*12000.0/1920.0; //FT8
|
||||
if(m_mode=="FT8") bw=7*12000.0/1920.0; //FT8
|
||||
|
||||
if(m_mode=="JT4") { //JT4
|
||||
bw=3*11025.0/2520.0; //Max tone spacing (3/4 of actual BW)
|
||||
|
@ -1,9 +1,9 @@
|
||||
<table cellspacing=1>
|
||||
<tr><td><b>F1 </b></td><td>Online User's Guide</td></tr>
|
||||
<tr><td><b>Ctrl+F1 </b></td><td>About WSJT-X</td></tr>
|
||||
<tr><td><b>F2 </b></td><td>Open configuration window</td></tr>
|
||||
<tr><td><b>F2 </b></td><td>Open settings window</td></tr>
|
||||
<tr><td><b>F3 </b></td><td>Display keyboard shortcuts</td></tr>
|
||||
<tr><td><b>F4 </b></td><td>Clear DX Call, DX Grid, Tx messages 1-5</td></tr>
|
||||
<tr><td><b>F4 </b></td><td>Clear DX Call, DX Grid, Tx messages 1-4</td></tr>
|
||||
<tr><td><b>Alt+F4 </b></td><td>Exit program</td></tr>
|
||||
<tr><td><b>F5 </b></td><td>Display special mouse commands</td></tr>
|
||||
<tr><td><b>F6 </b></td><td>Open next file in directory</td></tr>
|
||||
|
@ -360,7 +360,7 @@ void WideGraph::setRxBand (QString const& band)
|
||||
else
|
||||
{
|
||||
ui->fSplitSpinBox->setValue (m_fMinPerBand.value (band, 2500).toUInt ());
|
||||
ui->fSplitSpinBox->setEnabled (true);
|
||||
ui->fSplitSpinBox->setEnabled (m_mode=="JT9+JT65");
|
||||
}
|
||||
ui->widePlot->setRxBand(band);
|
||||
setRxRange ();
|
||||
|