Merge branch 'release-2.5.0'
| @ -26,7 +26,7 @@ if (WIN32) | ||||
|       add_custom_command ( | ||||
| 	OUTPUT ${outfile}.h ${outfile}.cpp | ||||
| 	COMMAND ${DUMPCPP_Executable} | ||||
| 	ARGS ${AX_SERVER_options} -o "${outfile}" "${infile}" | ||||
| 	ARGS ${ax_server_options} -o "${outfile}" "${infile}" | ||||
| 	MAIN_DEPENDENCY ${infile} VERBATIM) | ||||
|       list (APPEND ${outfiles} ${outfile}.cpp) | ||||
|     endforeach() | ||||
|  | ||||
| @ -71,7 +71,7 @@ message (STATUS "******************************************************") | ||||
| 
 | ||||
| include (set_build_type) | ||||
| # RC 0 or omitted is a development build, GA is a General Availability release build | ||||
| set_build_type (RC 3) | ||||
| set_build_type (RC 4) | ||||
| set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}") | ||||
| 
 | ||||
| # | ||||
|  | ||||
| @ -2735,6 +2735,7 @@ bool Configuration::impl::open_rig (bool force) | ||||
| 
 | ||||
|           ui_->test_CAT_push_button->setStyleSheet ({}); | ||||
|           rig_active_ = true; | ||||
|           LOG_TRACE ("emitting startup_transceiver"); | ||||
|           Q_EMIT start_transceiver (++transceiver_command_number_); // start rig on its thread
 | ||||
|           result = true; | ||||
|         } | ||||
| @ -2782,6 +2783,7 @@ void Configuration::impl::transceiver_frequency (Frequency f) | ||||
|   cached_rig_state_.frequency (apply_calibration (f + current_offset_)); | ||||
| 
 | ||||
|   // qDebug () << "Configuration::impl::transceiver_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f;
 | ||||
|   LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_); | ||||
|   Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); | ||||
| } | ||||
| 
 | ||||
| @ -2808,6 +2810,7 @@ void Configuration::impl::transceiver_tx_frequency (Frequency f) | ||||
|         } | ||||
| 
 | ||||
|       // qDebug () << "Configuration::impl::transceiver_tx_frequency: n:" << transceiver_command_number_ + 1 << "f:" << f;
 | ||||
|       LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_); | ||||
|       Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); | ||||
|     } | ||||
| } | ||||
| @ -2817,6 +2820,7 @@ void Configuration::impl::transceiver_mode (MODE m) | ||||
|   cached_rig_state_.online (true); // we want the rig online
 | ||||
|   cached_rig_state_.mode (m); | ||||
|   // qDebug () << "Configuration::impl::transceiver_mode: n:" << transceiver_command_number_ + 1 << "m:" << m;
 | ||||
|   LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_); | ||||
|   Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); | ||||
| } | ||||
| 
 | ||||
| @ -2826,6 +2830,7 @@ void Configuration::impl::transceiver_ptt (bool on) | ||||
|   set_cached_mode (); | ||||
|   cached_rig_state_.ptt (on); | ||||
|   // qDebug () << "Configuration::impl::transceiver_ptt: n:" << transceiver_command_number_ + 1 << "on:" << on;
 | ||||
|   LOG_TRACE ("emitting set_transceiver: requested state:" << cached_rig_state_); | ||||
|   Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_); | ||||
| } | ||||
| 
 | ||||
| @ -2909,6 +2914,7 @@ void Configuration::impl::close_rig () | ||||
|   if (rig_active_) | ||||
|     { | ||||
|       ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}"); | ||||
|       LOG_TRACE ("emitting stop_transceiver"); | ||||
|       Q_EMIT stop_transceiver (); | ||||
|       for (auto const& connection: rig_connections_) | ||||
|         { | ||||
|  | ||||
| @ -6,7 +6,7 @@ you change the name in the Applications folder from WSJT-X to WSJT-X_previous | ||||
| before proceeding.   | ||||
| 
 | ||||
| I recommend that you follow the installation instructions especially if you | ||||
| are moving from v2.2 to v2.3 or later, of WSJT-X or you have upgraded macOS. | ||||
| are moving from v2.3 to v2.4 or later, of WSJT-X or you have upgraded macOS. | ||||
| 
 | ||||
| Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. | ||||
| 
 | ||||
| @ -25,7 +25,7 @@ change has been made by typing: | ||||
| 
 | ||||
|       sysctl -a | grep sysv.shm | ||||
| 
 | ||||
| If shmmax is not shown as 52428800 then contact me since WSJT-X will fail to load with | ||||
| If shmmax is not shown as 52428800 then contact me since WSJT-X might fail to load with | ||||
| an error message: "Unable to create shared memory segment". | ||||
| 
 | ||||
| You can now close the Terminal window.  It will not be necessary to repeat this procedure  | ||||
| @ -72,7 +72,9 @@ Please email me if you have problems. | ||||
| 
 | ||||
| --- John G4KLA     (g4kla@rmnjmn.co.uk) | ||||
| 
 | ||||
| Addendum:  Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X. | ||||
| Additional Notes: | ||||
| 
 | ||||
| 1.  Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X | ||||
| 
 | ||||
| WSJT-X makes use of a block of memory which is shared between different parts of | ||||
| the code.  The normal allocation of shared memory on a Mac is insufficient and this  | ||||
| @ -87,7 +89,8 @@ simultaneously, the shmall parameter in the com.wsjtx.sysctl.plist file needs to | ||||
| The shmall parameter determines the amount of shared memory which is allocated in 4096 byte pages | ||||
| with 50MB (52428800) required for each instance.   The shmall parameter is calculated as:  | ||||
| (n * 52428800)/4096  where 'n' is the number of instances required to run simultaneously. | ||||
| Remember to reboot your Mac afterwards. | ||||
| Replace your new version of this file in /Library/LaunchDaemons and remember to reboot your | ||||
| Mac afterwards. | ||||
| 
 | ||||
| Note that the shmmax parameter remains unchanged.  This is the maximum amount of shared memory that | ||||
| any one instance is allowed to request from the total shared memory allocation and should not | ||||
| @ -97,3 +100,14 @@ If two instances of WSJT-X are running, it is likely that you might need additio | ||||
| audio devices, from two rigs for example.  Visit Audio MIDI Setup and create an Aggregate Device | ||||
| which will allow you to specify more than one interface.  I recommend you consult Apple's guide | ||||
| on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000. | ||||
| 
 | ||||
| 2.  Preventing WSJT-X from being put into 'sleep' mode (App Nap). | ||||
| 
 | ||||
| In normal circumstances an application which has not been directly accessed for a while can be  | ||||
| subject to App Nap which means it is suspended until such time as its windows are accessed.  If | ||||
| it is intended that WSJT-X should be submitting continued reports to, for example, PSK Reporter | ||||
| then reporting will be interrupted.  App Nap can be disabled as follows, but first quit WSJT-X: | ||||
| 
 | ||||
| Open a Terminal window and type:    defaults  write  org.k1jt.wsjtx  NSAppSleepDisable  -bool  YES | ||||
| If you type:   defaults  read  org.k1jt.wsjtx   then the response will be:  NSAppSleepDisable = 1; | ||||
| Close the Terminal window and launch WSJT-X.  (If you 'Hide' WSJT-X, this scheme will be suspended.) | ||||
|  | ||||
							
								
								
									
										20
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						| @ -12,6 +12,26 @@ | ||||
| Copyright 2001 - 2021 by Joe Taylor, K1JT. | ||||
| 
 | ||||
| 
 | ||||
| 	        Release: WSJT-X 2.5.0-rc4 | ||||
| 	               Aug 2, 2021 | ||||
| 	        ------------------------- | ||||
| 
 | ||||
| Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0.  Changes | ||||
| in the package since WSJT-X 2.5.0-rc3 include the following | ||||
| enhancements and defect repairs: | ||||
| 
 | ||||
| MAP65: | ||||
|  - Suppress display of duplicate decodes | ||||
|  - Increase the length of .tf2 & .iq files to 56 s | ||||
|  - Implements an early decoding pass at 52 s | ||||
|   | ||||
| WSJT-X: | ||||
|  - Repair a defect in CALL3.TXT lookups that incorrectly matched | ||||
|    partial calls | ||||
|  - Instructions in macOS ReadMe.txt to suppress App Nap energy saving | ||||
|  - Revised User Guide using FT8 mode for the basic tutorial | ||||
|  - Allow contest and FD operating in Q65 mode | ||||
| 
 | ||||
| 	        Release: WSJT-X 2.5.0-rc3 | ||||
| 	               Jul 5, 2021 | ||||
| 	        ------------------------- | ||||
|  | ||||
							
								
								
									
										26
									
								
								Radio.cpp
									
									
									
									
									
								
							
							
						
						| @ -42,6 +42,15 @@ namespace Radio | ||||
|         value = v.toDouble (); | ||||
|         if (ok) *ok = true; | ||||
|       } | ||||
|     if (ok && !*ok) | ||||
|       { | ||||
|         return value; | ||||
|       } | ||||
|     return frequency (value, scale, ok); | ||||
|   } | ||||
| 
 | ||||
|   Frequency frequency (double value, int scale, bool * ok) | ||||
|   { | ||||
|     value *= std::pow (10., scale); | ||||
|     if (ok) | ||||
|       { | ||||
| @ -50,6 +59,10 @@ namespace Radio | ||||
|             value = 0.; | ||||
|             *ok = false; | ||||
|           } | ||||
|         else | ||||
|           { | ||||
|             *ok = true; | ||||
|           } | ||||
|       } | ||||
|     return std::llround (value); | ||||
|   } | ||||
| @ -66,6 +79,15 @@ namespace Radio | ||||
|         value = v.toDouble (); | ||||
|         if (ok) *ok = true; | ||||
|       } | ||||
|     if (ok && !*ok) | ||||
|       { | ||||
|         return value; | ||||
|       } | ||||
|     return frequency_delta (value, scale, ok); | ||||
|   } | ||||
| 
 | ||||
|   FrequencyDelta frequency_delta (double value, int scale, bool * ok) | ||||
|   { | ||||
|     value *= std::pow (10., scale); | ||||
|     if (ok) | ||||
|       { | ||||
| @ -75,6 +97,10 @@ namespace Radio | ||||
|             value = 0.; | ||||
|             *ok = false; | ||||
|           } | ||||
|         else | ||||
|           { | ||||
|             *ok = true; | ||||
|           } | ||||
|       } | ||||
|     return std::llround (value); | ||||
|   } | ||||
|  | ||||
| @ -34,10 +34,12 @@ namespace Radio | ||||
|   //	QVariant argument is convertible to double and is assumed to
 | ||||
|   //	be scaled by (10 ** -scale).
 | ||||
|   //
 | ||||
|   Frequency UDP_EXPORT frequency (QVariant const&, int scale, | ||||
|   Frequency UDP_EXPORT frequency (QVariant const&, int scale = 0, | ||||
|                                   bool * ok = nullptr, QLocale const& = QLocale ()); | ||||
|   FrequencyDelta UDP_EXPORT frequency_delta (QVariant const&, int scale, | ||||
|   FrequencyDelta UDP_EXPORT frequency_delta (QVariant const&, int scale = 0, | ||||
|                                              bool * ok = nullptr, QLocale const& = QLocale ()); | ||||
|   Frequency UDP_EXPORT frequency (double, int scale = 0, bool * ok = nullptr); | ||||
|   FrequencyDelta UDP_EXPORT frequency_delta (double, int scale = 0, bool * ok = nullptr); | ||||
| 
 | ||||
|   //
 | ||||
|   // Frequency type formatting
 | ||||
|  | ||||
| @ -12,6 +12,27 @@ | ||||
| Copyright 2001 - 2021 by Joe Taylor, K1JT. | ||||
| 
 | ||||
| 
 | ||||
| 	        Release: WSJT-X 2.5.0-rc4 | ||||
| 	               Aug 2, 2021 | ||||
| 	        ------------------------- | ||||
| 
 | ||||
| Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0.  Changes | ||||
| in the package since WSJT-X 2.5.0-rc3 include the following | ||||
| enhancements and defect repairs: | ||||
| 
 | ||||
| MAP65: | ||||
|  - Suppress display of duplicate decodes | ||||
|  - Increase the length of .tf2 & .iq files to 56 s | ||||
|  - Implement an early decoding pass at 52 s | ||||
|  - Clean up the output written to map65_rx.log | ||||
|   | ||||
| WSJT-X: | ||||
|  - Repair a defect in CALL3.TXT lookups that incorrectly matched | ||||
|    partial calls | ||||
|  - Instructions in macOS ReadMe.txt to suppress App Nap energy saving | ||||
|  - Revised User Guide using FT8 mode for the basic tutorial | ||||
|  - Allow contest and FD operating in Q65 mode | ||||
| 
 | ||||
| 	        Release: WSJT-X 2.5.0-rc3 | ||||
| 	               Jul 5, 2021 | ||||
| 	        ------------------------- | ||||
|  | ||||
| @ -1128,7 +1128,7 @@ void HamlibTransceiver::do_poll () | ||||
|         { | ||||
|           m_->error_check (rig_get_freq (m_->rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency")); | ||||
|           f = std::round (f); | ||||
|           CAT_TRACE ("rig_get_freq frequency=" << f); | ||||
|           CAT_TRACE ("rig_get_freq frequency=" << Radio::frequency (f)); | ||||
|           update_rx_frequency (f); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -96,11 +96,11 @@ void OmniRigTransceiver::register_transceivers (logger_type *, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| OmniRigTransceiver::OmniRigTransceiver (logger_type * logger, | ||||
| OmniRigTransceiver::OmniRigTransceiver (logger_type * the_logger, | ||||
|                                         std::unique_ptr<TransceiverBase> wrapped, | ||||
|                                         RigNumber n, TransceiverFactory::PTTMethod ptt_type, | ||||
|                                         QString const& ptt_port, QObject * parent) | ||||
|   : TransceiverBase {logger, parent} | ||||
|   : TransceiverBase {the_logger, parent} | ||||
|   , wrapped_ {std::move (wrapped)} | ||||
|   , use_for_ptt_ {TransceiverFactory::PTT_method_CAT == ptt_type || ("CAT" == ptt_port && (TransceiverFactory::PTT_method_RTS == ptt_type || TransceiverFactory::PTT_method_DTR == ptt_type))} | ||||
|   , ptt_type_ {ptt_type} | ||||
| @ -111,26 +111,20 @@ OmniRigTransceiver::OmniRigTransceiver (logger_type * logger, | ||||
|   , reversed_ {false} | ||||
| { | ||||
|   CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread
 | ||||
|   CAT_TRACE ("constructed"); | ||||
| } | ||||
| 
 | ||||
| OmniRigTransceiver::~OmniRigTransceiver () | ||||
| { | ||||
|   CAT_TRACE ("destroying"); | ||||
|   CoUninitialize (); | ||||
| } | ||||
| 
 | ||||
| // returns false on time out
 | ||||
| bool OmniRigTransceiver::await_notification_with_timeout (int timeout) | ||||
| { | ||||
|   QEventLoop el; | ||||
|   connect (this, &OmniRigTransceiver::notified, &el, [&el] () {el.exit (1);}); | ||||
|   QTimer::singleShot (timeout, Qt::CoarseTimer, &el, [&el] () {el.exit (0);}); | ||||
|   return 1 == el.exec ();       // wait for notify or timer
 | ||||
| } | ||||
| 
 | ||||
| int OmniRigTransceiver::do_start () | ||||
| { | ||||
|   CAT_TRACE ("starting"); | ||||
| 
 | ||||
|   try | ||||
|     { | ||||
|       if (wrapped_) wrapped_->start (0); | ||||
| 
 | ||||
|       omni_rig_.reset (new OmniRig::OmniRigX {this}); | ||||
| @ -152,8 +146,10 @@ int OmniRigTransceiver::do_start () | ||||
|                , SIGNAL (CustomReply (int, QVariant const&, QVariant const&)) | ||||
|                , this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&))); | ||||
| 
 | ||||
|   CAT_INFO ("OmniRig s/w version: " << omni_rig_->SoftwareVersion () | ||||
|             << "i/f version: " << omni_rig_->InterfaceVersion ()); | ||||
|       CAT_INFO ("OmniRig s/w version: " << static_cast<quint16> (omni_rig_->SoftwareVersion () >> 16) | ||||
|                 << '.' << static_cast<quint16> (omni_rig_->SoftwareVersion () & 0xffff) | ||||
|                 << " i/f version: " << static_cast<int> (omni_rig_->InterfaceVersion () >> 8 & 0xff) | ||||
|                 << '.' << static_cast<int> (omni_rig_->InterfaceVersion () && 0xff)); | ||||
| 
 | ||||
|       // fetch the interface of the RigX CoClass and instantiate a proxy object
 | ||||
|       switch (rig_number_) | ||||
| @ -168,12 +164,26 @@ int OmniRigTransceiver::do_start () | ||||
|       // COM/OLE exceptions get signaled
 | ||||
|       connect (&*rig_, SIGNAL (exception (int, QString, QString, QString)), this, SLOT (handle_COM_exception (int, QString, QString, QString))); | ||||
| 
 | ||||
|   offline_timer_.reset (new QTimer); // instantiate here as
 | ||||
|                                      // constructor runs in wrong
 | ||||
|                                      // thread
 | ||||
|       offline_timer_.reset (new QTimer); // instantiate here as constructor runs in wrong thread
 | ||||
|       offline_timer_->setSingleShot (true); | ||||
|       connect (offline_timer_.data (), &QTimer::timeout, [this] () {offline ("Rig went offline");}); | ||||
| 
 | ||||
|       for (int i = 0; i < 5; ++i) | ||||
|         { | ||||
|           // leave some time for Omni-Rig to do its first poll
 | ||||
|           QThread::msleep (250); | ||||
|           if (OmniRig::ST_ONLINE == rig_->Status ()) | ||||
|             { | ||||
|               break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|       if (OmniRig::ST_ONLINE != rig_->Status ()) | ||||
|         { | ||||
|           CAT_ERROR ("rig not online"); | ||||
|           throw_qstring ("OmniRig: " + rig_->StatusStr ()); | ||||
|         } | ||||
| 
 | ||||
|       if (use_for_ptt_ && (TransceiverFactory::PTT_method_DTR == ptt_type_ || TransceiverFactory::PTT_method_RTS == ptt_type_)) | ||||
|         { | ||||
|           // fetch the interface for the serial port if we need it for PTT
 | ||||
| @ -213,27 +223,7 @@ int OmniRigTransceiver::do_start () | ||||
|          .arg (readable_params_, 8, 16, QChar ('0')) | ||||
|          .arg (writable_params_, 8, 16, QChar ('0')) | ||||
|          .arg (rig_number_)); | ||||
|   for (int i = 0; i < 5; ++i) | ||||
|     { | ||||
|       if (OmniRig::ST_ONLINE == rig_->Status ()) | ||||
|         { | ||||
|           break; | ||||
|         } | ||||
|       await_notification_with_timeout (1000); | ||||
|     } | ||||
|   if (OmniRig::ST_ONLINE != rig_->Status ()) | ||||
|     { | ||||
|       throw_qstring ("OmniRig: " + rig_->StatusStr ()); | ||||
|     } | ||||
|   QThread::msleep (500);        // leave some time for Omni-Rig to get
 | ||||
|                                 // the rig status for the 1st. time
 | ||||
|   auto f = rig_->GetRxFrequency (); | ||||
|   for (int i = 0; (f == 0) && (i < 5); ++i) | ||||
|     { | ||||
|       await_notification_with_timeout (1000); | ||||
|       f = rig_->GetRxFrequency (); | ||||
|     } | ||||
|   update_rx_frequency (f); | ||||
|       update_rx_frequency (rig_->GetRxFrequency ()); | ||||
|       int resolution {0}; | ||||
|       if (OmniRig::PM_UNKNOWN == rig_->Vfo () | ||||
|           && (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB)) | ||||
| @ -243,7 +233,7 @@ int OmniRigTransceiver::do_start () | ||||
|           // can't query VFO but can set explicitly
 | ||||
|           rig_->SetVfo (OmniRig::PM_VFOA); | ||||
|         } | ||||
|   f = state ().frequency (); | ||||
|       auto f = state ().frequency (); | ||||
|       if (f % 10) return resolution; // 1Hz resolution
 | ||||
|       auto test_frequency = f - f % 100 + 55; | ||||
|       if (OmniRig::PM_FREQ & writable_params_) | ||||
| @ -262,11 +252,6 @@ int OmniRigTransceiver::do_start () | ||||
|         { | ||||
|           throw_qstring (tr ("OmniRig: don't know how to set rig frequency")); | ||||
|         } | ||||
|   if (!await_notification_with_timeout (1000)) | ||||
|     { | ||||
|       CAT_ERROR ("do_start 1: wait timed out"); | ||||
|       throw_qstring (tr ("OmniRig: timeout waiting for update from rig")); | ||||
|     } | ||||
|       switch (rig_->GetRxFrequency () - test_frequency) | ||||
|         { | ||||
|         case -5: resolution = -1; break;  // 10Hz truncated
 | ||||
| @ -290,11 +275,6 @@ int OmniRigTransceiver::do_start () | ||||
|             { | ||||
|               rig_->SetFreqA (test_frequency); | ||||
|             } | ||||
|       if (!await_notification_with_timeout (2000)) | ||||
|         { | ||||
|           CAT_ERROR ("do_start 2: wait timed out"); | ||||
|           throw_qstring (tr ("OmniRig: timeout waiting for update from rig")); | ||||
|         } | ||||
|           if (9 == rig_->GetRxFrequency () - test_frequency) | ||||
|             { | ||||
|               resolution = 2;   // 20Hz rounded
 | ||||
| @ -313,11 +293,20 @@ int OmniRigTransceiver::do_start () | ||||
|           rig_->SetFreqA (f); | ||||
|         } | ||||
|       update_rx_frequency (f); | ||||
|       CAT_TRACE ("started"); | ||||
| 
 | ||||
|       return resolution; | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("start threw exception"); | ||||
|       throw; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void OmniRigTransceiver::do_stop () | ||||
| { | ||||
|   CAT_TRACE ("stopping"); | ||||
|   QThread::msleep (200);        // leave some time for pending
 | ||||
|                                 // commands at the server end
 | ||||
| 
 | ||||
| @ -337,6 +326,7 @@ void OmniRigTransceiver::do_stop () | ||||
|         { | ||||
|           rig_->clear (); | ||||
|           rig_.reset (); | ||||
|           CAT_TRACE ("rig_ reset"); | ||||
|         } | ||||
|       omni_rig_->clear (); | ||||
|       omni_rig_.reset (); | ||||
| @ -396,7 +386,6 @@ void OmniRigTransceiver::handle_status_change (int rig_number) | ||||
|       else | ||||
|         { | ||||
|           offline_timer_->stop (); // good to go again
 | ||||
|           Q_EMIT notified (); | ||||
|         } | ||||
|       // else
 | ||||
|       //   {
 | ||||
| @ -467,7 +456,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) | ||||
| 
 | ||||
|       if (params & OmniRig::PM_FREQ) | ||||
|         { | ||||
|           CAT_TRACE ("FREQ"); | ||||
|           need_frequency = true; | ||||
|         } | ||||
|       if (params & OmniRig::PM_FREQA) | ||||
| @ -653,7 +641,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) | ||||
|         } | ||||
|       CAT_TRACE ("OmniRig params change: state after:" << state ()); | ||||
|     } | ||||
|   Q_EMIT notified (); | ||||
| } | ||||
| 
 | ||||
| void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply) | ||||
| @ -710,7 +697,7 @@ void OmniRigTransceiver::do_ptt (bool on) | ||||
| 
 | ||||
| void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/) | ||||
| { | ||||
|   CAT_TRACE (f << state ()); | ||||
|   CAT_TRACE (f << ' ' << state ()); | ||||
|   if (!rig_ || rig_->isNull ()) return; | ||||
|   if (UNK != m) | ||||
|     { | ||||
| @ -739,7 +726,7 @@ void OmniRigTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/) | ||||
| 
 | ||||
| void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore*/) | ||||
| { | ||||
|   CAT_TRACE (tx << state ()); | ||||
|   CAT_TRACE (tx << ' ' << state ()); | ||||
|   if (!rig_ || rig_->isNull ()) return; | ||||
|   bool split {tx != 0}; | ||||
|   if (split) | ||||
| @ -804,7 +791,7 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, MODE m, bool /*no_ignore | ||||
| 
 | ||||
| void OmniRigTransceiver::do_mode (MODE mode) | ||||
| { | ||||
|   CAT_TRACE (mode << state ()); | ||||
|   CAT_TRACE (mode << ' ' << state ()); | ||||
|   if (!rig_ || rig_->isNull ()) return; | ||||
|   // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode
 | ||||
|   auto mapped = map_mode (mode); | ||||
|  | ||||
| @ -44,9 +44,6 @@ public: | ||||
|   void do_ptt (bool on) override; | ||||
| 
 | ||||
| private: | ||||
|   bool await_notification_with_timeout (int timeout); | ||||
|   Q_SIGNAL void notified () const; | ||||
|   // Q_SLOT void timeout_check ();
 | ||||
|   Q_SLOT void handle_COM_exception (int,  QString, QString, QString); | ||||
|   Q_SLOT void handle_visible_change (); | ||||
|   Q_SLOT void handle_rig_type_change (int rig_number); | ||||
|  | ||||
| @ -23,6 +23,12 @@ QDebug operator << (QDebug d, Transceiver::TransceiverState const& s) | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| std::ostream& operator << (std::ostream& os, Transceiver::MODE m) | ||||
| { | ||||
|   auto const& mo = Transceiver::staticMetaObject;                             \ | ||||
|   return os << mo.enumerator (mo.indexOfEnumerator ("MODE")).valueToKey (static_cast<int> (m)); \ | ||||
| } | ||||
| 
 | ||||
| std::ostream& operator << (std::ostream& os, Transceiver::TransceiverState const& s) | ||||
| { | ||||
|   return os | ||||
|  | ||||
| @ -169,6 +169,7 @@ Q_DECLARE_METATYPE (Transceiver::TransceiverState); | ||||
| QDebug operator << (QDebug, Transceiver::TransceiverState const&); | ||||
| #endif | ||||
| 
 | ||||
| std::ostream& operator << (std::ostream&, Transceiver::MODE); | ||||
| std::ostream& operator << (std::ostream&, Transceiver::TransceiverState const&); | ||||
| 
 | ||||
| ENUM_QDATASTREAM_OPS_DECL (Transceiver, MODE); | ||||
|  | ||||
| @ -16,6 +16,8 @@ namespace | ||||
| 
 | ||||
| void TransceiverBase::start (unsigned sequence_number) noexcept | ||||
| { | ||||
|   CAT_TRACE ("#: " << sequence_number); | ||||
| 
 | ||||
|   QString message; | ||||
|   try | ||||
|     { | ||||
| @ -26,10 +28,12 @@ void TransceiverBase::start (unsigned sequence_number) noexcept | ||||
|     } | ||||
|   catch (std::exception const& e) | ||||
|     { | ||||
|       CAT_TRACE ("#: " << sequence_number << " what: " << e.what ()); | ||||
|       message = e.what (); | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("#: " << sequence_number); | ||||
|       message = unexpected; | ||||
|     } | ||||
|   if (!message.isEmpty ()) | ||||
| @ -41,7 +45,7 @@ void TransceiverBase::start (unsigned sequence_number) noexcept | ||||
| void TransceiverBase::set (TransceiverState const& s, | ||||
|                            unsigned sequence_number) noexcept | ||||
| { | ||||
|   CAT_TRACE ("#: " << sequence_number << " " << s); | ||||
|   CAT_TRACE ("#: " << s); | ||||
| 
 | ||||
|   QString message; | ||||
|   try | ||||
| @ -119,10 +123,12 @@ void TransceiverBase::set (TransceiverState const& s, | ||||
|     } | ||||
|   catch (std::exception const& e) | ||||
|     { | ||||
|       CAT_TRACE ("#: " << sequence_number << " what: " << e.what ()); | ||||
|       message = e.what (); | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("#: " << sequence_number << " " << sequence_number); | ||||
|       message = unexpected; | ||||
|     } | ||||
|   if (!message.isEmpty ()) | ||||
| @ -133,6 +139,7 @@ void TransceiverBase::set (TransceiverState const& s, | ||||
| 
 | ||||
| void TransceiverBase::startup () | ||||
| { | ||||
|   CAT_TRACE ("startup"); | ||||
|   QString message; | ||||
|   try | ||||
|     { | ||||
| @ -144,10 +151,12 @@ void TransceiverBase::startup () | ||||
|     } | ||||
|   catch (std::exception const& e) | ||||
|     { | ||||
|       CAT_TRACE ("startup" << " what: " << e.what ()); | ||||
|       message = e.what (); | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("startup"); | ||||
|       message = unexpected; | ||||
|     } | ||||
|   if (!message.isEmpty ()) | ||||
| @ -158,6 +167,7 @@ void TransceiverBase::startup () | ||||
| 
 | ||||
| void TransceiverBase::shutdown () | ||||
| { | ||||
|   CAT_TRACE ("shutdown"); | ||||
|   may_update u {this}; | ||||
|   if (requested_.online ()) | ||||
|     { | ||||
| @ -177,6 +187,7 @@ void TransceiverBase::shutdown () | ||||
|         } | ||||
|       catch (...) | ||||
|         { | ||||
|           CAT_TRACE ("shutdown"); | ||||
|           // don't care about exceptions
 | ||||
|         } | ||||
|     } | ||||
| @ -186,6 +197,7 @@ void TransceiverBase::shutdown () | ||||
| 
 | ||||
| void TransceiverBase::stop () noexcept | ||||
| { | ||||
|   CAT_TRACE ("stop"); | ||||
|   QString message; | ||||
|   try | ||||
|     { | ||||
| @ -193,10 +205,12 @@ void TransceiverBase::stop () noexcept | ||||
|     } | ||||
|   catch (std::exception const& e) | ||||
|     { | ||||
|       CAT_TRACE ("stop" << " what: " << e.what ()); | ||||
|       message = e.what (); | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("stop"); | ||||
|       message = unexpected; | ||||
|     } | ||||
|   if (!message.isEmpty ()) | ||||
| @ -211,6 +225,7 @@ void TransceiverBase::stop () noexcept | ||||
| 
 | ||||
| void TransceiverBase::update_rx_frequency (Frequency rx) | ||||
| { | ||||
|   CAT_TRACE ("frequency: " << rx); | ||||
|   if (rx) | ||||
|     { | ||||
|       actual_.frequency (rx); | ||||
| @ -220,28 +235,35 @@ void TransceiverBase::update_rx_frequency (Frequency rx) | ||||
| 
 | ||||
| void TransceiverBase::update_other_frequency (Frequency tx) | ||||
| { | ||||
|   CAT_TRACE ("frequency: " << tx); | ||||
|   actual_.tx_frequency (tx); | ||||
| } | ||||
| 
 | ||||
| void TransceiverBase::update_split (bool state) | ||||
| { | ||||
|   CAT_TRACE ("state: " << state); | ||||
|   actual_.split (state); | ||||
| } | ||||
| 
 | ||||
| void TransceiverBase::update_mode (MODE m) | ||||
| { | ||||
|   CAT_TRACE ("mode: " << m); | ||||
|   actual_.mode (m); | ||||
|   requested_.mode (m);    // track rig changes
 | ||||
| } | ||||
| 
 | ||||
| void TransceiverBase::update_PTT (bool state) | ||||
| { | ||||
|   CAT_TRACE ("state: " << state); | ||||
|   actual_.ptt (state); | ||||
| } | ||||
| 
 | ||||
| void TransceiverBase::update_complete (bool force_signal) | ||||
| { | ||||
|   if ((do_pre_update () && actual_ != last_) || force_signal) | ||||
|   CAT_TRACE ("force signal: " << force_signal); | ||||
|   if ((do_pre_update () | ||||
|        && actual_ != last_) | ||||
|       || force_signal) | ||||
|     { | ||||
|       Q_EMIT update (actual_, last_sequence_number_); | ||||
|       last_ = actual_; | ||||
| @ -250,6 +272,7 @@ void TransceiverBase::update_complete (bool force_signal) | ||||
| 
 | ||||
| void TransceiverBase::offline (QString const& reason) | ||||
| { | ||||
|   CAT_TRACE ("reason: " << reason); | ||||
|   Q_EMIT failure (reason); | ||||
|   try | ||||
|     { | ||||
| @ -257,6 +280,7 @@ void TransceiverBase::offline (QString const& reason) | ||||
|     } | ||||
|   catch (...) | ||||
|     { | ||||
|       CAT_TRACE ("reason: " << reason); | ||||
|       // don't care
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,6 @@ JT4        11101000000011000011000000000000000000 | ||||
| JT4/VHF    11111001001011011011110000000000000000 | ||||
| JT9        11101000000011100001000000000000100000 | ||||
| JT9/VHF    11111010100011111001000000000000000000 | ||||
| JT9+JT65   11101000000111100001000000000000100000 | ||||
| JT65       11101000000011100001000000000000100000 | ||||
| JT65/VHF   11111001000011011010110001000000000000 | ||||
| Q65        11111101011011010011100000010000000011 | ||||
|  | ||||
| @ -49,12 +49,11 @@ set (UG_SRCS | ||||
|   system-requirements.adoc | ||||
|   transceiver-setup.adoc | ||||
|   tutorial-example1.adoc | ||||
|   tutorial-example2.adoc | ||||
|   tutorial-example3.adoc | ||||
|   tutorial-example4.adoc | ||||
|   tutorial-example5.adoc | ||||
|   tutorial-example6.adoc | ||||
|   tutorial-main-window.adoc | ||||
|   tutorial-download-samples.adoc | ||||
|   tutorial-wide-graph-settings.adoc | ||||
|   utilities.adoc | ||||
|   vhf-features.adoc | ||||
| @ -63,7 +62,6 @@ set (UG_SRCS | ||||
|   ) | ||||
| 
 | ||||
| set (UG_IMGS | ||||
|   images/130610_2343-wav-80.png | ||||
|   images/AstroData_2.png | ||||
|   images/Astronomical_data.png | ||||
|   images/auto-seq.png | ||||
| @ -72,7 +70,6 @@ set (UG_IMGS | ||||
|   images/colors.png | ||||
|   images/config-menu.png | ||||
|   images/decode-menu.png | ||||
|   images/decodes.png | ||||
|   images/download_samples.png | ||||
|   images/echo_144.png | ||||
|   images/EME_Deep_0.png | ||||
|  | ||||
| @ -1,11 +1,9 @@ | ||||
| // Status=edited | ||||
| 
 | ||||
| The following controls appear at the bottom of the Wide Graph window. | ||||
| Decoding occurs only in the displayed frequency range; otherwise, with | ||||
| the exceptions of *Start NNN Hz* and of *JT65 nnnn JT9* when operating | ||||
| in JT9+JT65 mode, controls on the Wide Graph window have no effect on | ||||
| the decoding process. | ||||
| 
 | ||||
| Decoding occurs only in the displayed frequency range; otherwise, | ||||
| controls on the Wide Graph window have no effect on the decoding | ||||
| process. | ||||
| image::wide-graph-controls.png[align="center",alt="Wide Graph Controls"] | ||||
| 
 | ||||
| - *Bins/Pixel* controls the displayed frequency resolution.  Set this | ||||
| @ -13,11 +11,6 @@ value to 1 for the highest possible resolution, or to higher numbers | ||||
| to compress the spectral display. Normal operation with a convenient | ||||
| window size works well at 2 to 8 bins per pixel. | ||||
| 
 | ||||
| - *JT65 nnnn JT9* sets the dividing point (blue marker) for wide-band | ||||
| decoding of JT65 and JT9 signals in *JT9+JT65* mode.  The decoder | ||||
| looks for JT65 signals everywhere, but JT9 signals only above this | ||||
| frequency. This setting is stored separately for each band. | ||||
| 
 | ||||
| - *Start nnn Hz* sets the low-frequency starting point of the | ||||
| waterfall frequency scale. | ||||
| 
 | ||||
|  | ||||
| Before Width: | Height: | Size: 52 KiB | 
| Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 133 KiB | 
| Before Width: | Height: | Size: 23 KiB | 
| Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 112 KiB | 
| Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 171 KiB | 
| @ -1,5 +1,13 @@ | ||||
| === Documentation Conventions | ||||
| 
 | ||||
| We include screen shots that illustrate many of the settings and | ||||
| features of _WSJT-X_.  Keep in mind that _WSJT-X_ is a multi-platform | ||||
| application: the detailed appearance of windows and user controls may | ||||
| be significantly different in Windows, Linux, or macOS environments. | ||||
| The underlying functionality is the same on all operating systems, | ||||
| however.  Where desirable we call special attention to important | ||||
| platform differences. | ||||
| 
 | ||||
| In this manual the following icons call attention to particular types | ||||
| of information: | ||||
| 
 | ||||
|  | ||||
| @ -39,7 +39,7 @@ image::RadioTab.png[align="center",alt="Radio Tab"] | ||||
| + | ||||
| 
 | ||||
| NOTE: A special value of *USB* is available for custom USB devices | ||||
|       like those used by some SDR kits. This is not the same a virtual | ||||
|       like those used by some SDR kits. This is not the same as the virtual | ||||
|       serial port provided by USB connected transceivers and CAT | ||||
|       interfaces, for those use the COM or serial port name that | ||||
|       refers to them. | ||||
|  | ||||
							
								
								
									
										16
									
								
								doc/user_guide/en/tutorial-download-samples.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,16 @@ | ||||
| // Status=review | ||||
| 
 | ||||
| [[DOWNLOAD_SAMPLES]] | ||||
| === Download Samples | ||||
| 
 | ||||
| The following steps will download sample audio Wave files that were originally recorded | ||||
| by WSJT-X. These files can be read in and processed by WSJT-X to simulate realtime  | ||||
| operation.  | ||||
|   | ||||
| - Select *Download samples...* from the *Help* menu. | ||||
| 
 | ||||
| - Download some or all of the available sample files using checkboxes | ||||
| on the screen shown below.  For this tutorial you will need at least | ||||
| the FT8 files. | ||||
| 
 | ||||
| image::download_samples.png[width=400,align="center",alt="Download Samples"] | ||||
| @ -1,121 +0,0 @@ | ||||
| // Status=review | ||||
| .Main Window: | ||||
| - Select *JT9+JT65* on the *Mode* menu. | ||||
| - Toggle the *Tx mode* button to read *Tx JT65 #*, and set the Tx and Rx | ||||
| frequencies to 1718 Hz. | ||||
| - Double-click on *Erase* to clear both text windows. | ||||
| 
 | ||||
| .Wide Graph Settings: | ||||
| 
 | ||||
| - *Bins/Pixel* = 7 | ||||
| - *JT65 .... JT9* = 2500 | ||||
| - Adjust the width of the Wide Graph window so that the upper | ||||
| frequency limit is approximately 4000 Hz. | ||||
| 
 | ||||
| .Open a Wave File: | ||||
| 
 | ||||
| - Select *File | Open* and navigate to +...\save\samples\JT9+JT65\130610_2343.wav+.   | ||||
| The waterfall should look something like this: | ||||
| 
 | ||||
| //.130610_2343.wav Decode | ||||
| [[X14]] | ||||
| image::130610_2343-wav-80.png[align="left",alt="Wide Graph Decode 130610_2343"] | ||||
| 
 | ||||
| The position of the blue marker on the waterfall scale is | ||||
| set by the spinner control *JT65 nnnn JT9*, where nnnn is an audio | ||||
| frequency in Hz. In *JT9+JT65* mode the program will automatically | ||||
| decode JT9 signals only above this frequency. JT65 signals will be | ||||
| decoded over the full displayed frequency range. | ||||
| 
 | ||||
| JT9 signals appear in the *Cumulative* spectrum as nearly rectangular | ||||
| shapes about 16 Hz wide.  They have no clearly visible sync tone like | ||||
| the one at the low-frequency edge of all JT65 signals.  By convention | ||||
| the nominal frequency of both JT9 and JT65 signals is taken to be that | ||||
| of the lowest tone, at the left edge of its spectrum. | ||||
| 
 | ||||
| This sample file contains 17 decodable signals — nine in JT65 mode | ||||
| (flagged with the character # in the decoded text windows), and eight | ||||
| in JT9 mode (flagged with @).  On multi-core computers the decoders | ||||
| for JT9 and JT65 modes run simultaneously, so their results will be | ||||
| interspersed.  The *Band Activity* window contains all decodes (you | ||||
| might need to scroll back in the window to see some of them).  A | ||||
| signal at the frequency specified by the green marker is given | ||||
| decoding priority, and its message is displayed also in the *Rx | ||||
| Frequency* window. | ||||
| 
 | ||||
| [[FigDecodes]] | ||||
| image::decodes.png[align="center"] | ||||
| 
 | ||||
| - Confirm that mouse-click behavior is similar to that described | ||||
| earlier, in <<TUT_EX1,Example 1>>.  _WSJT-X_ automatically determines | ||||
| the mode of each JT9 or JT65 message. | ||||
| 
 | ||||
| + | ||||
| 
 | ||||
| TIP: When you double-click on a signal in the waterfall it will be | ||||
| properly decoded even if on the "`wrong`" side of the *JT65 nnnn JT9* | ||||
| marker.  The Tx mode automatically switches to that of the decoded | ||||
| signal and the Rx and Tx frequency markers on the waterfall scale | ||||
| resize themselves accordingly. When selecting a JT65 signal, click on | ||||
| the sync tone at its left edge. | ||||
| 
 | ||||
| - Double-click on the waterfall near 815 Hz: a JT65 message | ||||
| originating from W7VP will be decoded and appear in the *Rx Frequency* | ||||
| window.  Between the *UTC* and *Freq* columns on the decoded text line | ||||
| you will find *dB*, the measured signal-to-noise ratio, and *DT*, the | ||||
| signal's time offset in seconds relative to your computer clock. | ||||
| 
 | ||||
| [width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"] | ||||
| |=== | ||||
| |UTC|dB|DT|Freq|Mode|Message | ||||
| |+2343+|+-7+|+0.3+|+815+|+#+|+KK4DSD W7VP -16+ | ||||
| |=== | ||||
| 
 | ||||
| - Double-click on the waterfall at 3196 Hz.  The program will decode a | ||||
| JT9 message from IZ0MIT: | ||||
| 
 | ||||
| [width="80%",align="center",cols="^10,2*^8,2*^10,54",options="header"] | ||||
| |=== | ||||
| |UTC|dB|DT|Freq|Mode|Message | ||||
| |+2343+|+-8+|+0.3+|+3196+|+@+|+WB8QPG IZ0MIT -11+ | ||||
| |=== | ||||
| 
 | ||||
| - Scroll back in the *Band Activity* window and double-click on the | ||||
| message `CQ DL7ACA JO40`. The program will set *Tx mode* to JT65 and | ||||
| the Rx frequency to that of DL7ACA, 975 Hz.  If you hold down the | ||||
| *Ctrl* key, both Rx and Tx frequencies will be moved.  If you had | ||||
| checked *Double-click on call sets Tx Enable* on the *Setup* menu, the | ||||
| program would configure itself to begin a transmission and start a QSO | ||||
| with DL7ACA. | ||||
| 
 | ||||
| - Hold *Ctrl* down and double-click on the decoded JT65 message `CQ | ||||
| TA4A KM37`.  The program will set Tx mode to JT9 and the Rx and Tx | ||||
| frequencies to 3567 Hz.  The program is now configured properly for a | ||||
| JT9 QSO with TA4A. | ||||
| 
 | ||||
| .Reopen the First Sample File: | ||||
| - Select *File | Open* and navigate to `...\save\samples\130418_1742.wav`. | ||||
| 
 | ||||
| Taking full advantage of the wide-band, dual-mode capability of | ||||
| _WSJT-X_ requires a receiver bandwidth of at least 4 kHz.  These | ||||
| data were recorded with a much narrower Rx bandwidth, roughly 200 to | ||||
| 2400 Hz. If you have no Rx filter wider than about 2.7 kHz, you will | ||||
| be using data like this. For best viewing, adjust *Bins/Pixel* and the | ||||
| width of the Wide Graph so that only the active part of the spectrum | ||||
| shows, say 200 to 2400 Hz.  Re-open the example file after any change of | ||||
| *Bins/Pixel* or Wide Graph width, to refresh the waterfall. | ||||
| 
 | ||||
| The signals in this file are all JT9 signals.  To decode them | ||||
| automatically in *JT9+JT65* mode you’ll need to move the *JT65 nnnn JT9* | ||||
| delimiter down to 1000 Hz or less. | ||||
| 
 | ||||
| .Waterfall Controls | ||||
| 
 | ||||
| Now is a good time to experiment with the *Start* control and the | ||||
| sliders controlling gain and zero-point of the waterfall and spectrum | ||||
| plots.  *Start* determines the frequency displayed at the left side of | ||||
| the waterfall scale.  Sliders set the baseline level and gain for the | ||||
| waterfall and the several types of spectra.  Good starting values | ||||
| should be close to mid-scale.  You might want to uncheck *Flatten* | ||||
| when adjusting the sliders.  Re-open the wave file after each change, | ||||
| to see the new results. | ||||
| @ -1,27 +1,92 @@ | ||||
| // Status=review | ||||
| .Main Window: | ||||
| - Select *FT8* on the *Mode* menu. | ||||
| - Click the *Stop* button on the main window to halt any data acquisition.   | ||||
| - Select *FT8* from the *Mode* menu and *Deep* from the *Decode* menu. | ||||
| - Double-click on *Erase* to clear both text windows. | ||||
| 
 | ||||
| .Wide Graph Settings: | ||||
| 
 | ||||
| - *Bins/Pixel* = 5, *Start* = 100 Hz, *N Avg* = 2 | ||||
| - Adjust the width of the Wide Graph window so that the upper | ||||
| frequency limit is approximately 3300 Hz. | ||||
| 
 | ||||
| .Open a Wave File: | ||||
| 
 | ||||
| - Select *File | Open* and navigate to | ||||
| +...\save\samples\FT8\181201_180245.wav+.  The waterfall and Band | ||||
| Activity window should look something like the following screen shots. | ||||
| (This recording was made during the "FT8 Roundup" contest, so most | ||||
| transmissions happen to be using *RTTY Roundup* message formats.) | ||||
| - Select *File | Open log directory* and navigate to | ||||
| +...\save\samples\FT8\210703_133430.wav+.  The waterfall and Band | ||||
| Activity/Rx Frequency windows should look something like the following screen shots: | ||||
| 
 | ||||
| - You may want to pretend you are K1JT | ||||
| by entering that callsign temporarily as *My Call* on the  | ||||
| *Settings | General* tab.  Your results should then be identical to | ||||
| those shown in the screen shot below. Don't forget to change *My Call* | ||||
| back to your own call when you are done! | ||||
| 
 | ||||
| [[X15]] | ||||
| image::FT8_waterfall.png[align="left",alt="Wide Graph Decode 170709_135615"] | ||||
| image::FT8_waterfall.png[align="left",alt="Wide Graph Decode 210703_133430"] | ||||
| 
 | ||||
| image::ft8_decodes.png[align="left"] | ||||
| 
 | ||||
| 
 | ||||
| .Decoding Overview | ||||
| 
 | ||||
| Decoding takes place at the end of a receive sequence. With *Decode* set | ||||
| to *Deep*, three decoding passes will be done and the *Decode* button on the  | ||||
| mainwindow will illuminate three times, once for each pass.  | ||||
| The first decoding attempt in each decoding pass is done at the selected Rx frequency, | ||||
| indicated by the U-shaped green marker on the waterfall frequency | ||||
| scale. All decodes appear in the left (*Band Activity*) window. The right | ||||
| (*Rx Frequency*) text window displays any decodes obtained at the current | ||||
| Rx frequency along with any decodes addressed to *My Call* (K1JT in this case). | ||||
| The red marker on the waterfall scale indicates your | ||||
| Tx frequency. | ||||
| 
 | ||||
| Twenty one FT8 signals are decoded from the example file. The number | ||||
| of decodes is shown in a box at the bottom of the main window. | ||||
| When this file was recorded HA5WA was finishing a QSO with K1JT, and | ||||
| his 73 message is shown in red because it is addressed to *My Call* (in this case K1JT).  | ||||
| By default, lines containing `CQ` | ||||
| are highlighted in green, and lines with *My Call* (K1JT) | ||||
| in red. Notice that K1JT has two callers; HA0DU and EA3AGB.   | ||||
| 
 | ||||
| [[X13]] | ||||
| .Decoding Controls | ||||
| 
 | ||||
| To gain some feeling for controls frequently used when making QSOs, | ||||
| try double-clicking with the mouse on the decoded text lines and on the | ||||
| waterfall spectral display. You should be able to confirm the | ||||
| following behavior: | ||||
| 
 | ||||
| - Double-click on one of the decoded *CQ* messages highlighted in | ||||
| green. These actions produce the following results: | ||||
| 
 | ||||
| ** Callsign and locator of the station calling CQ are copied to the *DX | ||||
| Call* and *DX Grid* entry fields.  | ||||
| 
 | ||||
| ** Messages are generated for a standard minimal QSO. | ||||
| 
 | ||||
| ** The *Tx even* box is checked or cleared appropriately, so that you | ||||
| will transmit in the proper (odd or even) minutes. | ||||
| 
 | ||||
| ** The Rx frequency marker is moved to the frequency of the CQing | ||||
| station. | ||||
| 
 | ||||
| ** You can modify the double-click behavior by holding down the | ||||
| *Shift* key to move only the Tx frequency or the *Ctrl* key to move | ||||
| both Rx and Tx frequencies. (On a Mac computer, use the *command* key | ||||
| instead of *Ctrl*).  | ||||
| 
 | ||||
| ** In addition, if *Double-click on call sets Tx enable* is checked on the  | ||||
| *Settings | General* tab then *Enable Tx* will be activated | ||||
| so that a transmission will start automatically at the proper time. | ||||
| 
 | ||||
| 
 | ||||
| + | ||||
| 
 | ||||
| NOTE: You can prevent your Tx frequency from being changed by checking the | ||||
| box *Hold Tx Freq*. | ||||
| 
 | ||||
| - Double-click on the decoded message `K1JT HA0DU KN07`, highlighted | ||||
| in red.  Results will be similar to those in the previous step. The Tx | ||||
| frequency (red marker) is not moved unless *Shift* or *Ctrl* is held | ||||
| down.  Messages highlighted in red are usually in response to your own | ||||
| CQ or from a tail-ender, and you probably want your Tx frequency to | ||||
| stay where it was. | ||||
| 
 | ||||
| - 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. | ||||
| @ -38,11 +103,12 @@ things just described and also invokes the decoder in a small range | ||||
| around the Rx frequency.  To decode a particular signal, double-click | ||||
| near the left edge of its waterfall trace. | ||||
| 
 | ||||
| - Now double-click on any of the lines of decoded text in the Band | ||||
| Activity window.  Any line will show the same behavior, setting | ||||
| Rx frequency to that of the selected message and leaving Tx frequency | ||||
| unchanged.  To change both Rx and Tx frequencies, hold *Ctrl* down | ||||
| when double-clicking. | ||||
| - Ctrl-double-click on a signal to set both Rx and Tx frequencies and | ||||
| decode at the new frequency. | ||||
| 
 | ||||
| - Click *Erase* to clear the right window.  | ||||
| 
 | ||||
| - Double-click *Erase* to clear both text windows. | ||||
| 
 | ||||
| TIP: To avoid QRM from competing callers, it is usually best  | ||||
| to answer a CQ on a different frequency from that of the CQing | ||||
| @ -53,6 +119,11 @@ box *Hold Tx Freq*. | ||||
| TIP: Keyboard shortcuts *Shift+F11* and *Shift+F12* provide an easy | ||||
| way to move your Tx frequency down or up in 60 Hz steps. | ||||
| 
 | ||||
| TIP: Sliders and spinner controls respond to *Arrow* key presses | ||||
| and *Page Up/Down* key presses, with the *Page* keys moving the | ||||
| controls in larger steps.  You can also type numbers directly into | ||||
| the spinner controls or use the mouse wheel. | ||||
| 
 | ||||
| TIP: An online {ft8_tips} by ZL2IFB offers many additional tips on | ||||
| operating procedures. | ||||
| 
 | ||||
|  | ||||
| @ -1,25 +0,0 @@ | ||||
| // Status=review | ||||
| 
 | ||||
| - Click the *Stop* button on the main window to halt any data acquisition.   | ||||
| 
 | ||||
| - Select *JT9* from the *Mode* menu and *Deep* from the *Decode* menu. | ||||
| 
 | ||||
| - Set the audio frequencies to *Tx 1224 Hz* and *Rx 1224 Hz*.   | ||||
| 
 | ||||
| + | ||||
| 
 | ||||
| TIP: Sliders and spinner controls respond to *Arrow* key presses | ||||
| and *Page Up/Down* key presses, with the *Page* keys moving the | ||||
| controls in larger steps.  You can also type numbers directly into | ||||
| the spinner controls or use the mouse wheel. | ||||
| 
 | ||||
| [[DOWNLOAD_SAMPLES]] | ||||
| === Download Samples | ||||
| 
 | ||||
| - Select *Download samples...* from the *Help* menu. | ||||
| 
 | ||||
| - Download some or all of the available sample files using checkboxes | ||||
| on the screen shown below.  For this tutorial you will need at least | ||||
| the JT9 and JT9+JT65 files. | ||||
| 
 | ||||
| image::download_samples.png[align="center",alt="Downlod Samples"] | ||||
| @ -1,13 +1,46 @@ | ||||
| // Status=review | ||||
| 
 | ||||
| - *Bins/Pixel* = 4 | ||||
| - *Start* = 200 Hz | ||||
| - *N Avg* = 5 | ||||
| - *Palette* = Digipan | ||||
| - *Flatten* = checked | ||||
| - Select *Cumulative* for data display | ||||
| - *Gain* and *Zero* sliders for waterfall and spectrum set near midscale | ||||
| - *Spec* = 25% | ||||
| The WSJT-X Wide Graph window displays the frequency spectrum of the received audio. Usually, the  | ||||
| upper portion of the window shows a waterfall plot of the frequency spectrum (a spectrogram) and  | ||||
| a line plot of the current or average spectrum. Controls at the bottom of the window are used to  | ||||
| set up the displayed audio frequency range, color palette, and scaling of the spectrum displays.  | ||||
| A control on the bottom right of the Wide Graph (displayed as *Spec nn%*) lets you control | ||||
| the vertical fraction of the window occupied by the spectrum line plot. | ||||
| It is important to set appropriate lower and upper  | ||||
| audio frequency limits for the Wide Graph because these limits define the FT8 decoder's search window. | ||||
| For this tutorial, the limits will be set to cover 100-3300 Hz: | ||||
| 
 | ||||
| - Set *Start* = 100 Hz. | ||||
| - Set *Bins/Pixel* = 5. Smaller/larger values make the Wide Graph cover a smaller/larger  | ||||
| frequency range. | ||||
| - Use the mouse to grab the left or right edge of the *Wide Graph*, and | ||||
| adjust its width so that the upper frequency limit is about 2400 Hz. | ||||
| adjust its width so that the upper frequency limit is about 3300 Hz. | ||||
| 
 | ||||
| The *N Avg* setting controls how many spectra are averaged to produce each line in the spectrogram.  | ||||
| Smaller values make the spectrogram update more frequently, resulting in signals being more spread | ||||
| out in the vertical (time) direction. | ||||
| On the other hand, larger values make it easier to detect very weak signals: | ||||
| 
 | ||||
| - Set *N Avg* = 2.  | ||||
| 
 | ||||
| The *Palette* setting controls the color scheme used for the spectrogram:  | ||||
| 
 | ||||
| - Set *Palette* = Fldigi  | ||||
| 
 | ||||
| When *Flatten* is checked, WSJT-X attempts to correct for slope or curvature in the receiver's | ||||
| passband shape.   | ||||
| 
 | ||||
| - *Flatten* = checked  | ||||
| 
 | ||||
| The line plot can be set to display the current (un-averaged) spectrum or the cumulative (averaged) | ||||
| spectrum: | ||||
| 
 | ||||
| - Select *Cumulative* for data display | ||||
| - Set the *Gain* and *Zero* sliders for the waterfall and spectrum to near midscale | ||||
| 
 | ||||
| The *Spec nn%* setting determines what fraction of the vertical extent of the Wide Graph will | ||||
| be used for the line plot of the spectrum. Setting *Spec* to 0 will eliminate the line plot and | ||||
| a setting of 100 will eliminate the spectrogram and show only the line plot: | ||||
| 
 | ||||
| - Set *Spec* = 50%  | ||||
| 
 | ||||
|  | ||||
| @ -141,31 +141,20 @@ include::transceiver-setup.adoc[] | ||||
| == Basic Operating Tutorial | ||||
| 
 | ||||
| This section introduces the basic user controls and program behavior | ||||
| of _WSJT-X_, with particular emphasis on the JT9, JT65, and FT8 modes. | ||||
| of _WSJT-X_, with particular emphasis on the FT8 mode. | ||||
| We suggest that new users should go through the full HF-oriented | ||||
| tutorial, preferably while at your radio.  Note that as of late 2018, | ||||
| digital usage on the HF bands has mostly moved from JT65 and JT9 to FT8.  So | ||||
| you may wish to pay particular attention to *FT8*, in Section 6.6. | ||||
| tutorial, preferably while at your radio.   | ||||
| 
 | ||||
| Subsequent sections cover additional details on <<MAKE_QSOS,Making | ||||
| QSOs>>, <<WSPR,WSPR mode>> and <<VHF_AND_UP,VHF+ Features>>. | ||||
| 
 | ||||
| [[TUT_MAIN]] | ||||
| === Main Window Settings | ||||
| include::tutorial-main-window.adoc[] | ||||
| [[TUT_SAMPLES]] | ||||
| include::tutorial-download-samples.adoc[] | ||||
| 
 | ||||
| [[TUT_WIDE_GRAPH]] | ||||
| === Wide Graph Settings | ||||
| include::tutorial-wide-graph-settings.adoc[] | ||||
| 
 | ||||
| [[TUT_EX1]] | ||||
| === JT9 | ||||
| include::tutorial-example1.adoc[] | ||||
| 
 | ||||
| [[TUT_EX2]] | ||||
| === JT9+JT65 | ||||
| include::tutorial-example2.adoc[] | ||||
| 
 | ||||
| [[TUT_EX3]] | ||||
| === FT8 | ||||
| include::tutorial-example3.adoc[] | ||||
|  | ||||
| @ -1118,7 +1118,7 @@ subroutine pack77_1(nwords,w,i3,n3,c77) | ||||
|      irpt=irpt+35 | ||||
|   else if(c2.eq.'R+' .or. c2.eq.'R-') then | ||||
|      ir=1 | ||||
|      read(w(nwords)(2:),*) irpt | ||||
|      read(w(nwords)(2:),*,err=900) irpt | ||||
|      if(irpt.ge.-50 .and. irpt.le.-31) irpt=irpt+101 | ||||
|      irpt=irpt+35 | ||||
|   else if(trim(w(nwords)).eq.'RRR') then | ||||
| @ -1274,6 +1274,7 @@ subroutine pack77_4(nwords,w,i3,n3,c77) | ||||
|      if(call_1(1:1).eq.'<') call_1=w(1)(2:len(trim(w(1)))-1) | ||||
|      call_2=w(2) | ||||
|      if(call_2(1:1).eq.'<') call_2=w(2)(2:len(trim(w(2)))-1) | ||||
|      if(call_1(1:1).ne.'<' .and. call_2(1:1).ne.'<') goto 900 | ||||
|      call chkcall(call_1,bcall_1,ok1) | ||||
|      call chkcall(call_2,bcall_2,ok2) | ||||
|      icq=0 | ||||
|  | ||||
| @ -55,7 +55,8 @@ subroutine jt9a() | ||||
|   if(.not.ok) call abort | ||||
|   call flush(6) | ||||
|   call timer('decoder ',0) | ||||
|   if(local_params%nmode.eq.8 .and. local_params%ndiskdat) then | ||||
|   if(local_params%nmode.eq.8 .and. local_params%ndiskdat .and.    & | ||||
|        .not. local_params%nagain) then | ||||
| ! Early decoding pass, FT8 only, when wsjtx reads from disk | ||||
|      nearly=41 | ||||
|      local_params%nzhsym=nearly | ||||
|  | ||||
| @ -157,12 +157,17 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave,  & | ||||
| ! Try list decoding via "Deep Likelihood". | ||||
|      call timer('ccf_85  ',0) | ||||
| ! Try to synchronize using all 85 symbols | ||||
|      call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) | ||||
|      call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,   & | ||||
|           better,ccf1) | ||||
|      call timer('ccf_85  ',1) | ||||
| 
 | ||||
|      if(better.ge.1.10 .or. mode_q65.ge.8) then | ||||
|         call timer('list_dec',0) | ||||
|         call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) | ||||
|         call timer('list_dec',1) | ||||
| !        if(idec.ge.0) write(70,3070) idec,mode_q65,better,trim(decoded) | ||||
| !3070    format(i3,i5,f8.2,2x,a) | ||||
|      endif | ||||
| ! If idec=3 we have a q3 decode.  Continue to compute sync curve for plotting. | ||||
|   endif | ||||
| 
 | ||||
| @ -359,18 +364,21 @@ subroutine q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) | ||||
| 100 return | ||||
| end subroutine q65_dec_q012 | ||||
| 
 | ||||
| subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) | ||||
| subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,   & | ||||
|      better,ccf1) | ||||
| 
 | ||||
| ! Attempt synchronization using all 85 symbols, in advance of an | ||||
| ! attempt at q3 decoding.  Return ccf1 for the "red sync curve". | ||||
|    | ||||
|   real s1(iz,jz) | ||||
|   real, allocatable :: ccf(:,:)          !CCF(freq,lag) | ||||
|   real, allocatable :: best(:)           !best(imsg) -- for checking 2nd best | ||||
|   real ccf1(-ia2:ia2) | ||||
|   integer ijpk(2) | ||||
|   integer itone(85) | ||||
| 
 | ||||
|   allocate(ccf(-ia2:ia2,-53:214)) | ||||
|   allocate(best(ncw)) | ||||
|   ipk=0 | ||||
|   jpk=0 | ||||
|   ccf_best=0. | ||||
| @ -415,8 +423,15 @@ subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) | ||||
|         imsg_best=imsg | ||||
|         ccf1=ccf(:,jpk) | ||||
|      endif | ||||
|      best(imsg)=ccfmax | ||||
|   enddo  ! imsg | ||||
| 
 | ||||
|   deallocate(ccf) | ||||
|   better=0. | ||||
|   if(imsg_best.gt.0) then | ||||
|      best(imsg_best)=0. | ||||
|      better=ccf_best/maxval(best) | ||||
|   endif | ||||
| 
 | ||||
|   return | ||||
| end subroutine q65_ccf_85 | ||||
|  | ||||
| @ -34,11 +34,14 @@ extern struct {                     //This is "common/datcom/..." in Fortran | ||||
|   int nfast;                        //No longer used
 | ||||
|   int nsave;                        //Number of s3(64,63) spectra saved
 | ||||
|   int max_drift;                    //Maximum Q65 drift: units symbol_rate/TxT
 | ||||
|   int nhsym;                        //Number of available JT65 half-symbols
 | ||||
|   char mycall[12]; | ||||
|   char mygrid[6]; | ||||
|   char hiscall[12]; | ||||
|   char hisgrid[6]; | ||||
|   char datetime[20]; | ||||
|   int junk1;                        //Used to test extent of copy to shared memory
 | ||||
|   int junk2; | ||||
| } datcom_; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ extern qint16 id[4*60*96000]; | ||||
| 
 | ||||
| void getfile(QString fname, bool xpol, int dbDgrd) | ||||
| { | ||||
|   int npts=2*52*96000; | ||||
|   int npts=2*56*96000; | ||||
|   if(xpol) npts=2*npts; | ||||
| 
 | ||||
| // Degrade S/N by dbDgrd dB -- for tests only!!
 | ||||
| @ -56,7 +56,7 @@ void getfile(QString fname, bool xpol, int dbDgrd) | ||||
| 
 | ||||
| void savetf2(QString fname, bool xpol) | ||||
| { | ||||
|   int npts=2*52*96000; | ||||
|   int npts=2*56*96000; | ||||
|   if(xpol) npts=2*npts; | ||||
| 
 | ||||
|   qint16* buf=(qint16*)malloc(2*npts); | ||||
|  | ||||
| @ -136,8 +136,8 @@ target_link_libraries (m65 m65impl ${FFTW3_LIBRARIES}) | ||||
| add_executable (mapsim mapsim.f90) | ||||
| target_link_libraries (mapsim m65impl ${FFTW3_LIBRARIES}) | ||||
| 
 | ||||
| add_executable (synctest synctest.f90) | ||||
| target_link_libraries (synctest m65impl ${FFTW3_LIBRARIES}) | ||||
| #add_executable (synctest synctest.f90) | ||||
| #target_link_libraries (synctest m65impl ${FFTW3_LIBRARIES}) | ||||
| 
 | ||||
| if (WIN32) | ||||
|   install ( | ||||
|  | ||||
| @ -6,18 +6,21 @@ subroutine decode0(dd,ss,savg,nstandalone) | ||||
|   real*4 dd(4,NSMAX),ss(4,322,NFFT),savg(4,NFFT) | ||||
|   real*8 fcenter | ||||
|   integer hist(0:32768) | ||||
|   logical ldecoded | ||||
|   character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20 | ||||
|   character mycall0*12,hiscall0*12,hisgrid0*6 | ||||
|   common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain,                & | ||||
|        ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift,                 & | ||||
|        mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode,               & | ||||
|        nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime | ||||
|        nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
|   data neme0/-99/,mcall3b/1/ | ||||
|   save | ||||
| 
 | ||||
|   call sec0(0,tquick) | ||||
|   call timer('decode0 ',0) | ||||
|   if(newdat.ne.0) then | ||||
|      nz=52*96000 | ||||
|      nz=96000*nhsym/5.3833 | ||||
|      hist=0 | ||||
|      do i=1,nz | ||||
|         j1=min(abs(dd(1,i)),32768.0) | ||||
| @ -36,7 +39,6 @@ subroutine decode0(dd,ss,savg,nstandalone) | ||||
|      enddo | ||||
| 10   rmsdd=1.5*i | ||||
|   endif | ||||
|   nhsym=279 | ||||
|   ndphi=0 | ||||
|   if(iand(nrxlog,8).ne.0) ndphi=1 | ||||
| 
 | ||||
| @ -52,12 +54,16 @@ subroutine decode0(dd,ss,savg,nstandalone) | ||||
|   call map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,           & | ||||
|        mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift,          & | ||||
|        nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid,                 & | ||||
|        neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,nxpol,nmode) | ||||
|        neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,             & | ||||
|        ndiskdat,nxpol,nmode) | ||||
|   call timer('map65a  ',1) | ||||
|   call timer('decode0 ',1) | ||||
| 
 | ||||
|   write(*,1010) nsum,nsave | ||||
| 1010 format('<DecodeFinished>',2i4) | ||||
|   call sec0(1,tdec) | ||||
|   if(nhsym.eq.nhsym1) write(*,1010) nsum,nsave,nstandalone,nhsym,tdec | ||||
| 1010 format('<EarlyFinished>',3i4,i6,f6.2) | ||||
|   if(nhsym.eq.nhsym2) write(*,1012) nsum,nsave,nstandalone,nhsym,tdec | ||||
| 1012 format('<DecodeFinished>',3i4,i6,f6.2) | ||||
|   flush(6) | ||||
| 
 | ||||
|   return | ||||
|  | ||||
| @ -3,14 +3,15 @@ subroutine display(nkeep,ftol) | ||||
|   parameter (MAXLINES=400,MX=400,MAXCALLS=500) | ||||
|   integer indx(MAXLINES),indx2(MX) | ||||
|   character*83 line(MAXLINES),line2(MX),line3(MAXLINES) | ||||
|   character out*52,cfreq0*3,livecq*58 | ||||
|   character out*52,out0*52,cfreq0*3,livecq*58 | ||||
|   character*6 callsign,callsign0 | ||||
|   character*12 freqcall(MAXCALLS) | ||||
|   real freqkHz(MAXLINES) | ||||
|   integer utc(MAXLINES),utc2(MX),utcz | ||||
|   real*8 f0 | ||||
| 
 | ||||
|   rewind 26 | ||||
|   out0=' ' | ||||
|   rewind(26) | ||||
| 
 | ||||
|   do i=1,MAXLINES | ||||
|      read(26,1010,end=10) line(i) | ||||
| @ -45,7 +46,7 @@ subroutine display(nkeep,ftol) | ||||
|      enddo | ||||
| 20   i0=i | ||||
|      nz=nz-i0+1 | ||||
|      rewind 26 | ||||
|      rewind(26) | ||||
|      if(nz.lt.1) go to 999 | ||||
|      do i=1,nz | ||||
|         j=i+i0-1 | ||||
| @ -132,8 +133,14 @@ subroutine display(nkeep,ftol) | ||||
|            index(livecq,' QRT ').gt.0 .or. index(livecq,' CQV ').gt.0 .or.  & | ||||
|            index(livecq,' CQH ').gt.0) write(19,1029) livecq | ||||
| 1029    format(a58) | ||||
| 
 | ||||
| ! Suppress listing duplicate (same time, same decoded message) | ||||
|         if(out(14:17).ne.out0(14:17) .or. out(26:50).ne.out0(26:50)) then | ||||
|            write(*,1030) out                  !Messages | ||||
| 1030       format('@',a52) | ||||
|            out0=out | ||||
|         endif | ||||
| 
 | ||||
|         i1=index(out(26:),' ') | ||||
|         callsign=out(i1+26:) | ||||
|         i2=index(callsign,' ') | ||||
|  | ||||
| @ -26,21 +26,23 @@ program m65 | ||||
|   use timer_module, only: timer | ||||
|   use timer_impl, only: init_timer, fini_timer | ||||
| 
 | ||||
|   include 'njunk.f90' | ||||
|   parameter (NFFT=32768) | ||||
|   parameter (NSMAX=60*96000) | ||||
|   parameter (NREAD=2048) | ||||
|   integer*2 i2(NREAD) | ||||
|   real*8 hsym | ||||
|   real*4 ssz5a(NFFT) | ||||
|   logical*1 lstrong(0:1023) | ||||
|   logical*1 lstrong(0:1023),ldecoded,eof | ||||
|   real*8 fc0,fcenter | ||||
|   character*80 arg,infile | ||||
|   character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20 | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fc0,nutc0,junk(37) | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fc0,nutc0,junk(NJUNK) | ||||
|   common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain,                & | ||||
|        ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift,                 & | ||||
|        mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode,               & | ||||
|        nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime | ||||
|        nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
| 
 | ||||
|   nargs=iargc() | ||||
|   if(nargs.ne.1 .and. nargs.lt.5) then | ||||
| @ -52,6 +54,9 @@ program m65 | ||||
|      print*,'  (Gets data from MAP65, via shared memory region.)' | ||||
|      go to 999 | ||||
|   endif | ||||
|   nstandalone=1 | ||||
|   nhsym1=280 | ||||
|   nhsym2=302 | ||||
|   call getarg(1,arg) | ||||
|   if(arg(1:2).eq.'-s') then | ||||
|      call m65a | ||||
| @ -124,9 +129,12 @@ program m65 | ||||
| 
 | ||||
|      nch=2 | ||||
|      if(nxpol.eq.1) nch=4 | ||||
| 
 | ||||
|      eof=.false. | ||||
|      do irec=1,9999999 | ||||
|         read(10,end=10) i2 | ||||
|         if(.not.eof) read(10,end=4) i2 | ||||
|         go to 6 | ||||
| 4       eof=.true. | ||||
| 6       if(eof) i2=0 | ||||
|         do i=1,NREAD,nch | ||||
|            k=k+1 | ||||
|            if(k.gt.60*96000) exit | ||||
| @ -156,15 +164,18 @@ program m65 | ||||
|                 rejecty,pxdb,pydb,ssz5a,nkhz,ihsym,nzap,slimit,lstrong) | ||||
|            call timer('symspec ',1) | ||||
|            nhsym0=nhsym | ||||
| 
 | ||||
|            nutc=nutc0 | ||||
|            if(nhsym.eq.nhsym1) call decode0(dd,ss,savg,nstandalone) | ||||
|            if(nhsym.eq.nhsym2) then | ||||
|               call decode0(dd,ss,savg,nstandalone) | ||||
|               exit | ||||
|            endif | ||||
|         endif | ||||
|      enddo  ! irec | ||||
| 
 | ||||
| 10   continue | ||||
|      if(iqadjust.ne.0) write(*,3002) rejectx,rejecty | ||||
| 3002 format('Image rejection:',2f7.1,' dB') | ||||
|      nutc=nutc0 | ||||
|      nstandalone=1 | ||||
|      call decode0(dd,ss,savg,nstandalone) | ||||
|   enddo  ! ifile | ||||
| 
 | ||||
|   call timer('m65     ',1) | ||||
| @ -175,5 +186,10 @@ program m65 | ||||
|   print*,infile | ||||
| 
 | ||||
| 999 call fini_timer() | ||||
|   if(arg(1:2).eq.'-s') then | ||||
|      write(21,1999) datetime(:17) | ||||
| 1999 format('Subprocess m65 terminated normally at UTC ',a17) | ||||
|      close(21) | ||||
|   endif | ||||
| 
 | ||||
| end program m65 | ||||
|  | ||||
| @ -70,27 +70,35 @@ subroutine m65b(m65com,nbytes) | ||||
| end subroutine m65b | ||||
| 
 | ||||
| subroutine m65c(dd,ss,savg,nparams0) | ||||
| 
 | ||||
|   include 'njunk.f90' | ||||
|   real*4 dd(4,5760000),ss(4,322,32768),savg(4,32768) | ||||
|   real*8 fcenter | ||||
|   integer nparams0(40),nparams(40) | ||||
|   integer nparams0(NJUNK+2),nparams(NJUNK+2) | ||||
|   logical ldecoded | ||||
|   character*12 mycall,hiscall | ||||
|   character*6 mygrid,hisgrid | ||||
|   character*20 datetime | ||||
|   common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain,              & | ||||
|        ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift,               & | ||||
|        mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode,             & | ||||
|        nfast,nsave,max_drift,mycall,mygrid,hiscall,hisgrid,datetime | ||||
|        nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,       & | ||||
|        datetime,junk1,junk2 | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
|   equivalence (nparams,fcenter) | ||||
|    | ||||
|   nparams=nparams0                     !Copy parameters into common/npar/ | ||||
|   npatience=1 | ||||
|   if(iand(nrxlog,1).ne.0) then | ||||
|   if(nhsym.eq.nhsym1 .and. iand(nrxlog,1).ne.0) then | ||||
|      write(21,1000) datetime(:17) | ||||
| 1000 format(/'UTC Date: 'a17/78('-')) | ||||
|      flush(21) | ||||
|   endif | ||||
|   if(iand(nrxlog,2).ne.0) rewind 21 | ||||
|   if(iand(nrxlog,4).ne.0) rewind 26 | ||||
|   if(iand(nrxlog,2).ne.0) rewind(21) | ||||
|   if(iand(nrxlog,4).ne.0) then | ||||
|      if(nhsym.eq.nhsym1) rewind(26) | ||||
|      if(nhsym.eq.nhsym2) backspace(26) | ||||
|   endif | ||||
| 
 | ||||
|   nstandalone=0 | ||||
|   if(sum(nparams).ne.0) call decode0(dd,ss,savg,nstandalone) | ||||
|  | ||||
| @ -1,7 +1,8 @@ | ||||
| subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|      mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift,             & | ||||
|      nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid,                    & | ||||
|      neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,nxpol,nmode) | ||||
|      neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample,                & | ||||
|      ndiskdat,nxpol,nmode) | ||||
| 
 | ||||
| !  Processes timf2 data from Linrad to find and decode JT65 signals. | ||||
| 
 | ||||
| @ -24,6 +25,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|   logical done(MAXMSG) | ||||
|   logical xpol,bq65,q65b_called | ||||
|   logical candec(MAX_CANDIDATES) | ||||
|   logical ldecoded | ||||
|   character decoded*22,blank*22,cmode*2 | ||||
|   real short(3,NFFT)                 !SNR dt ipol for potential shorthands | ||||
|   real qphi(12) | ||||
| @ -31,35 +33,44 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|    | ||||
|   common/c3com/ mcall3a | ||||
|   common/testcom/ifreq | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
| 
 | ||||
|   data blank/'                      '/,cm/'#'/ | ||||
|   data shmsg0/'ATT','RO ','RRR','73 '/ | ||||
|   data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/ | ||||
|   save | ||||
| 
 | ||||
|   call sec0(0,tquick) | ||||
| ! Clean start for Q65 at early decode | ||||
|   if(nhsym.eq.nhsym1 .or. nagain.ne.0) ldecoded=.false. | ||||
| 
 | ||||
|   nkhz_center=nint(1000.0*(fcenter-int(fcenter))) | ||||
|   mfa=nfa-nkhz_center+48 | ||||
|   mfb=nfb-nkhz_center+48 | ||||
|   mode65=mod(nmode,10) | ||||
|   if(mode65.eq.3) mode65=4 | ||||
|   mode_q65=nmode/10 | ||||
|   nts_jt65=2**(mode65-1)              !JT65 tone separation factor | ||||
|   nts_q65=2**(mode_q65-1)             !Q65 tone separation factor | ||||
|   xpol=(nxpol.ne.0) | ||||
|    | ||||
|   nts_jt65=2**(mode65-1)              !JT65 tone separation factor | ||||
|   nts_q65=2**(mode_q65)               !Q65 tone separation factor | ||||
| ! No second decode for JT65? | ||||
| !  if(nhsym.eq.nhsym2 .and. (nstandalone.eq.1 .or. ndiskdat.eq.0)) mode65=0 | ||||
|   if(nhsym.eq.nhsym2 .and. nagain.eq.0) mode65=0 | ||||
| !  print*,'=a',nhsym,nagain,mode65 | ||||
| 
 | ||||
|   if(nagain.eq.0) then | ||||
|      call timer('get_cand',0) | ||||
|      call get_candidates(ss,savg,xpol,mfa,mfb,nts_jt65,nts_q65,cand,ncand) | ||||
|      call get_candidates(ss,savg,xpol,nhsym,mfa,mfb,nts_jt65,nts_q65,cand,ncand) | ||||
|      call timer('get_cand',1) | ||||
|      candec=.false. | ||||
|   endif | ||||
| !### | ||||
| !  do k=1,ncand | ||||
| !     freq=cand(k)%f+nkhz_center-48.0-1.27046 | ||||
| !     write(70,3010) nutc,k,cand(k)%snr,cand(k)%f,freq,cand(k)%xdt,    & | ||||
| !          cand(k)%ipol,cand(k)%iflip | ||||
| !3010 format(i4.4,i5,f10.1,3f10.3,2i3) | ||||
| !     ipk=cand(k)%indx | ||||
| !     write(*,3010) nutc,k,db(cand(k)%snr),freq,cand(k)%xdt,    & | ||||
| !          cand(k)%ipol,cand(k)%iflip,ipk,ldecoded(ipk) | ||||
| !3010 format('=a',i5.4,i5,f8.2,f10.3,f8.2,2i3,i6,L4) | ||||
| !  enddo | ||||
| !### | ||||
| 
 | ||||
| @ -111,7 +122,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|      short=0.                                 !Zero the whole short array | ||||
|      jpz=1 | ||||
|      if(xpol) jpz=4 | ||||
|      if(mode65.eq.0) go to 50 | ||||
| 
 | ||||
| ! First steps for JT65 decoding | ||||
|      do i=ia,ib                               !Search over freq range | ||||
|         freq=0.001*(i-16385)*df | ||||
| !  Find the local base level for each polarization; update every 10 bins. | ||||
| @ -278,8 +291,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|         endif | ||||
|      enddo  !i=ia,ib | ||||
| 
 | ||||
|      if(nqd.eq.1) then | ||||
| 50   if(nqd.eq.1) then | ||||
|         nwrite=0 | ||||
|         if(mode65.eq.0) km=0 | ||||
|         do k=1,km | ||||
|            decoded=msg(k) | ||||
|            if(decoded.ne.'                      ') then | ||||
| @ -350,7 +364,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|               call timer('q65b    ',0) | ||||
|               call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,   & | ||||
|                    ntol,xpol,mycall,mygrid, hiscall,hisgrid,mode_q65,f0,fqso, & | ||||
|                    newdat,nagain,max_drift,idec) | ||||
|                    newdat,nagain,max_drift,nhsym,idec) | ||||
|               call timer('q65b    ',1) | ||||
|               if(idec.ge.0) candec(icand)=.true. | ||||
|            enddo | ||||
| @ -361,7 +375,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|               call timer('q65b    ',0) | ||||
|               call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,   & | ||||
|                    ntol,xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,  & | ||||
|                    newdat,nagain,max_drift,idec) | ||||
|                    newdat,nagain,max_drift,nhsym,idec) | ||||
|               call timer('q65b    ',1) | ||||
|            endif | ||||
|         endif | ||||
| @ -379,15 +393,17 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|       | ||||
|      if(ndphi.eq.1 .and.iloop.eq.12) call getdphi(qphi) | ||||
|      if(nqd.eq.1) then | ||||
|         write(*,1013) nsum,nsave | ||||
| 1013    format('<QuickDecodeDone>',2i4) | ||||
|         call sec0(1,tdec) | ||||
|         write(*,1013) nsum,nsave,nstandalone,nhsym,tdec | ||||
| 1013    format('<QuickDecodeDone>',3i4,i6,f6.2) | ||||
|         flush(6) | ||||
|         call sec0(1,tquick) | ||||
|         open(16,file='tquick.dat',status='unknown',access='append') | ||||
|         write(16,1016) nutc,tquick | ||||
|         write(16,1016) nutc,tdec | ||||
| 1016    format(i4.4,f7.1) | ||||
|         close(16) | ||||
|      endif | ||||
|      call sec0(1,tsec0) | ||||
|      if(nhsym.eq.nhsym1 .and. tsec0.gt.3.0) go to 700 | ||||
|      if(nqd.eq.1 .and. nagain.eq.1) go to 900 | ||||
| 
 | ||||
|      if(nqd.eq.0 .and. bq65) then | ||||
| @ -403,21 +419,19 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|            call timer('q65b    ',0) | ||||
|            call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, & | ||||
|                 xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,newdat,   & | ||||
|                 nagain,max_drift,idec) | ||||
|                 nagain,max_drift,nhsym,idec) | ||||
|            call timer('q65b    ',1) | ||||
|            if(idec.ge.0) candec(icand)=.true. | ||||
|         enddo  ! icand | ||||
|      endif | ||||
|      call sec0(1,tsec0) | ||||
| 
 | ||||
|   enddo  ! nqd | ||||
| 
 | ||||
| !  Trim the list and produce a sorted index and sizes of groups. | ||||
| !  (Should trimlist remove all but best SNR for given UTC and message content?) | ||||
|   call trimlist(sig,km,ftol,indx,nsiz,nz) | ||||
| 
 | ||||
|   do i=1,km | ||||
|      done(i)=.false. | ||||
|   enddo | ||||
| 700 call trimlist(sig,km,ftol,indx,nsiz,nz) | ||||
|   done(1:km)=.false. | ||||
|   j=0 | ||||
|   ilatest=-1 | ||||
|   do n=1,nz | ||||
| @ -490,11 +504,8 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb,        & | ||||
|            write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp,          & | ||||
|                 cmode(1:1),cmode(2:2) | ||||
| 1100       format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1) | ||||
|            | ||||
| !           write(21,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1,       & | ||||
| !                nutc,decoded,cp,cmode | ||||
| 
 | ||||
|         endif | ||||
| 
 | ||||
|      endif | ||||
|      j=j+nsiz(n) | ||||
|   enddo  !i=1,km | ||||
|  | ||||
							
								
								
									
										1
									
								
								map65/libm65/njunk.f90
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | ||||
|   parameter(NJUNK=40) | ||||
| @ -1,6 +1,6 @@ | ||||
| subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|      mycall0,mygrid,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain,          & | ||||
|      max_drift,idec) | ||||
|      max_drift,nhsym,idec) | ||||
| 
 | ||||
| ! This routine provides an interface between MAP65 and the Q65 decoder | ||||
| ! in WSJT-X.  All arguments are input data obtained from the MAP65 GUI. | ||||
| @ -22,17 +22,20 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|   integer*2 iwave(60*12000) | ||||
|   complex ca(MAXFFT1),cb(MAXFFT1)          !FFTs of raw x,y data | ||||
|   complex cx(0:MAXFFT2-1),cy(0:MAXFFT2-1),cz(0:MAXFFT2) | ||||
|   logical xpol | ||||
|   logical xpol,ldecoded | ||||
|   integer ipk1(1) | ||||
|   real*8 fcenter,freq0,freq1 | ||||
|   character*12 mycall0,hiscall0 | ||||
|   character*12 mycall,hiscall | ||||
|   character*6 mygrid,hisgrid | ||||
|   character*4 grid4 | ||||
|   character*28 msg00 | ||||
|   character*80 line | ||||
|   character*80 wsjtx_dir | ||||
|   character*1 cp,cmode*2 | ||||
|   common/cacb/ca,cb | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
|   data nutc00/-1/,msg00/'                            '/ | ||||
|   save | ||||
| 
 | ||||
|   open(9,file='wsjtx_dir.txt',status='old') | ||||
| @ -50,8 +53,8 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|   ib=nint(ifreq+ntol/df3) | ||||
|   ipk1=maxloc(sync(ia:ib)%ccfmax) | ||||
|   ipk=ia+ipk1(1)-1 | ||||
|   if(ldecoded(ipk)) go to 900 | ||||
|   snr1=sync(ipk)%ccfmax | ||||
| 
 | ||||
|   ipol=1 | ||||
|   if(xpol) ipol=sync(ipk)%ipol | ||||
| 
 | ||||
| @ -141,6 +144,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|   freq0=MHz + 0.001d0*ikhz | ||||
| 
 | ||||
|   if(nsnr0.gt.-99) then | ||||
|      ldecoded(ipk)=.true. | ||||
|      nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal | ||||
|      nq65df=nq65df + nfreq0 - 1000 | ||||
|      npol=nint(poldeg) | ||||
| @ -163,7 +167,6 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|      endif | ||||
| 
 | ||||
| ! Write to lu 26, for Messages and Band Map windows | ||||
| 
 | ||||
|      cmode=': ' | ||||
|      cmode(2:2)=char(ichar('A') + mode_q65-1) | ||||
|      freq1=freq0 + 0.001d0*(ikhz1-ikhz) | ||||
| @ -171,9 +174,14 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & | ||||
|           ':',cp,cmode | ||||
| 1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2) | ||||
| 
 | ||||
| ! Suppress writing duplicates (same time, same decoded message) to map65_rx.log | ||||
|      if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00) then | ||||
| ! Write to file map65_rx.log: | ||||
|         write(21,1110)  freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0 | ||||
| 1110    format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3) | ||||
|         nutc00=nutc | ||||
|         msg00=msg0(1:28) | ||||
|      endif | ||||
|   endif | ||||
| 
 | ||||
| 900 close(13) | ||||
|  | ||||
| @ -2,6 +2,7 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,buf16) | ||||
| 
 | ||||
| ! Reformat timf2 data from Linrad and stuff data into r*4 array dd(). | ||||
| 
 | ||||
|   include 'njunk.f90' | ||||
|   parameter (NSMAX=60*96000)          !Total sample intervals per minute | ||||
|   parameter (NFFT=32768) | ||||
|   integer*1 userx_no | ||||
| @ -11,7 +12,8 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,buf16) | ||||
|   integer*2 jd(4),kd(2),nblock2 | ||||
|   real*4 xd(4),yd(2) | ||||
|   real*8 fcenter | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,junk(36) | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,  & | ||||
|        junk(NJUNK) | ||||
|   equivalence (kd,d4) | ||||
|   equivalence (jd,d8,yd) | ||||
|   equivalence (xd,c16) | ||||
|  | ||||
| @ -18,11 +18,13 @@ subroutine symspec(k,nxpol,ndiskdat,nb,nbslider,idphi,nfsample,    & | ||||
| !  ihsym    index number of this half-symbol (1-322) | ||||
| !  nzap     number of samples zero'ed by noise blanker | ||||
| 
 | ||||
|   include 'njunk.f90' | ||||
|   parameter (NSMAX=60*96000)          !Total sample intervals per minute | ||||
|   parameter (NFFT=32768)              !Length of FFTs | ||||
|   real*8 ts,hsym | ||||
|   real*8 fcenter | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,junk(36) | ||||
|   common/datcom/dd(4,5760000),ss(4,322,NFFT),savg(4,NFFT),fcenter,nutc,  & | ||||
|        junk(NJUNK) | ||||
|   real*4 ssz5a(NFFT),w(NFFT),w2a(NFFT),w2b(NFFT) | ||||
|   complex z,zfac | ||||
|   complex zsumx,zsumy | ||||
|  | ||||
| @ -41,7 +41,7 @@ program synctest | ||||
|   call timer('synctest',0) | ||||
| 
 | ||||
|   call timer('get_cand',0) | ||||
|   call  get_candidates(ss,savg,.true.,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
|   call  get_candidates(ss,savg,302,.true.,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
|   call timer('get_cand',1) | ||||
| 
 | ||||
|   do k=1,ncand | ||||
|  | ||||
| @ -7,6 +7,7 @@ module wideband_sync | ||||
|      real :: pol          !Polarization angle, degrees | ||||
|      integer :: ipol      !Polarization angle, 1 to 4 ==> 0, 45, 90, 135 deg | ||||
|      integer :: iflip     !Sync type: JT65 = +/- 1, Q65 = 0 | ||||
|      integer :: indx | ||||
|   end type candidate | ||||
|   type sync_dat | ||||
|      real :: ccfmax | ||||
| @ -25,24 +26,20 @@ module wideband_sync | ||||
| 
 | ||||
|   contains | ||||
| 
 | ||||
| subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
| subroutine get_candidates(ss,savg,xpol,jz,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
| 
 | ||||
| ! Search symbol spectra ss() over frequency range nfa to nfb (in kHz) for | ||||
| ! JT65 and Q65 sync patterns. The nts_* variables are the submode tone | ||||
| ! spacings: 1 2 4 8 16 for A B C D E.  Birdies are detected and | ||||
| ! excised.  Candidates are returned in the structure array cand(). | ||||
| 
 | ||||
|   parameter (MAX_PEAKS=300) | ||||
|   parameter (MAX_PEAKS=100) | ||||
|   real ss(4,322,NFFT),savg(4,NFFT) | ||||
|   real pavg(-20:20) | ||||
|   integer indx(NFFT) | ||||
|   logical xpol,skip | ||||
|   logical xpol,skip,ldecoded | ||||
|   type(candidate) :: cand(MAX_CANDIDATES) | ||||
| 
 | ||||
|   do j=322,1,-1                            !Find end of data in ss() | ||||
|      if(sum(ss(1,j,1:NFFT)).gt.0.0) exit | ||||
|   enddo | ||||
|   jz=j | ||||
|   common/early/nhsym1,nhsym2,ldecoded(32768) | ||||
| 
 | ||||
|   call wb_sync(ss,savg,xpol,jz,nfa,nfb) | ||||
| 
 | ||||
| @ -87,11 +84,11 @@ subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
|         diffhz=1000.0*(f0-cand(m)%f) | ||||
|         bw=nts_q65*110.0 | ||||
|         if(cand(m)%iflip.ne.0) bw=nts_jt65*178.0 | ||||
|         if(diffhz.gt.-20.0 .and. diffhz.lt.bw+20.0) skip=.true. | ||||
| !        write(*,3301) i,k,m,f0,cand(m)%f,diffhz,snr1,skip | ||||
| !3301    format('=',3i5,f10.1,3f10.3,L3) | ||||
|         if(diffhz.gt.-0.03*bw .and. diffhz.lt.1.03*bw) skip=.true. | ||||
|      enddo | ||||
|      if(skip) cycle | ||||
| !     write(*,3301) i,k,m,f0,diffhz,bw,db(snr1) | ||||
| !3301 format('=A',3i5,f8.3,2f8.0,f8.2) | ||||
|      k=k+1 | ||||
|      cand(k)%snr=snr1 | ||||
|      cand(k)%f=f0 | ||||
| @ -99,6 +96,7 @@ subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand) | ||||
|      cand(k)%pol=sync(n)%pol | ||||
|      cand(k)%ipol=sync(n)%ipol | ||||
|      cand(k)%iflip=nint(flip) | ||||
|      cand(k)%indx=n | ||||
|      if(k.ge.MAX_CANDIDATES) exit | ||||
|   enddo | ||||
|   ncand=k | ||||
|  | ||||
| @ -19,7 +19,7 @@ int main(int argc, char *argv[]) | ||||
|   QApplication a {argc, argv}; | ||||
|   // Override programs executable basename as application name.
 | ||||
|   a.setApplicationName ("MAP65"); | ||||
|   a.setApplicationVersion ("3.0.0-rc3"); | ||||
|   a.setApplicationVersion ("3.0.0-rc4"); | ||||
|   // switch off as we share an Info.plist file with WSJT-X
 | ||||
|   a.setAttribute (Qt::AA_DontUseNativeMenuBar); | ||||
|   MainWindow w; | ||||
|  | ||||
| @ -520,6 +520,7 @@ void MainWindow::dataSink(int k) | ||||
|   static int nkhz; | ||||
|   static int nfsample=96000; | ||||
|   static int nxpol=0; | ||||
|   static int iRxState=0; | ||||
|   static float fgreen; | ||||
|   static int ndiskdat; | ||||
|   static int nb; | ||||
| @ -530,7 +531,6 @@ void MainWindow::dataSink(int k) | ||||
|   static float rejecty; | ||||
|   static float slimit; | ||||
| 
 | ||||
| 
 | ||||
|   if(m_diskData) { | ||||
|     ndiskdat=1; | ||||
|     datcom_.ndiskdat=1; | ||||
| @ -620,10 +620,23 @@ void MainWindow::dataSink(int k) | ||||
|     n=0; | ||||
|   } | ||||
| 
 | ||||
| //  if(ihsym == 280) {   //For JT65, decode at t=52 s (also for old *.tf2/*.iq disk files)
 | ||||
|   if(ihsym == 302) {   //For Q65, decode at t=56 s
 | ||||
|   if(ihsym<280) iRxState=0; | ||||
| 
 | ||||
|   if(iRxState==0 and ihsym>=280) {   //Early decode, t=52 s
 | ||||
|     iRxState=1; | ||||
|     datcom_.newdat=1; | ||||
|     datcom_.nagain=0; | ||||
|     datcom_.nhsym=ihsym; | ||||
|     QDateTime t = QDateTime::currentDateTimeUtc(); | ||||
|     m_dateTime=t.toString("yyyy-MMM-dd hh:mm"); | ||||
|     decode();                                           //Start the decoder
 | ||||
|   } | ||||
| 
 | ||||
|   if(iRxState<=1 and ihsym>=302) {   //Decode at t=56 s (for Q65 and data from disk)
 | ||||
|     iRxState=2; | ||||
|     datcom_.newdat=1; | ||||
|     datcom_.nagain=0; | ||||
|     datcom_.nhsym=ihsym; | ||||
|     QDateTime t = QDateTime::currentDateTimeUtc(); | ||||
|     m_dateTime=t.toString("yyyy-MMM-dd hh:mm"); | ||||
|     decode();                                           //Start the decoder
 | ||||
| @ -636,6 +649,7 @@ void MainWindow::dataSink(int k) | ||||
|       watcher2->setFuture(*future2); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   soundInThread.m_dataSinkBusy=false; | ||||
| } | ||||
| 
 | ||||
| @ -1107,15 +1121,14 @@ void MainWindow::diskDat()                                   //diskDat() | ||||
|   m_diskData=true; | ||||
|   datcom_.newdat=1; | ||||
| 
 | ||||
| //  if(g_pWideGraph->m_bForceCenterFreq)  datcom_.fcenter=g_pWideGraph->m_dForceCenterFreq;
 | ||||
| //  qDebug() << "aa" << datcom_.fcenter << g_pWideGraph->m_dForceCenterFreq
 | ||||
| //           << g_pWideGraph->m_bForceCenterFreq;
 | ||||
| 
 | ||||
|   if(m_fs96000) hsym=2048.0*96000.0/11025.0;   //Samples per JT65 half-symbol
 | ||||
|   if(!m_fs96000) hsym=2048.0*95238.1/11025.0; | ||||
|   for(int i=0; i<304; i++) {           // Do the half-symbol FFTs
 | ||||
|     int k = i*hsym + 2048.5; | ||||
|     dataSink(k); | ||||
|     while(m_decoderBusy) { | ||||
|       qApp->processEvents(); | ||||
|     } | ||||
|     if(i%10 == 0) qApp->processEvents();       //Keep the GUI responsive
 | ||||
|   } | ||||
| } | ||||
| @ -1248,6 +1261,9 @@ void MainWindow::freezeDecode(int n)                          //freezeDecode() | ||||
| void MainWindow::decode()                                       //decode()
 | ||||
| { | ||||
|   ui->DecodeButton->setStyleSheet(m_pbdecoding_style1); | ||||
| 
 | ||||
| //  QFile f("mockRTfiles.txt");
 | ||||
| //  if(datcom_.nagain==0 && (!m_diskData) && !f.exists()) {
 | ||||
|   if(datcom_.nagain==0 && (!m_diskData)) { | ||||
|     qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000; | ||||
|     int imin=ms/60000; | ||||
| @ -1282,7 +1298,7 @@ void MainWindow::decode()                                       //decode() | ||||
|   datcom_.ntol=m_tol; | ||||
|   datcom_.nxant=0; | ||||
|   if(m_xpolx) datcom_.nxant=1; | ||||
|   if(datcom_.nutc < m_nutc0) m_map65RxLog |= 1;  //Date and Time to all65.txt
 | ||||
|   if(datcom_.nutc < m_nutc0) m_map65RxLog |= 1;  //Date and Time to map65_rx.log
 | ||||
|   m_nutc0=datcom_.nutc; | ||||
|   datcom_.map65RxLog=m_map65RxLog; | ||||
|   datcom_.nfsample=96000; | ||||
| @ -1303,7 +1319,9 @@ void MainWindow::decode()                                       //decode() | ||||
|   memcpy(datcom_.mygrid, mgrid.toLatin1(), 6); | ||||
|   memcpy(datcom_.hiscall, hcall.toLatin1(), 12); | ||||
|   memcpy(datcom_.hisgrid, hgrid.toLatin1(), 6); | ||||
|   memcpy(datcom_.datetime, m_dateTime.toLatin1(), 20); | ||||
|   memcpy(datcom_.datetime, m_dateTime.toLatin1(), 17); | ||||
|   datcom_.junk1=1234; | ||||
|   datcom_.junk2=5678; | ||||
| 
 | ||||
|   //newdat=1  ==> this is new data, must do the big FFT
 | ||||
|   //nagain=1  ==> decode only at fQSO +/- Tol
 | ||||
| @ -1317,9 +1335,10 @@ void MainWindow::decode()                                       //decode() | ||||
|     from += noffset; | ||||
|     size -= noffset; | ||||
|   } | ||||
|   memcpy(to, from, qMin(mem_m65.size(), size)); | ||||
|   memcpy(to, from, qMin(mem_m65.size(), size-8)); | ||||
|   datcom_.nagain=0; | ||||
|   datcom_.ndiskdat=0; | ||||
|   m_map65RxLog=0; | ||||
|   m_call3Modified=false; | ||||
| 
 | ||||
|   QFile lockFile(m_appDir + "/.lock");       // Allow m65 to start
 | ||||
| @ -1371,7 +1390,8 @@ void MainWindow::readFromStdout()                             //readFromStdout | ||||
|       lab7->setText (QString {"Avg: %1"}.arg (m_nsum)); | ||||
|       if(m_modeQ65>0) m_wide_graph_window->setDecodeFinished(); | ||||
|     } | ||||
|     if(t.indexOf("<DecodeFinished>") >= 0) { | ||||
| 
 | ||||
|     if((t.indexOf("<EarlyFinished>") >= 0) or (t.indexOf("<DecodeFinished>") >= 0)) { | ||||
|       if(m_widebandDecode) { | ||||
|         m_messages_window->setText(m_messagesText,m_bandmapText); | ||||
|         m_band_map_window->setText(m_bandmapText); | ||||
| @ -1379,10 +1399,12 @@ void MainWindow::readFromStdout()                             //readFromStdout | ||||
|       } | ||||
|       QFile lockFile(m_appDir + "/.lock"); | ||||
|       lockFile.open(QIODevice::ReadWrite); | ||||
|       ui->DecodeButton->setStyleSheet(""); | ||||
|       decodeBusy(false); | ||||
|       if(t.indexOf("<DecodeFinished>") >= 0) { | ||||
|         m_map65RxLog=0; | ||||
|         m_startAnother=m_loopall; | ||||
|       } | ||||
|       ui->DecodeButton->setStyleSheet(""); | ||||
|       decodeBusy(false); | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
| @ -1531,11 +1553,13 @@ void MainWindow::guiUpdate() | ||||
|     msgsent[22]=0; | ||||
| 
 | ||||
|     if(m_restart) { | ||||
|       QString t="  Tx " + m_modeTx + "   "; | ||||
|       t=t.left(11); | ||||
|       QFile f("map65_tx.log"); | ||||
|       f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); | ||||
|       QTextStream out(&f); | ||||
|       out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") | ||||
|           << "  Tx message:  " << QString::fromLatin1(msgsent) | ||||
|           << t << QString::fromLatin1(msgsent) | ||||
| #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0) | ||||
|           << Qt::endl | ||||
| #else | ||||
| @ -1560,11 +1584,13 @@ void MainWindow::guiUpdate() | ||||
|     m_transmitting=true; | ||||
|     m_wide_graph_window->enableSetRxHardware(false); | ||||
| 
 | ||||
|     QString t="  Tx " + m_modeTx + "   "; | ||||
|     t=t.left(11); | ||||
|     QFile f("map65_tx.log"); | ||||
|     f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); | ||||
|     QTextStream out(&f); | ||||
|     out << QDateTime::currentDateTimeUtc().toString("yyyy-MMM-dd hh:mm") | ||||
|         << "  Tx message:  " << QString::fromLatin1(msgsent) | ||||
|         << t << QString::fromLatin1(msgsent) | ||||
| #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0) | ||||
|         << Qt::endl | ||||
| #else | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| set (SAMPLE_FILES | ||||
|   FT4/000000_000002.wav | ||||
|   FT8/181201_180245.wav | ||||
|   FT8/210703_133430.wav | ||||
|   FST4+FST4W/210115_0058.wav | ||||
|   FST4+FST4W/201230_0300.wav | ||||
|   MSK144/181211_120500.wav | ||||
| @ -17,7 +17,6 @@ set (SAMPLE_FILES | ||||
|   JT65/JT65B/000000_0005.wav | ||||
|   JT65/JT65B/000000_0006.wav | ||||
|   JT65/JT65B/000000_0007.wav | ||||
|   JT9+JT65/130610_2343.wav | ||||
|   JT9/130418_1742.wav | ||||
|   MSK144/181211_120500.wav | ||||
|   MSK144/181211_120800.wav | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								samples/FT8/210703_133430.wav
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -453,10 +453,6 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con | ||||
|           // if enabled add the DXCC entity and B4 status to the end of the
 | ||||
|           // preformated text line t1
 | ||||
|           auto currentMode = mode; | ||||
|           if ("JT9+JT65" == mode) | ||||
|             { | ||||
|               currentMode = decodedText.isJT65 () ? "JT65" : "JT9"; | ||||
|             } | ||||
|           message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg | ||||
|                                     , logBook, currentBand, currentMode, extra); | ||||
|         } | ||||
|  | ||||
| @ -1028,9 +1028,9 @@ void MainWindow::not_GA_warning_message () | ||||
|   MessageBox::critical_message (this, | ||||
|                                 "This is a pre-release version of WSJT-X 2.5.0 made\n" | ||||
|                                 "available for testing purposes.  By design it will\n" | ||||
|                                 "be nonfunctional after Aug 31, 2021."); | ||||
|                                 "be nonfunctional after Sept 30, 2021."); | ||||
|   auto now = QDateTime::currentDateTimeUtc (); | ||||
|   if (now >= QDateTime {{2021, 8, 31}, {23, 59, 59, 999}, Qt::UTC}) { | ||||
|   if (now >= QDateTime {{2021, 9, 30}, {23, 59, 59, 999}, Qt::UTC}) { | ||||
|     Q_EMIT finished (); | ||||
|   } | ||||
| } | ||||
| @ -4942,12 +4942,13 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     bool bContestOK=(m_mode=="FT4" or m_mode=="FT8" or m_mode=="Q65" or m_mode=="MSK144"); | ||||
|     if(message_words.size () > 3   // enough fields for a normal message
 | ||||
|        && (message_words.at(1).contains(m_baseCall) || "DE" == message_words.at(1)) | ||||
|        && (message_words.at(2).contains(qso_partner_base_call) or m_bDoubleClicked | ||||
|            or bEU_VHF_w2 or (m_QSOProgress==CALLING))) { | ||||
|       if(message_words.at(3).contains(grid_regexp) and SpecOp::EU_VHF!=m_config.special_op_id()) { | ||||
|         if(SpecOp::NA_VHF==m_config.special_op_id() or SpecOp::WW_DIGI==m_config.special_op_id()){ | ||||
|         if((SpecOp::NA_VHF==m_config.special_op_id() or SpecOp::WW_DIGI==m_config.special_op_id()) and bContestOK){ | ||||
|           setTxMsg(3); | ||||
|           m_QSOProgress=ROGER_REPORT; | ||||
|         } else { | ||||
| @ -5604,8 +5605,8 @@ void MainWindow::lookup() | ||||
|           break; | ||||
|         } | ||||
|         QString t=QString(c); | ||||
|         if(t.indexOf(hisCall)==0) { | ||||
|         int i1=t.indexOf(","); | ||||
|         if(t.left(i1)==hisCall) { | ||||
|           QString hisgrid=t.mid(i1+1,6); | ||||
|           i1=hisgrid.indexOf(","); | ||||
|           if(i1>0) { | ||||
| @ -6454,13 +6455,21 @@ void MainWindow::on_actionQ65_triggered() | ||||
|   ui->lh_decodes_headings_label->setText("UTC   dB   DT Freq    " + tr ("Message")); | ||||
|   ui->rh_decodes_headings_label->setText("UTC   dB   DT Freq    " + tr ("Message")); | ||||
|   statusChanged(); | ||||
|   if(SpecOp::NONE < m_config.special_op_id()) { | ||||
|     ui->labDXped->setVisible(true); | ||||
|     ui->labDXped->setText("Contest ?"); | ||||
|   } else { | ||||
| 
 | ||||
|   if (SpecOp::NONE < m_config.special_op_id () && SpecOp::FOX > m_config.special_op_id ()) { | ||||
|     QString t0=""; | ||||
|     if(SpecOp::NA_VHF==m_config.special_op_id()) t0="NA VHF"; | ||||
|     if(SpecOp::EU_VHF==m_config.special_op_id()) t0="EU VHF"; | ||||
|     if(SpecOp::FIELD_DAY==m_config.special_op_id()) t0="Field Day"; | ||||
|     if(t0=="") { | ||||
|       ui->labDXped->setVisible(false); | ||||
|     ui->labDXped->setText(""); | ||||
|     } else { | ||||
|       ui->labDXped->setVisible(true); | ||||
|       ui->labDXped->setText(t0); | ||||
|     } | ||||
|     on_contest_log_action_triggered(); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void MainWindow::on_actionMSK144_triggered() | ||||
|  | ||||
| @ -530,9 +530,8 @@ void CPlotter::DrawOverlay()                   //DrawOverlay() | ||||
|   int yh=5; | ||||
|   int yTxTop=12; | ||||
|   int yRxBottom=yTxTop + 2*yh + 4; | ||||
|   if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="JT9+JT65" | ||||
|      or m_mode=="Q65" or m_mode=="FT8" or m_mode=="FT4" | ||||
|      or m_mode.startsWith("FST4")) { | ||||
|   if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="Q65" or m_mode=="FT8" | ||||
|      or m_mode=="FT4" or m_mode.startsWith("FST4")) { | ||||
| 
 | ||||
|     if(m_mode=="FST4" and !m_bSingleDecode) { | ||||
|       x1=XfromFreq(m_nfa); | ||||
| @ -580,9 +579,8 @@ void CPlotter::DrawOverlay()                   //DrawOverlay() | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if(m_mode=="JT9" or m_mode=="JT65" or m_mode=="JT9+JT65" or | ||||
|      m_mode.mid(0,4)=="WSPR" or m_mode=="Q65" or m_mode=="FT8" | ||||
|      or m_mode=="FT4" or m_mode.startsWith("FST4")) { | ||||
|   if(m_mode=="JT9" or m_mode=="JT65" or m_mode.mid(0,4)=="WSPR" or m_mode=="Q65" | ||||
|      or m_mode=="FT8" or m_mode=="FT4" or m_mode.startsWith("FST4")) { | ||||
|     painter0.setPen(penRed); | ||||
|     x1=XfromFreq(m_txFreq); | ||||
|     x2=XfromFreq(m_txFreq+bw); | ||||
| @ -597,15 +595,6 @@ void CPlotter::DrawOverlay()                   //DrawOverlay() | ||||
|     painter0.drawLine(x2,yTxTop,x2,yTxTop+yh); | ||||
|   } | ||||
| 
 | ||||
|   if(m_mode=="JT9+JT65") { | ||||
|     QPen pen2(Qt::blue, 3);                //Mark the JT65 | JT9 divider
 | ||||
|     painter0.setPen(pen2); | ||||
|     x1=XfromFreq(m_fMin); | ||||
|     if(x1<2) x1=2; | ||||
|     x2=x1+30; | ||||
|     painter0.drawLine(x1,8,x1,28); | ||||
|   } | ||||
| 
 | ||||
|   if(m_dialFreq>10.13 and m_dialFreq< 10.15 and m_mode.mid(0,4)!="WSPR") { | ||||
|     float f1=1.0e6*(10.1401 - m_dialFreq); | ||||
|     float f2=f1+200.0; | ||||
|  | ||||
| @ -292,7 +292,7 @@ void WideGraph::setTxFreq(int n)                                   //setTxFreq | ||||
| void WideGraph::setMode(QString mode)                              //setMode
 | ||||
| { | ||||
|   m_mode=mode; | ||||
|   ui->fSplitSpinBox->setEnabled(m_mode=="JT9+JT65" or m_mode.startsWith("FST4")); | ||||
|   ui->fSplitSpinBox->setEnabled(m_mode.startsWith("FST4")); | ||||
|   ui->widePlot->setMode(mode); | ||||
|   ui->widePlot->DrawOverlay(); | ||||
|   ui->widePlot->update(); | ||||
| @ -363,7 +363,7 @@ void WideGraph::setRxBand (QString const& band) | ||||
|   else | ||||
|     { | ||||
|       ui->fSplitSpinBox->setValue (m_fMinPerBand.value (band, 2500).toUInt ()); | ||||
|       ui->fSplitSpinBox->setEnabled (m_mode=="JT9+JT65" or m_mode.startsWith("FST4")); | ||||
|       ui->fSplitSpinBox->setEnabled (m_mode.startsWith("FST4")); | ||||
|     } | ||||
|   ui->widePlot->setRxBand(band); | ||||
|   setRxRange (); | ||||
|  | ||||