diff --git a/AppVersion/AppVersion.cpp b/AppVersion/AppVersion.cpp new file mode 100644 index 000000000..26cac2c10 --- /dev/null +++ b/AppVersion/AppVersion.cpp @@ -0,0 +1,43 @@ +// +// wsjtx_app_version - a console application that outputs WSJT-X +// application version +// +// This application is only provided as a simple console application +// +// + +#include +#include +#include + +#include +#include +#include + +#include "revision_utils.hpp" + +int main (int argc, char * argv[]) +{ + QCoreApplication app {argc, argv}; + try + { + app.setApplicationName ("WSJT-X"); + app.setApplicationVersion (version()); + + QCommandLineParser parser; +// parser.setApplicationDescription ("\n" PROJECT_DESCRIPTION); + parser.addHelpOption (); + parser.addVersionOption (); + parser.process (app); + return EXIT_SUCCESS; + } + catch (std::exception const& e) + { + std::cerr << "Error: " << e.what () << '\n'; + } + catch (...) + { + std::cerr << "Unexpected error\n"; + } + return -1; +} diff --git a/Audio/soundin.cpp b/Audio/soundin.cpp index 581f1a92f..53a29799c 100644 --- a/Audio/soundin.cpp +++ b/Audio/soundin.cpp @@ -88,17 +88,16 @@ void SoundInput::start(QAudioDeviceInfo const& device, int framesPerBuffer, Audi //qDebug () << "SoundIn default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); // the Windows MME version of QAudioInput uses 1/5 of the buffer // size for period size other platforms seem to optimize themselves -#if defined (Q_OS_WIN) - m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer * 5)); -#else - Q_UNUSED (framesPerBuffer); -#endif + if (framesPerBuffer > 0) + { + m_stream->setBufferSize (m_stream->format ().bytesForFrames (framesPerBuffer)); + } if (m_sink->initialize (QIODevice::WriteOnly, channel)) { m_stream->start (sink); checkStream (); cummulative_lost_usec_ = -1; - //qDebug () << "SoundIn selected buffer size (bytes):" << m_stream->bufferSize () << "peirod size:" << m_stream->periodSize (); + LOG_DEBUG ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } else { diff --git a/Audio/soundout.cpp b/Audio/soundout.cpp index fe7c58fbf..f3ec3dce3 100644 --- a/Audio/soundout.cpp +++ b/Audio/soundout.cpp @@ -7,6 +7,7 @@ #include #include +#include "Logger.hpp" #include "Audio/AudioDevice.hpp" #include "moc_soundout.cpp" @@ -104,15 +105,13 @@ void SoundOutput::restart (QIODevice * source) // Windows implementation seems to forget the buffer size after a // stop. //qDebug () << "SoundOut default buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); - if (m_framesBuffered) + if (m_framesBuffered > 0) { -#if defined (Q_OS_WIN) m_stream->setBufferSize (m_stream->format().bytesForFrames (m_framesBuffered)); -#endif } m_stream->setCategory ("production"); m_stream->start (source); - // qDebug () << "SoundOut selected buffer size (bytes):" << m_stream->bufferSize () << "period size:" << m_stream->periodSize (); + LOG_DEBUG ("Selected buffer size (bytes): " << m_stream->bufferSize () << " period size: " << m_stream->periodSize ()); } void SoundOutput::suspend () diff --git a/CMakeLists.txt b/CMakeLists.txt index 72c38fa13..3108a6d84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.9 FATAL_ERROR) +cmake_minimum_required (VERSION 3.7.2 FATAL_ERROR) if (APPLE) # @@ -46,9 +46,9 @@ endif () project (wsjtx VERSION 2.3.0.0 - DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio" LANGUAGES C CXX Fortran ) +set (PROJECT_DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio") # # Local CMake modules and support files @@ -70,7 +70,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 2) +set_build_type (RC 3) set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}") # @@ -79,7 +79,7 @@ set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_ set (PROJECT_BUNDLE_NAME "WSJT-X") set (PROJECT_VENDOR "Joe Taylor, K1JT") set (PROJECT_CONTACT "Joe Taylor ") -set (PROJECT_COPYRIGHT "Copyright (C) 2001-2020 by Joe Taylor, K1JT") +set (PROJECT_COPYRIGHT "Copyright (C) 2001-2021 by Joe Taylor, K1JT") set (PROJECT_HOMEPAGE https://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html) set (PROJECT_MANUAL wsjtx-main) set (PROJECT_MANUAL_DIRECTORY_URL https://www.physics.princeton.edu/pulsar/K1JT/wsjtx-doc/) @@ -459,6 +459,7 @@ set (wsjt_FSRCS lib/jtmsg.f90 lib/libration.f90 lib/lorentzian.f90 + lib/fst4/lorentzian_fading.f90 lib/lpf1.f90 lib/mixlpf.f90 lib/makepings.f90 @@ -562,6 +563,7 @@ set (wsjt_FSRCS lib/fst4/ldpcsim240_74.f90 lib/fst4/osd240_101.f90 lib/fst4/osd240_74.f90 + lib/fst4/fastosd240_74.f90 lib/fst4/get_crc24.f90 lib/fst4/fst4_baseline.f90 ) @@ -838,7 +840,7 @@ endif () if (WIN32) set (Boost_USE_STATIC_LIBS OFF) endif () -find_package (Boost 1.63 REQUIRED COMPONENTS log_setup log) +find_package (Boost 1.62 REQUIRED COMPONENTS log_setup log) # # OpenMP @@ -1053,7 +1055,7 @@ query_qmake (QT_HOST_DATA QT_DATA_DIR) set (QT_MKSPECS_DIR ${QT_DATA_DIR}/mkspecs) # project definitions -add_definitions (-DQT5 -DCMAKE_BUILD -DBIGSYM=1) +add_definitions (-DQT5 -DCMAKE_BUILD -DBIGSYM=1 -DBOOST_ALL_DYN_LINK) if (CMAKE_HOST_UNIX) add_definitions (-DUNIX) elseif (CMAKE_HOST_WIN32) @@ -1062,7 +1064,6 @@ endif () # build a library of package functionality (without and optionally with OpenMP support) add_library (wsjt_cxx STATIC ${wsjt_CSRCS} ${wsjt_CXXSRCS}) -target_compile_definitions (wsjt_cxx PUBLIC BOOST_LOG_DYN_LINK) target_link_libraries (wsjt_cxx ${LIBM_LIBRARIES} Boost::log_setup ${LIBM_LIBRARIES}) # build an OpenMP variant of the Fortran library routines @@ -1310,7 +1311,7 @@ target_link_libraries (qcp Qt5::Widgets Qt5::PrintSupport) # build a library of package Qt functionality add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${wsjt_qt_GENUISRCS} ${GENAXSRCS}) # set wsjtx_udp exports to static variants -target_compile_definitions (wsjt_qt PUBLIC UDP_STATIC_DEFINE BOOST_LOG_DYN_LINK) +target_compile_definitions (wsjt_qt PUBLIC UDP_STATIC_DEFINE) target_link_libraries (wsjt_qt Boost::log qcp Qt5::Widgets Qt5::Network Qt5::Sql) target_include_directories (wsjt_qt BEFORE PRIVATE ${hamlib_INCLUDE_DIRS}) if (WIN32) @@ -1458,6 +1459,15 @@ generate_version_info (udp_daemon_VERSION_RESOURCES add_executable (udp_daemon UDPExamples/UDPDaemon.cpp ${udp_daemon_VERSION_RESOURCES}) target_link_libraries (udp_daemon wsjtx_udp-static) +generate_version_info (wsjtx_app_version_VERSION_RESOURCES + NAME wsjtx_app_version + BUNDLE ${PROJECT_BUNDLE_NAME} + ICON ${WSJTX_ICON_FILE} + FILE_DESCRIPTION "Display WSJT-X Application Version on console" + ) +add_executable (wsjtx_app_version AppVersion/AppVersion.cpp ${wsjtx_app_version_VERSION_RESOURCES}) +target_link_libraries (wsjtx_app_version wsjt_qt) + generate_version_info (message_aggregator_VERSION_RESOURCES NAME message_aggregator BUNDLE ${PROJECT_BUNDLE_NAME} @@ -1517,7 +1527,7 @@ install (TARGETS wsjtx # DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx # ) -install (TARGETS udp_daemon message_aggregator +install (TARGETS udp_daemon message_aggregator wsjtx_app_version RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ) @@ -1574,6 +1584,13 @@ install (FILES #COMPONENT runtime ) +install (DIRECTORY + example_log_configurations + DESTINATION ${CMAKE_INSTALL_DOCDIR} + FILES_MATCHING REGEX "^.*[^~]$" + #COMPONENT runtime + ) + # # Mac installer files # @@ -1853,11 +1870,11 @@ else () endif () set (CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE}") -set (CPACK_DEBIAN_PACKAGE_DEPENDS "libgfortran5 (>=8.3) | libgfortran4 (>=7.3) | libgfortran3 (>=6.3), libfftw3-single3 (>=3.3), libgomp1 (>=6), libqt5serialport5 (>=5.7), libqt5multimedia5-plugins (>=5.7), libqt5widgets5 (>=5.7), libqt5network5 (>=5.7), libqt5printsupport5 (>=5.7), libqt5sql5-sqlite (>=5.7), libusb-1.0-0 (>=1.0.21), libboost-log1.65.1 (>=1.62.0) | libboost-log1.65.1 (>=1.65.1) | libboost-log1.67.0 (>=1.67.0) | libboost-log1.71.0 (>=1.71.0)") +set (CPACK_DEBIAN_PACKAGE_DEPENDS "libgfortran5 (>=8.3) | libgfortran4 (>=7.3) | libgfortran3 (>=6.3), libfftw3-single3 (>=3.3), libgomp1 (>=6), libqt5serialport5 (>=5.7), libqt5multimedia5-plugins (>=5.7), libqt5widgets5 (>=5.7), libqt5network5 (>=5.7), libqt5printsupport5 (>=5.7), libqt5sql5-sqlite (>=5.7), libusb-1.0-0 (>=1.0.21), libboost-log1.62.0 (>=1.62.0) | libboost-log1.65.1 (>=1.65.1) | libboost-log1.67.0 (>=1.67.0) | libboost-log1.71.0 (>=1.71.0) | libboost-log1.74.0 (>=1.74.0)") set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) set (CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) -set (CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9, qt5-qtserialport >= 5.9, qt5-qtmultimedia >= 5.9, qt5-qtsvg >= 5.9, libusbx >= 1.0.22, libgfortran >= 7, libgomp >= 7, fftw-libs-single >= 3.3") +set (CPACK_RPM_PACKAGE_REQUIRES "qt5-qtbase >= 5.9, qt5-qtserialport >= 5.9, qt5-qtmultimedia >= 5.9, qt5-qtsvg >= 5.9, libusbx >= 1.0.22, libgfortran >= 7, libgomp >= 7, fftw-libs-single >= 3.3, boost-log >= 1.62") set (CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/share/pixmaps /usr/share/applications /usr/share/man /usr/share/man1) configure_file ("${PROJECT_SOURCE_DIR}/CMakeCPackOptions.cmake.in" diff --git a/Configuration.cpp b/Configuration.cpp index 98f3841cd..2b668f902 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -812,7 +812,7 @@ bool Configuration::is_dummy_rig () const bool Configuration::transceiver_online () { - LOG_TRACE ("transceiver_online: " << m_->cached_rig_state_); + LOG_TRACE (m_->cached_rig_state_); return m_->have_rig (); } @@ -823,37 +823,37 @@ int Configuration::transceiver_resolution () const void Configuration::transceiver_offline () { - LOG_TRACE ("transceiver_offline: " << m_->cached_rig_state_); + LOG_TRACE (m_->cached_rig_state_); m_->close_rig (); } void Configuration::transceiver_frequency (Frequency f) { - LOG_TRACE ("transceiver_frequency: " << f << m_->cached_rig_state_); + LOG_TRACE (f << ' ' << m_->cached_rig_state_); m_->transceiver_frequency (f); } void Configuration::transceiver_tx_frequency (Frequency f) { - LOG_TRACE ("transceiver_tx_frequency: " << f << m_->cached_rig_state_); + LOG_TRACE (f << ' ' << m_->cached_rig_state_); m_->transceiver_tx_frequency (f); } void Configuration::transceiver_mode (MODE mode) { - LOG_TRACE ("transceiver_mode: " << mode << " " << m_->cached_rig_state_); + LOG_TRACE (mode << ' ' << m_->cached_rig_state_); m_->transceiver_mode (mode); } void Configuration::transceiver_ptt (bool on) { - LOG_TRACE ("transceiver_ptt: " << on << " " << m_->cached_rig_state_); + LOG_TRACE (on << ' ' << m_->cached_rig_state_); m_->transceiver_ptt (on); } void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_split) { - LOG_TRACE ("sync_transceiver: force signal: " << force_signal << " enforce_mode_and_split: " << enforce_mode_and_split << " " << m_->cached_rig_state_); + LOG_TRACE ("force signal: " << force_signal << " enforce_mode_and_split: " << enforce_mode_and_split << ' ' << m_->cached_rig_state_); m_->sync_transceiver (force_signal); if (!enforce_mode_and_split) { @@ -1076,9 +1076,6 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv")); - // load the dictionary if it exists, fetch and load if it doesn't - lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text ()); - // // validation // @@ -1239,6 +1236,19 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network audio_output_device_ = next_audio_output_device_; audio_output_channel_ = next_audio_output_channel_; + bool fetch_if_needed {false}; + for (auto const& item : decode_highlighing_model_.items ()) + { + if (DecodeHighlightingModel::Highlight::LotW == item.type_) + { + fetch_if_needed = item.enabled_; + break; + } + } + // load the LoTW users dictionary if it exists, fetch and load if it + // doesn't and we need it + lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), fetch_if_needed); + transceiver_thread_ = new QThread {this}; transceiver_thread_->start (); } @@ -2828,7 +2838,7 @@ void Configuration::impl::sync_transceiver (bool /*force_signal*/) void Configuration::impl::handle_transceiver_update (TransceiverState const& state, unsigned sequence_number) { - LOG_TRACE ("handle_transceiver_update: Transceiver State #: " << sequence_number << " " << state); + LOG_TRACE ("#: " << sequence_number << ' ' << state); // only follow rig on some information, ignore other stuff cached_rig_state_.online (state.online ()); diff --git a/Darwin/ReadMe.txt b/Darwin/ReadMe.txt index 3adf32f21..78c092ca4 100644 --- a/Darwin/ReadMe.txt +++ b/Darwin/ReadMe.txt @@ -1,15 +1,33 @@ Notes on WSJT-X Installation for Mac OS X ----------------------------------------- +Important: If you are using the new Mac with the M1 chip then please read +the section marked: BEGIN M1. Otherwise BEGIN INTEL applies. + If you have already downloaded a previous version of WSJT-X then I suggest you change the name in the Applications folder from WSJT-X to WSJT-X_previous before proceeding. -If you have installed a previous version of WSJT-X before, then there is no -need to change anything on your system so proceed to NEXT. If you upgrade macOS -it is possible that you might need to re-install the sysctl.conf file. +I recommend that you follow the installation instructions especially if you +are moving from v2.2 to v2.3 of WSJT-X or you have upgraded macOS. -BEGIN: +BEGIN M1: + +Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. + +Now open a Terminal window by going to Applications->Utilities and clicking on Terminal. + +There are two system variables that must be set manually since the M1 Macs do not recognise +automatic parameter settings by means of the sysctl.conf file present in the download. +Type these commands - you will be asked for your password which will not be echoed: + + sudo sysctl -w kern.sysv.shmmax=104857600 + sudo sysctl -w kern.sysv.shmall=25600 + +It is important to note that these parameter settings will not survive a reboot. If you +need to reboot your Mac, then these commands must be re-entered. Now proceed to NEXT. + +BEGIN INTEL: Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site. @@ -18,7 +36,7 @@ Now open a Terminal window by going to Applications->Utilities and clicking on T Along with this ReadMe file there is a file: sysctl.conf which must be copied to a system area by typing this line in the Terminal window and then pressing the Return key. - sudo cp /Volumes/WSJT-X/sysctl.conf /etc + sudo cp /Volumes/WSJT-X/sysctl.conf /etc you will be asked for your normal password because authorisation is needed to copy this file. (Your password will not be echoed but press the Return key when completed.) @@ -26,9 +44,9 @@ Now re-boot your Mac. This is necessary to install the changes. After the reboot you should re-open the Terminal window as before and you can check that the change has been made by typing: - sysctl -a | grep sysv.shm + sysctl -a | grep sysv.shm -If shmmax is not shown as 14680064 then contact me since WSJT-X will fail to load with +If shmmax is not shown as 104857600 then contact me since WSJT-X will 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 @@ -77,23 +95,20 @@ Please email me if you have problems. --- John G4KLA (g4kla@rmnjmn.co.uk) -Addendum: Information about sysctl.conf and multiple instances of wsjt-x. +Addendum: Information about sysctl.conf 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 has to be increased. The sysctl.conf file is used for this purpose. You can use a Mac editor to examine sysctl.conf. (Do not use another editor - the file -would be probably be corrupted.) +would probably be corrupted.) -There are two important parameters that you need to consider. shmmax determines the -amount of shared memory that must be allocated for WSJT-X to operate. This is 14680064 (14MB) -and this is defined in the sysctl.conf file and should not be changed. +It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2 +Frequently asked Questions" in the User Guide. If you wish to run more than two instances +simultaneously, the sysctl.conf file needs to be modified. Please email me with your +requirements and I will provide a replacement sysctl.conf to suit. -It is possible to run more than one instance of WSJT-X simultaneously. See -"Section 16.2 Frequently asked Questions" in the User Guide. The second important parameter -shmall=17920 determines how many instances are permitted. This is calculated as: - (shmall x 4096/14680064) = 5. -The sysctl.conf file is configured to permit up to 5 instances of wsjtx to run simultaneously. -If this limitation is acceptable then you can continue to install the sysctl.conf file without making any -alterations. Otherwise you must edit the file to increase shmall according to this calculation. - +If two instances of WSJT-X are running, it is likely that you might need additional +audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device +which will allow you to specific 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. diff --git a/INSTALL b/INSTALL index c96e7d3b3..121572022 100644 --- a/INSTALL +++ b/INSTALL @@ -23,10 +23,10 @@ Building from Source ==================== On Linux systems some of the prerequisite libraries are available in -the mainstream distribution repositories. They are Qt v5 and FFTW v3. -For MS Windows see the section "Building from Source on MS Windows" -below. For Apple Mac see the section "Building from Source on Apple -Mac". +the mainstream distribution repositories. They are Qt v5, FFTW v3, and +the Boost C++ libraries. For MS Windows see the section "Building +from Source on MS Windows" below. For Apple Mac see the section +"Building from Source on Apple Mac". Qt v5, preferably v5.9 or later is required to build WSJT-X. @@ -43,12 +43,13 @@ the libfftw library development package. Normally installing the library development package pulls in all the FFTW v3 libraries including the single precision variant. -The Hamlib library optionally requires the libusb-1.0-1 library, if -the development version (libusb-1.0-0-dev) is available Hamlib will -configure its custom USB device back end drivers. Most rigs do not -require this so normally you can choose not to install libusb-1.0-dev -but if you have a SoftRock USB or similar SDR that uses a custom USB -interface then it is required. +The Hamlib library requires the readline development package and +optionally requires the libusb-1.0-1 library, if the development +version (libusb-1.0-0-dev) is available Hamlib will configure its +custom USB device back end drivers. Most rigs do not require this so +normally you can choose not to install libusb-1.0-dev but if you have +a SoftRock USB or similar SDR that uses a custom USB interface then it +is required. The Hamlib library is required. Currently WSJT-X needs to be built using a forked version of the Hamlib git master. This fork contains diff --git a/Logger.cpp b/Logger.cpp index 6c92ca407..e92c7aa2a 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -18,14 +18,13 @@ #include #include #include -#include #include #include #include - -#include +#include #include +namespace fs = boost::filesystem; namespace logging = boost::log; namespace srcs = logging::sources; namespace sinks = logging::sinks; @@ -129,7 +128,7 @@ namespace Logger CommonInitialization ci; } - void init_from_config (std::istream& stream) + void init_from_config (std::wistream& stream) { CommonInitialization ci; try @@ -153,24 +152,24 @@ namespace Logger logging::core::get ()->set_logging_enabled (false); } - void add_datafile_log (std::string const& log_file_name) + void add_datafile_log (std::wstring const& log_file_name) { // Create a text file sink - boost::shared_ptr backend + boost::shared_ptr backend ( - new sinks::text_ostream_backend() + new sinks::wtext_ostream_backend() ); - backend->add_stream (boost::shared_ptr (new std::ofstream (log_file_name))); + backend->add_stream (boost::shared_ptr (new fs::wofstream (log_file_name))); // Flush after each log record backend->auto_flush (true); // Create a sink for the backend - typedef sinks::synchronous_sink sink_t; + typedef sinks::synchronous_sink sink_t; boost::shared_ptr sink (new sink_t (backend)); // The log output formatter - sink->set_formatter (expr::format ("[%1%][%2%] %3%") + sink->set_formatter (expr::format (L"[%1%][%2%] %3%") % expr::attr ("TimeStamp") % logging::trivial::severity % expr::message diff --git a/Logger.hpp b/Logger.hpp index 6e29789e4..5d497943f 100644 --- a/Logger.hpp +++ b/Logger.hpp @@ -21,14 +21,14 @@ namespace Logger void init (); // define logger(s) and sinks from a configuration stream - void init_from_config (std::istream& config_stream); + void init_from_config (std::wistream& config_stream); // disable logging - useful for unit testing etc. void disable (); // add a new file sink for LOG_DATA_* for Severity >= INFO // this file sink will be used alongside any configured above - void add_data_file_log (std::string const& log_file_name); + void add_data_file_log (std::wstring const& log_file_name); } #define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \ diff --git a/NEWS b/NEWS index 3c78bb4c2..76fe7c528 100644 --- a/NEWS +++ b/NEWS @@ -10,7 +10,126 @@ \$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$ -Copyright 2001 - 2020 by Joe Taylor, K1JT. +Copyright 2001 - 2021 by Joe Taylor, K1JT. + + + Release: WSJT-X 2.3.0-rc3 + Jan 6, 2021 + ------------------------- + +WSJT-X 2.3.0 Release Candidate 3 adds an improved FST4W decoder and +fixes several defects and regressions discovered since the second +release candidate. + + - FST4W: Improve FST4W decoder sensitivity on fading channels and + decrease false decode rate. + + FST4W uses 50-bit messages and a 24-bit CRC. The 74-bit + message+CRC is encoded into a 240-bit codeword. Received messages + are decoded by two different decoders: (i) a “belief propagation” + (BP) decoder and (ii) an ordered statistics decoder (OSD). The + ordered statistics decoder has a knob that allows any or all CRC + bits to be treated as additional parity bits rather than as part of + the message+CRC field. Thus, the OSD decoder can decode the + received message as a (240,50+Nc) code, where Nc is any integer + between 0 and 24. In the RC1 and RC2 releases the OSD decoding + attempt treated the code as a (240,64) code (14-bit CRC). This + release uses 2 OSD decoding attempts that treat the received word + as (i) a (240,66) code with 16-bit CRC and code rate 0.308 and (ii) + a (240,50) code with no CRC and code rate 0.208. Codewords returned + by the (240,50) CRC-less decoding attempt are unpacked and the + decode is printed only if it contains a callsign/grid pair that + have been previously decoded by the belief propagation decoder + (which treats the code as a (240,74) code with 24-bit CRC) or the + ordered statistics decoder configured for (240,66) (16-bit + CRC). The callsign/grid memory is stored in file “fst4w_calls.txt” + which resides in the data directory. + + - FT8: Fixed a crash triggered by double clicking on the waterfall to + invoke a decode of a signal in the preceding T/R interval. + + - FST4W: Do not save .c2 files. + + - FST4W: Correct a bug that could cause incorrect operation when + using negative noise blanker (NB) percentage to trigger looping + over a range of NB percentages. + + - fst4sim: Added simulation of Lorentzian fading spectrum, invoked by + negative fspread values. + + - Color highlighting scheme window fixed in dark mode. + + - Reports sent by QSO partners to other stations no longer logged in + error. + + - UDP Status(1) message now includes the current Tx message. + + - Example diagnostic logging configuration files included. + + - Use system localization for date fields in Log QSO dialog. + + - Improvements to audio input and output buffer sizes. + + - wsprd: Fails gracefully if data directory does not exist. + + - wsjtx_app_version: new utility to print application version string. + + - Regression causing incorrect working frequency selection when + changing modes repaired. + + - Regression with QSO initiation with "Best S&P" repaired. + + - Updated installation instructions for macOS covering M1 hardware. + + - Improved compatibility is Debian 9 required distribution packages. + + - Repair regression with missing time-stamps in the ALL.TXT journal. + + - Allow hamlib_settings.json to work with PTT only configurations so + that optional PTT sharing on RTS or DTR can be enabled. + + - Several improvements to main window sizing and layout. + + - Repair regression with OpenSSL libraries being required when LoTW + highlighting is not enabled. + + - Repair a defect that caused 2 by 1 callsigns to be incorrectly + parsed as non-standard. + + - Several updates to international UI translations. + + + + Release: WSJT-X 2.3.0-rc2 + Nov 16, 2020 + ------------------------- + +WSJT-X 2.3.0 Release Candidate 2 fixes issues found in RC1 and +includes some new functionality that missed the RC1 cut off deadline. + + - Dropped audio samples message box removed, warnings and errors for + these are now sent to the WSJT-X system log. + + - FST4W spots to WSPRNet.org will be augmented such that the server + can distinguish the mode being spotted. Spots to WSPRNet.org will + no longer be restricted to WSPR sub-bands. + + - A new internal system and data logging facility used to provide + trace, debug, information, warning, error, and fatal error + messages. The verbosity and filtering of messages is user definable + via a configuration file. Without a configuration file a basic log + is written with information, warning and error messages only. Log + files are automatically rotated to limit disk usage. + + - Due to some users using inappropriate multicast IP addresses for + their interoperating severs the default behaviour now is to only + send multicast UDP datagrams to the loop-back network interface. + Users who require WSJT-X UDP Message Protocol datagrams to reach + other hosts will now have to configure WSJT-X to send on an + appropriate network interface, and use an appropriately scoped + multicast group address for their server applications. If you are + not sure then 224.0.0.1 (or ff02::1 if IPv6 is desired) is a safe + choice. Release: WSJT-X 2.3.0-rc1 diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 45d47f9b6..4374e8dc1 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -569,7 +569,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , bool watchdog_timeout, QString const& sub_mode , bool fast_mode, quint8 special_op_mode , quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name) + , QString const& configuration_name + , QString const& tx_message) { if (m_->server_port_ && !m_->server_.isNull ()) { @@ -578,8 +579,9 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () - << fast_mode << special_op_mode << frequency_tolerance << tr_period << configuration_name.toUtf8 (); - TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "frequency tolerance:" << frequency_tolerance << "T/R period:" << tr_period << "configuration name:" << configuration_name); + << fast_mode << special_op_mode << frequency_tolerance << tr_period << configuration_name.toUtf8 () + << tx_message.toUtf8 (); + TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "frequency tolerance:" << frequency_tolerance << "T/R period:" << tr_period << "configuration name:" << configuration_name << "Tx message:" << tx_message); m_->send_message (out, message); } } diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index cc348be2d..3f21a598a 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -63,7 +63,8 @@ public: , quint32 rx_df, quint32 tx_df, QString const& de_call, QString const& de_grid , QString const& dx_grid, bool watchdog_timeout, QString const& sub_mode , bool fast_mode, quint8 special_op_mode, quint32 frequency_tolerance - , quint32 tr_period, QString const& configuration_name); + , quint32 tr_period, QString const& configuration_name + , QString const& tx_message); Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence , bool off_air); diff --git a/Network/NetworkMessage.hpp b/Network/NetworkMessage.hpp index f892eda06..61aaf7038 100644 --- a/Network/NetworkMessage.hpp +++ b/Network/NetworkMessage.hpp @@ -160,6 +160,7 @@ * Frequency Tolerance quint32 * T/R Period quint32 * Configuration Name utf8 + * Tx Message utf8 * * WSJT-X sends this status message when various internal state * changes to allow the server to track the relevant state of each @@ -183,7 +184,8 @@ * when the Tx watchdog is set or reset, * when the frequency tolerance is changed, * when the T/R period is changed, - * when the configuration name changes. + * when the configuration name changes, + * when the message being transmitted changes. * * The Special operation mode is an enumeration that indicates the * setting selected in the WSJT-X "Settings->Advanced->Special diff --git a/Radio.cpp b/Radio.cpp index 56b943739..79b332fbd 100644 --- a/Radio.cpp +++ b/Radio.cpp @@ -22,7 +22,7 @@ namespace Radio QRegularExpression valid_callsign_regexp {R"(\d[[:alpha:]]|[[:alpha:]]\d)"}; // standard callsign - QRegularExpression strict_standard_callsign_re {R"(^([A-Z][0-9]?|[0-9][A-Z])[0-9][A-Z]{0,3}$)"}; + QRegularExpression strict_standard_callsign_re {R"(^([A-Z][0-9]?|[0-9A-Z][A-Z])[0-9][A-Z]{0,3}$)"}; // suffixes that are often used and should not be interpreted as a // DXCC Entity prefix used as a suffix diff --git a/Release_Notes.txt b/Release_Notes.txt index 793cb905a..b091f6973 100644 --- a/Release_Notes.txt +++ b/Release_Notes.txt @@ -10,7 +10,94 @@ -Copyright 2001 - 2020 by Joe Taylor, K1JT. +Copyright 2001 - 2021 by Joe Taylor, K1JT. + + + Release: WSJT-X 2.3.0-rc3 + Jan 6, 2021 + ------------------------- + +WSJT-X 2.3.0 Release Candidate 3 adds an improved FST4W decoder and +fixes several defects and regressions discovered since the second +release candidate. + + - FST4W: Improve FST4W decoder sensitivity on fading channels and + decrease false decode rate. + + FST4W uses 50-bit messages and a 24-bit CRC. The 74-bit + message+CRC is encoded into a 240-bit codeword. Received messages + are decoded by two different decoders: (i) a “belief propagation” + (BP) decoder and (ii) an ordered statistics decoder (OSD). The + ordered statistics decoder has a knob that allows any or all CRC + bits to be treated as additional parity bits rather than as part of + the message+CRC field. Thus, the OSD decoder can decode the + received message as a (240,50+Nc) code, where Nc is any integer + between 0 and 24. In the RC1 and RC2 releases the OSD decoding + attempt treated the code as a (240,64) code (14-bit CRC). This + release uses 2 OSD decoding attempts that treat the received word + as (i) a (240,66) code with 16-bit CRC and code rate 0.308 and (ii) + a (240,50) code with no CRC and code rate 0.208. Codewords returned + by the (240,50) CRC-less decoding attempt are unpacked and the + decode is printed only if it contains a callsign/grid pair that + have been previously decoded by the belief propagation decoder + (which treats the code as a (240,74) code with 24-bit CRC) or the + ordered statistics decoder configured for (240,66) (16-bit + CRC). The callsign/grid memory is stored in file “fst4w_calls.txt” + which resides in the data directory. + + - FT8: Fixed a crash triggered by double clicking on the waterfall to + invoke a decode of a signal in the preceding T/R interval. + + - FST4W: Do not save .c2 files. + + - FST4W: Correct a bug that could cause incorrect operation when + using negative noise blanker (NB) percentage to trigger looping + over a range of NB percentages. + + - fst4sim: Added simulation of Lorentzian fading spectrum, invoked by + negative fspread values. + + - Color highlighting scheme window fixed in dark mode. + + - Reports sent by QSO partners to other stations no longer logged in + error. + + - UDP Status(1) message now includes the current Tx message. + + - Example diagnostic logging configuration files included. + + - Use system localization for date fields in Log QSO dialog. + + - Improvements to audio input and output buffer sizes. + + - wsprd: Fails gracefully if data directory does not exist. + + - wsjtx_app_version: new utility to print application version string. + + - Regression causing incorrect working frequency selection when + changing modes repaired. + + - Regression with QSO initiation with "Best S&P" repaired. + + - Updated installation instructions for macOS covering M1 hardware. + + - Improved compatibility is Debian 9 required distribution packages. + + - Repair regression with missing time-stamps in the ALL.TXT journal. + + - Allow hamlib_settings.json to work with PTT only configurations so + that optional PTT sharing on RTS or DTR can be enabled. + + - Several improvements to main window sizing and layout. + + - Repair regression with OpenSSL libraries being required when LoTW + highlighting is not enabled. + + - Repair a defect that caused 2 by 1 callsigns to be incorrectly + parsed as non-standard. + + - Several updates to international UI translations. + Release: WSJT-X 2.3.0-rc2 @@ -45,6 +132,7 @@ includes some new functionality that missed the RC1 cut off deadline. choice. + Release: WSJT-X 2.3.0-rc1 Sept 28, 2020 ------------------------- diff --git a/Transceiver/HamlibTransceiver.cpp b/Transceiver/HamlibTransceiver.cpp index 67fc36dc3..13b08ed6f 100644 --- a/Transceiver/HamlibTransceiver.cpp +++ b/Transceiver/HamlibTransceiver.cpp @@ -259,53 +259,53 @@ HamlibTransceiver::HamlibTransceiver (logger_type * logger, // rig_->state.obj = this; - if (!is_dummy_) + // + // user defined Hamlib settings + // + auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation + , "hamlib_settings.json"); + if (!settings_file_name.isEmpty ()) { - // - // user defined Hamlib settings - // - auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation - , "hamlib_settings.json"); - if (!settings_file_name.isEmpty ()) + QFile settings_file {settings_file_name}; + qDebug () << "Using Hamlib settings file:" << settings_file_name; + if (settings_file.open (QFile::ReadOnly)) { - QFile settings_file {settings_file_name}; - qDebug () << "Using Hamlib settings file:" << settings_file_name; - if (settings_file.open (QFile::ReadOnly)) + QJsonParseError status; + auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status); + if (status.error) { - QJsonParseError status; - auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status); - if (status.error) - { - throw error {tr ("Hamlib settings file error: %1 at character offset %2") - .arg (status.errorString ()).arg (status.offset)}; - } - qDebug () << "Hamlib settings JSON:" << settings_doc.toJson (); - if (!settings_doc.isObject ()) - { - throw error {tr ("Hamlib settings file error: top level must be a JSON object")}; - } - auto const& settings = settings_doc.object (); + throw error {tr ("Hamlib settings file error: %1 at character offset %2") + .arg (status.errorString ()).arg (status.offset)}; + } + qDebug () << "Hamlib settings JSON:" << settings_doc.toJson (); + if (!settings_doc.isObject ()) + { + throw error {tr ("Hamlib settings file error: top level must be a JSON object")}; + } + auto const& settings = settings_doc.object (); - // - // configuration settings - // - auto const& config = settings["config"]; - if (!config.isUndefined ()) + // + // configuration settings + // + auto const& config = settings["config"]; + if (!config.isUndefined ()) + { + if (!config.isObject ()) { - if (!config.isObject ()) - { - throw error {tr ("Hamlib settings file error: config must be a JSON object")}; - } - auto const& config_list = config.toObject (); - for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item) - { - set_conf (item.key ().toLocal8Bit ().constData () - , (*item).toVariant ().toString ().toLocal8Bit ().constData ()); - } + throw error {tr ("Hamlib settings file error: config must be a JSON object")}; + } + auto const& config_list = config.toObject (); + for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item) + { + set_conf (item.key ().toLocal8Bit ().constData () + , (*item).toVariant ().toString ().toLocal8Bit ().constData ()); } } } + } + if (!is_dummy_) + { switch (rig_->caps->port_type) { case RIG_PORT_SERIAL: diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 3be8c788c..b82836f04 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include "validators/MaidenheadLocatorValidator.hpp" @@ -73,7 +72,7 @@ bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row , QModelIndex const& source_parent) const { auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent); - return sourceModel ()->data (source_index_col0).value () == key_; + return sourceModel ()->data (source_index_col0, Qt::UserRole + 1).value () == key_; } void ClientWidget::IdFilterModel::de_call (QString const& call) @@ -148,6 +147,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod , mode_line_edit_ {new QLineEdit {this}} , frequency_tolerance_spin_box_ {new QSpinBox {this}} , tx_mode_label_ {new QLabel {this}} + , tx_message_label_ {new QLabel {this}} , submode_line_edit_ {new QLineEdit {this}} , fast_mode_check_box_ {new QCheckBox {this}} , tr_period_spin_box_ {new QSpinBox {this}} @@ -303,6 +303,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // set up status area status_bar_->addPermanentWidget (de_label_); status_bar_->addPermanentWidget (tx_mode_label_); + status_bar_->addPermanentWidget (tx_message_label_); status_bar_->addPermanentWidget (frequency_label_); status_bar_->addPermanentWidget (tx_df_label_); status_bar_->addPermanentWidget (report_label_); @@ -401,7 +402,7 @@ void ClientWidget::update_status (ClientKey const& key, Frequency f, QString con , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& submode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name) + , QString const& configuration_name, QString const& tx_message) { if (key == key_) { @@ -428,8 +429,8 @@ void ClientWidget::update_status (ClientKey const& key, Frequency f, QString con update_spin_box (frequency_tolerance_spin_box_, frequency_tolerance , quint32_max == frequency_tolerance ? QString {"n/a"} : QString {}); update_line_edit (submode_line_edit_, submode, false); - tx_mode_label_->setText (QString {"Tx Mode: %1"} - .arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')')); + tx_mode_label_->setText (tx_mode.isEmpty () || tx_mode == mode ? "" : "Tx Mode: (" + tx_mode + ')'); + tx_message_label_->setText (tx_message.isEmpty () ? "" : "Tx Msg: " + tx_message.trimmed ()); frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f)); update_line_edit (dx_call_line_edit_, dx_call); update_line_edit (dx_grid_line_edit_, dx_grid); diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index ee91d084a..fb0ef47f4 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -52,7 +52,7 @@ public: , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name); + , QString const& configuration_name, QString const& tx_message); Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); @@ -122,6 +122,7 @@ private: QLineEdit * mode_line_edit_; QSpinBox * frequency_tolerance_spin_box_; QLabel * tx_mode_label_; + QLabel * tx_message_label_; QLineEdit * submode_line_edit_; QCheckBox * fast_mode_check_box_; QSpinBox * tr_period_spin_box_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 8aadd08a6..74090395b 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -243,9 +243,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s quint32 frequency_tolerance {quint32_max}; quint32 tr_period {quint32_max}; QByteArray configuration_name; + QByteArray tx_message; in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode - >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name; + >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name + >> tx_message; if (check_status (in) != Fail) { Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) @@ -256,7 +258,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s , QString::fromUtf8 (dx_grid), watchdog_timeout , QString::fromUtf8 (sub_mode), fast_mode , special_op_mode, frequency_tolerance, tr_period - , QString::fromUtf8 (configuration_name)); + , QString::fromUtf8 (configuration_name) + , QString::fromUtf8 (tx_message)); } } break; diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 7cf5653a0..c18cc95fd 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -97,7 +97,7 @@ public: , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period - , QString const& configuration_name); + , QString const& configuration_name, QString const& tx_message); Q_SIGNAL void client_closed (ClientKey const&); Q_SIGNAL void decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2d028f074..1d3a7abef 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -59,7 +59,7 @@ public: , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/ , quint8 /*special_op_mode*/, quint32 /*frequency_tolerance*/, quint32 /*tr_period*/ - , QString const& /*configuration_name*/) + , QString const& /*configuration_name*/, QString const& /*tx_message*/) { if (key == key_) { diff --git a/WSJTXLogging.cpp b/WSJTXLogging.cpp index 76adf81b0..e0ba871bd 100644 --- a/WSJTXLogging.cpp +++ b/WSJTXLogging.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include #include +#include #include #include #include @@ -35,7 +35,7 @@ namespace trivial = logging::trivial; namespace keywords = logging::keywords; namespace expr = logging::expressions; namespace sinks = logging::sinks; -namespace ptime = boost::posix_time; +namespace posix_time = boost::posix_time; namespace gregorian = boost::gregorian; namespace container = boost::container; @@ -60,12 +60,62 @@ namespace //throw; } }; + + // Reroute Qt messages to the system logger + void qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg) + { + // Convert Qt message types to logger severities + auto severity = trivial::trace; + switch (type) + { + case QtDebugMsg: severity = trivial::debug; break; + case QtInfoMsg: severity = trivial::info; break; + case QtWarningMsg: severity = trivial::warning; break; + case QtCriticalMsg: severity = trivial::error; break; + case QtFatalMsg: severity = trivial::fatal; break; + } + // Map non-default Qt categories to logger channels, Qt logger + // context is mapped to the appropriate logger attributes. + auto log = sys::get (); + std::string file; + std::string function; + if (context.file) + { + file = context.file; + } + if (context.function) + { + function = context.function; + } + if (!context.category || !qstrcmp (context.category, "default")) + { + BOOST_LOG_SEV (log, severity) + << boost::log::add_value ("Line", context.line) + << boost::log::add_value ("File", file) + << boost::log::add_value ("Function", function) + << msg.toStdWString (); + } + else + { + BOOST_LOG_SEV (log, severity) + << boost::log::add_value ("Line", context.line) + << boost::log::add_value ("File", file) + << boost::log::add_value ("Function", function) + << context.category << ": " << msg.toStdWString (); + } + if (QtFatalMsg == type) + { + // bail out + throw std::runtime_error {"Fatal Qt Error"}; + } + } } WSJTXLogging::WSJTXLogging () { + auto core = logging::core::get (); // Catch relevant exceptions from logging. - logging::core::get ()->set_exception_handler + core->set_exception_handler ( logging::make_exception_handler (exception_handler {}) ); @@ -105,8 +155,8 @@ WSJTXLogging::WSJTXLogging () pos = match.capturedEnd (0); } new_config += config.mid (pos); - std::stringbuf buffer {new_config.toStdString (), std::ios_base::in}; - std::istream stream {&buffer}; + std::wstringbuf buffer {new_config.toStdWString (), std::ios_base::in}; + std::wistream stream {&buffer}; Logger::init_from_config (stream); LOG_INFO ("Read logging configuration file: " << log_config.fileName ()); } @@ -120,7 +170,6 @@ WSJTXLogging::WSJTXLogging () // Default log file location. QDir app_data {QStandardPaths::writableLocation (QStandardPaths::AppLocalDataLocation)}; Logger::init (); // Basic setup of attributes - auto core = logging::core::get (); // // Sink intended for general use that passes everything above @@ -131,7 +180,7 @@ WSJTXLogging::WSJTXLogging () ( keywords::auto_flush = false #if BOOST_VERSION / 100 >= 1070 - , keywords::file_name = app_data.absoluteFilePath ("wsjtx_syslog.log").toStdString () + , keywords::file_name = app_data.absoluteFilePath ("wsjtx_syslog.log").toStdWString () , keywords::target_file_name = #else , keywords::file_name = @@ -139,7 +188,9 @@ WSJTXLogging::WSJTXLogging () app_data.absoluteFilePath ("logs/wsjtx_syslog_%Y-%m.log").toStdString () , keywords::time_based_rotation = sinks::file::rotation_at_time_point (gregorian::greg_day (1), 0, 0, 0) , keywords::open_mode = std::ios_base::out | std::ios_base::app +#if BOOST_VERSION / 100 >= 1063 , keywords::enable_final_rotation = false +#endif ); sys_sink->locked_backend ()->set_file_collector @@ -149,7 +200,7 @@ WSJTXLogging::WSJTXLogging () keywords::max_size = 40 * 1024 * 1024 , keywords::min_free_space = 1024 * 1024 * 1024 , keywords::max_files = 12 - , keywords::target = app_data.absoluteFilePath ("logs").toStdString () + , keywords::target = app_data.absoluteFilePath ("logs").toStdWString () ) ); sys_sink->locked_backend ()->scan_for_files (); @@ -166,77 +217,24 @@ WSJTXLogging::WSJTXLogging () ( expr::stream << "[" << channel - << "][" << expr::format_date_time ("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") - << "][" << expr::format_date_time ("Uptime", "%O:%M:%S.%f") + << "][" << expr::format_date_time ("TimeStamp", "%Y-%m-%d %H:%M:%S.%f") + << "][" << expr::format_date_time ("Uptime", "%O:%M:%S.%f") << "][" << trivial::severity << "] " << expr::message ); core->add_sink (sys_sink); - -#if !defined (NDEBUG) && defined (Q_OS_WIN) - // auto windbg_sink = boost::make_shared> (); - // windbg_sink->set_filter (trivial::severity >= trivial::trace && expr::is_debugger_present ()); - // core->add_sink (windbg_sink); -#endif } + // Indicate start of logging LOG_INFO ("Log Start"); + ::qInstallMessageHandler (&qt_log_handler); } WSJTXLogging::~WSJTXLogging () { LOG_INFO ("Log Finish"); - auto lg = logging::core::get (); - lg->flush (); - lg->remove_all_sinks (); -} - -// Reroute Qt messages to the system logger -void WSJTXLogging::qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg) -{ - // Convert Qt message types to logger severities - auto severity = trivial::trace; - switch (type) - { - case QtDebugMsg: severity = trivial::debug; break; - case QtInfoMsg: severity = trivial::info; break; - case QtWarningMsg: severity = trivial::warning; break; - case QtCriticalMsg: severity = trivial::error; break; - case QtFatalMsg: severity = trivial::fatal; break; - } - // Map non-default Qt categories to logger channels, Qt logger - // context is mapped to the appropriate logger attributes. - auto log = sys::get (); - std::string file; - std::string function; - if (context.file) - { - file = context.file; - } - if (context.function) - { - function = context.function; - } - if (!context.category || !qstrcmp (context.category, "default")) - { - BOOST_LOG_SEV (log, severity) - << boost::log::add_value ("Line", context.line) - << boost::log::add_value ("File", file) - << boost::log::add_value ("Function", function) - << msg.toStdString (); - } - else - { - BOOST_LOG_CHANNEL_SEV (log, std::string {context.category}, severity) - << boost::log::add_value ("Line", context.line) - << boost::log::add_value ("File", file) - << boost::log::add_value ("Function", function) - << msg.toStdString (); - } - if (QtFatalMsg == type) - { - // bail out - throw std::runtime_error {"Fatal Qt Error"}; - } + auto core = logging::core::get (); + core->flush (); + core->remove_all_sinks (); } diff --git a/WSJTXLogging.hpp b/WSJTXLogging.hpp index d36e9afd2..4ecedbf78 100644 --- a/WSJTXLogging.hpp +++ b/WSJTXLogging.hpp @@ -1,10 +1,6 @@ #ifndef WSJTX_LOGGING_HPP__ #define WSJTX_LOGGING_HPP__ -#include - -class QString; - // // Class WSJTXLogging - wraps application specific logging // @@ -13,14 +9,6 @@ class WSJTXLogging final public: explicit WSJTXLogging (); ~WSJTXLogging (); - - // - // Install this as the Qt message handler (qInstallMessageHandler) - // to integrate Qt messages. This handler can be installed at any - // time, it does not rely on an instance of WSJTXLogging existing, - // so logging occurring before the logging sinks, filters, and - // formatters, etc, are established can take place. - static void qt_log_handler (QtMsgType type, QMessageLogContext const& context, QString const&); }; #endif diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 9b48ced82..40d8b27fd 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -197,7 +197,7 @@ function (document) -a data-uri! -a VERSION_MAJOR=${WSJTX_VERSION_MAJOR} -a VERSION_MINOR=${WSJTX_VERSION_MINOR} - -a VERSION_PATCH=${WSJTX_VERSION_PATCH} + -a VERSION_PATCH=${WSJTX_VERSION_PATCH}${BUILD_TYPE_REVISION} -a VERSION=${wsjtx_VERSION} -D ${CMAKE_CURRENT_BINARY_DIR} -o ${_docbook_file} ${_source_name} diff --git a/doc/building on MS Windows.txt b/doc/building on MS Windows.txt index 9e954285c..42ea8d0e5 100644 --- a/doc/building on MS Windows.txt +++ b/doc/building on MS Windows.txt @@ -43,7 +43,7 @@ CMake ----- Download and install a recent version from the official CMake web -site. A default installation is fine. I am currently using v3.18.3, +site. A default installation is fine. I am currently using v3.18.4, versions as old as v3.9 should work. Other tools and libraries without installers @@ -59,8 +59,10 @@ FFTW v3 DFT library ------------------- The MS Windows builds of FFTW3 can be downloaded from -http://www.fftw.org/install/windows.html and unzipped into C:\Tools. -You only need the 64-bit package. +http://www.fftw.org/install/windows.html. The ZIP archives for this +package have no directory structure so create a directory under C:\ +Tools\ called fftw-3.3.5-dll64 and unzip the archive there. You only +need the 64-bit package. libusb library -------------- diff --git a/doc/building-Boost-libs.txt b/doc/building-Boost-libs.txt index 8f913a90a..f45b3ceec 100644 --- a/doc/building-Boost-libs.txt +++ b/doc/building-Boost-libs.txt @@ -82,12 +82,12 @@ Common steps Download and extract the latest Boost library sources, at the time of writing that was https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.7z -. Extract to some convenient location, I use %HOME%\src . +. Extract to some convenient location, I use %USERPROFILE%\src . Download and extract the libbacktrace sources from https://github.com/ianlancetaylor/libbacktrace as follows. -cd %HOME%\src +cd %USERPROFILE%\src mkdir github.com cd github.com mkdir ianlancetaylor @@ -101,8 +101,8 @@ names are unique per architecture and tool-chain. This saves a lot of space as the boost header files are quite big, and there's no need to install multiple copies. -Create a new file %HOME%\src\boost_1_74_0\project-config.jam with the -following three lines to specify how Boost.Build finds the +Create a new file %USERPROFILE%\src\boost_1_74_0\project-config.jam +with the following three lines to specify how Boost.Build finds the libbacktrace library matched to your relevant C++ compliers: import toolset ; @@ -133,13 +133,15 @@ tool-chain bundled with your Qt binary installation. Verify the correct compiler is in the PATH. i.e. it identifies (g++ --version) as i686-posix-dwarf-rev0. -cd %HOME%\src\boost_1_74_0\tools\build +cd %USERPROFILE%\src\boost_1_74_0\tools\build bootstrap.bat mingw .\b2 --prefix=C:\Tools\boost-build\MinGW32 install cd ..\.. C:\Tools\boost-build\MinGW32\bin\b2 -j8 toolset=gcc ^ - --build-dir=%HOME%\build\boost ^ - --build-type=complete --prefix=C:\Tools\boost install + --build-dir=%USERPROFILE%\build\boost ^ + address-model=32 architecture=x86 variant=debug,release ^ + link=shared threading=multi ^ + --with-log --with-stacktrace --prefix=C:\Tools\boost install If all is well you should see the following line about a 1/3 of the way through the initial configuration steps. @@ -156,7 +158,7 @@ warnings can usually be ignored. If successful; you can release some space by cleaning the build tree: C:\Tools\boost-build\MinGW32\bin\b2 toolset=gcc ^ - --build-dir=%HOME%\build\boost ^ + --build-dir=%USERPROFILE%\build\boost ^ --build-type=complete clean 64-bit @@ -179,13 +181,16 @@ compilers and the project-config.jam file you created above. With a v7 gcc-8~64. My example matches my 64-bit Qt v5.15.0 with the bundled MinGW64 v8.1.0. -cd %HOME%\src\boost_1_74_0\tools\build -bootstrap.bat +cd %USERPROFILE%\src\boost_1_74_0\tools\build +bootstrap.bat mingw .\b2 --prefix=C:\Tools\boost-build\MinGW64 install cd ..\.. C:\Tools\boost-build\MinGW64\bin\b2 -j8 toolset=gcc-8~64 ^ - address-model=64 --build-dir=%HOME%\build\boost ^ - --build-type=complete --prefix=C:\Tools\boost install + address-model=64 architecture=x86 variant=debug,release ^ + link=shared threading=multi ^ + --with-log --with-stacktrace ^ + --build-dir=%USERPROFILE%\build\boost ^ + --prefix=C:\Tools\boost install If all is well you should see the following line about a 1/3 of the way through the initial configuration steps. @@ -202,9 +207,8 @@ warnings can usually be ignored. If successful; you can release some space by cleaning the build tree: C:\Tools\boost-build\MinGW32\bin\b2 toolset=gcc-8~64 ^ - address-model=64 --build-dir=%HOME%\build\boost ^ + address-model=64 --build-dir=%USERPROFILE%\build\boost ^ --build-type=complete clean - Run-time Environment -------------------- @@ -226,15 +230,12 @@ configuration tool-chain file: # ... set (BOOSTDIR C:/Tools/boost) -set (QTDIR C:/Qt/5.12.9/mingw73_32) -# set (QTDIR C:/Qt/5.15.0/mingw81_32) +set (QTDIR C:/Qt/5.15.2/mingw81_32) set (FFTWDIR C:/Tools/fftw-3.3.5-dll32) set (HAMLIBDIR C:/test-install/hamlib/mingw32/debug) set (LIBUSBDIR C:/Tools/libusb-1.0.23) -set (PYTHONDIR C:/Python27) -set (ASCIIDOCDIR C:/Tools/asciidoc-master) # where to find required packages -set (CMAKE_PREFIX_PATH ${BOOSTDIR} ${QTDIR} ${FFTWDIR} ${HAMLIBDIR} ${HAMLIBDIR}/bin ${LIBUSBDIR} ${PYTHONDIR} ${ASCIIDOCDIR}) +set (CMAKE_PREFIX_PATH ${BOOSTDIR} ${QTDIR} ${FFTWDIR} ${HAMLIBDIR} ${HAMLIBDIR}/bin ${LIBUSBDIR}) # ... diff --git a/doc/user_guide/en/install-linux.adoc b/doc/user_guide/en/install-linux.adoc index bbd53b2b9..ff108ef34 100644 --- a/doc/user_guide/en/install-linux.adoc +++ b/doc/user_guide/en/install-linux.adoc @@ -43,7 +43,8 @@ You may also need to execute the following command in a terminal: .... sudo apt install libgfortran5 libqt5widgets5 libqt5network5 \ libqt5printsupport5 libqt5multimedia5-plugins libqt5serialport5 \ - libqt5sql5-sqlite libfftw3-single3 libgomp1 libusb-1.0-0 + libqt5sql5-sqlite libfftw3-single3 libgomp1 libboost-all-dev \ + libusb-1.0-0 .... Fedora, CentOS, Red Hat, and other rpm-based systems: @@ -75,5 +76,5 @@ You may also need to execute the following command in a terminal: .... sudo dnf install libgfortran fftw-libs-single qt5-qtbase \ qt5-qtmultimedia qt5-qtserialport qt5-qtsvg \ - qt5-qtserialport libgomp libusbx + qt5-qtserialport libgomp boost libusbx .... diff --git a/example_log_configurations/README b/example_log_configurations/README new file mode 100644 index 000000000..d7ed52f40 --- /dev/null +++ b/example_log_configurations/README @@ -0,0 +1,5 @@ +Example WSJT-X Logging Configuration Files +========================================== + +Here you will find some typical loggin configuration files. Pick a +suitable one and copy it to the WSJT-X log files directory. diff --git a/example_log_configurations/wsjtx_log_config.ini.console b/example_log_configurations/wsjtx_log_config.ini.console new file mode 100644 index 000000000..a1076b788 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.console @@ -0,0 +1,14 @@ +# +# Example logging confguration file to send records to the console terminal +# + +[Core] +# Set DisableLogging to true to disable all logging. +DisableLogging="false" + +[Sinks.Console] +Destination="Console" +Asynchronous="false" +AutoFlush="true" +Format="[%TimeStamp(format=\"%H:%M:%S.%f\")%][%Channel%:%Severity%] %Message%" +Filter="(%Channel% matches \"SYSLOG\" & %Severity% >= trace) | (%Channel% matches \"RIGCTRL\" & %Severity% >= info)" \ No newline at end of file diff --git a/example_log_configurations/wsjtx_log_config.ini.debugger b/example_log_configurations/wsjtx_log_config.ini.debugger new file mode 100644 index 000000000..71056aee5 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.debugger @@ -0,0 +1,15 @@ +# +# Example WSJT-X logging configuration for sending records to the +# attached Windows debugger (e.g. gdb) +# + +[Core] +# Set DisableLogging to true to disable all logging. +DisableLogging="false" + +[Sinks.Debugger] +Destination="Debugger" +Asynchronous="false" +AutoFlush="true" +Format="[%TimeStamp(format=\"%H:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" +Filter="(%Channel% matches \"SYSLOG\" & %Severity% >= debug) | (%Channel% matches \"RIGCTRL\" & %Severity% >= info)" \ No newline at end of file diff --git a/example_log_configurations/wsjtx_log_config.ini.rig_control b/example_log_configurations/wsjtx_log_config.ini.rig_control new file mode 100644 index 000000000..0bcb82066 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.rig_control @@ -0,0 +1,25 @@ +[Sinks.SYSLOG] +Destination=TextFile +Asynchronous=true +AutoFlush=false +FileName="${AppLocalDataLocation}/wsjtx_syslog.log" +TargetFileName="${AppLocalDataLocation}/logs/wsjtx_syslog_%Y-%m.log" +RotationTimePoint="01 00:00:00" +Append=true +EnableFinalRotation=false +MaxSize=41943040 +MinFreeSpace=1073741824 +MaxFiles=12 +Target="${AppLocalDataLocation}/logs" +ScanForFiles="Matching" +Format="[%Channel%][%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %Message%" +Filter="%Severity% >= info" + +[Sinks.RIGCTRL] +Destination=TextFile +Asynchronous=true +AutoFlush=true +FileName="${DesktopLocation}/WSJT-X_RigControl.log" +Append=true +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%:%Severity%] %Message%" +Filter="%Channel% matches \"RIGCTRL\" | %Severity% >= info" diff --git a/example_log_configurations/wsjtx_log_config.ini.simple_verbose b/example_log_configurations/wsjtx_log_config.ini.simple_verbose new file mode 100644 index 000000000..26047ebb0 --- /dev/null +++ b/example_log_configurations/wsjtx_log_config.ini.simple_verbose @@ -0,0 +1,14 @@ +[Sinks.SYSLOG] +Destination="TextFile" +Asynchronous="true" +AutoFlush="true" +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" +RotationTimePoint="11:42:00" +Target="${AppLocalDataLocation}/logs" +FileName="${AppLocalDataLocation}/wsjtx_syslog.log" +TargetFileName="${AppLocalDataLocation}/logs/wsjtx_syslog_%Y-%m_%3N.log" +Append="true" +EnableFinalRotation="false" +ScanForFiles="Matching" +MaxSize=1073741824 +MaxFiles="10" diff --git a/lib/fst4/decode240_74.f90 b/lib/fst4/decode240_74.f90 index be18f6e09..f5aac2e10 100644 --- a/lib/fst4/decode240_74.f90 +++ b/lib/fst4/decode240_74.f90 @@ -25,6 +25,8 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder include "ldpc_240_74_parity.f90" maxiterations=30 + if(Keff.eq.50) maxiterations=1 + nosd=0 if(maxosd.gt.3) maxosd=3 if(maxosd.eq.0) then ! osd with channel llrs @@ -36,6 +38,8 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder nosd=0 endif + if(maxosd.eq.0) goto 73 + toc=0 tov=0 tanhtoc=0 @@ -133,9 +137,11 @@ subroutine decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw,ntype,nharder enddo ! bp iterations +73 continue do i=1,nosd zn=zsave(:,i) - call osd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) +! call osd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) + call fastosd240_74(zn,Keff,apmask,norder,message74,cw,nharderror,dminosd) if(nharderror.gt.0) then hdec=0 where(llr .ge. 0) hdec=1 diff --git a/lib/fst4/fastosd240_74.f90 b/lib/fst4/fastosd240_74.f90 new file mode 100644 index 000000000..f4bb61d60 --- /dev/null +++ b/lib/fst4/fastosd240_74.f90 @@ -0,0 +1,291 @@ +subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin) +! +! An ordered-statistics decoder for the (240,74) code. +! Message payload is 50 bits. Any or all of a 24-bit CRC can be +! used for detecting incorrect codewords. The remaining CRC bits are +! cascaded with the LDPC code for the purpose of improving the +! distance spectrum of the code. +! +! If p1 (0.le.p1.le.24) is the number of CRC24 bits that are +! to be used for bad codeword detection, then the argument k should +! be set to 77+p1. +! +! Valid values for k are in the range [50,74]. +! + character*24 c24 + integer, parameter:: N=240 + integer*1 apmask(N),apmaskr(N) + integer*1, allocatable, save :: gen(:,:) + integer*1, allocatable :: genmrb(:,:),g2(:,:) + integer*1, allocatable :: temp(:),temprow(:),m0(:),me(:),mi(:) + integer indices(N),indices2(N),nxor(N) + integer*1 cw(N),ce(N),c0(N),hdec(N) + integer*1, allocatable :: decoded(:) + integer*1 message74(74) + integer*1, allocatable :: sp(:) + integer indx(N),ksave + real llr(N),rx(N),absrx(N) + + logical first + data first/.true./,ksave/64/ + save first,ksave + + allocate( genmrb(k,N), g2(N,k) ) + allocate( temp(k), temprow(n), m0(k), me(k), mi(k) ) + allocate( decoded(k) ) + + if( first .or. k.ne.ksave) then ! fill the generator matrix +! +! Create generator matrix for partial CRC cascaded with LDPC code. +! +! Let p2=74-k and p1+p2=24. +! +! The last p2 bits of the CRC24 are cascaded with the LDPC code. +! +! The first p1=k-50 CRC24 bits will be used for error detection. +! + if( allocated(gen) ) deallocate(gen) + allocate( gen(k,N) ) + gen=0 + do i=1,k + message74=0 + message74(i)=1 + if(i.le.50) then + call get_crc24(message74,74,ncrc24) + write(c24,'(b24.24)') ncrc24 + read(c24,'(24i1)') message74(51:74) + message74(51:k)=0 + endif + call encode240_74(message74,cw) + gen(i,:)=cw + enddo + + first=.false. + ksave=k + endif + +! Use best k elements from the sorted list for the first basis. For the 2nd basis replace +! the nswap lowest quality symbols with the best nswap elements from the parity symbols. + nswap=20 + + do ibasis=1,2 + rx=llr + apmaskr=apmask + +! Hard decisions on the received word. + hdec=0 + where(rx .ge. 0) hdec=1 + +! Use magnitude of received symbols as a measure of reliability. + absrx=abs(llr) + call indexx(absrx,N,indx) + +! Re-order the columns of the generator matrix in order of decreasing reliability. + do i=1,N + genmrb(1:k,i)=gen(1:k,indx(N+1-i)) + indices(i)=indx(N+1-i) + enddo + + if(ibasis.eq.2) then + do i=k-nswap+1,k + temp(1:k)=genmrb(1:k,i) + genmrb(1:k,i)=genmrb(1:k,i+nswap) + genmrb(1:k,i+nswap)=temp(1:k) + itmp=indices(i) + indices(i)=indices(i+nswap) + indices(i+nswap)=itmp + enddo + endif + +! Do gaussian elimination to create a generator matrix with the most reliable +! received bits in positions 1:k in order of decreasing reliability (more or less). + + icol=1 + indices2=0 + nskipped=0 + do id=1,k + iflag=0 + do while(iflag.eq.0) + if(genmrb(id,icol).ne.1) then + do j=id+1,k + if(genmrb(j,icol).eq.1) then + temprow=genmrb(id,:) + genmrb(id,:)=genmrb(j,:) + genmrb(j,:)=temprow + iflag=1 + endif + enddo + if(iflag.eq.0) then ! skip this column + nskipped=nskipped+1 + indices2(k+nskipped)=icol ! put icol where skipped columns go + icol=icol+1 ! look at the next column + endif + else + iflag=1 + endif + enddo + indices2(id)=icol + do j=1,k + if(id.ne.j .and. genmrb(j,icol).eq.1) then + genmrb(j,:)=ieor(genmrb(id,:),genmrb(j,:)) + endif + enddo + icol=icol+1 + enddo + do i=k+nskipped+1,240 + indices2(i)=i + enddo + genmrb(1:k,:)=genmrb(1:k,indices2) + indices=indices(indices2) + +!************************************ + g2=transpose(genmrb) + +! The hard decisions for the k MRB bits define the order 0 message, m0. +! Encode m0 using the modified generator matrix to find the "order 0" codeword. +! Flip various combinations of bits in m0 and re-encode to generate a list of +! codewords. Return the member of the list that has the smallest Euclidean +! distance to the received word. + + hdec=hdec(indices) ! hard decisions from received symbols + m0=hdec(1:k) ! zero'th order message + absrx=abs(llr) + absrx=absrx(indices) + rx=rx(indices) + apmaskr=apmaskr(indices) + + call mrbencode74(m0,c0,g2,N,k) + nxor=ieor(c0,hdec) + nhardmin=sum(nxor) + dmin=sum(nxor*absrx) + np=32 + if(ibasis.eq.1) allocate(sp(np)) + + cw=c0 + ntotal=0 + nrejected=0 + + if(ndeep.eq.0) goto 998 ! norder=0 + if(ndeep.gt.4) ndeep=4 + if( ndeep.eq. 1) then + nord=1 + xlambda=0.0 + nsyncmax=np + elseif(ndeep.eq.2) then + nord=2 + xlambda=0.0 + nsyncmax=np + elseif(ndeep.eq.3) then + nord=3 + xlambda=4.0 + nsyncmax=11 + elseif(ndeep.eq.4) then + nord=4 + xlambda=3.4 + nsyndmax=12 + endif + + s1=sum(absrx(1:k)) + s2=sum(absrx(k+1:N)) + rho=s1/(s1+xlambda*s2) + rhodmin=rho*dmin + nerr64=-1 + do iorder=1,nord +!beta=0.0 +!if(iorder.ge.3) beta=0.4 +!spnc_order=sum(absrx(k-iorder+1:k))+beta*(N-k) +!if(dmin.lt.spnc_order) cycle + mi(1:k-iorder)=0 + mi(k-iorder+1:k)=1 + iflag=k-iorder+1 + do while(iflag .ge.0) + ntotal=ntotal+1 + me=ieor(m0,mi) + d1=sum(mi(1:k)*absrx(1:k)) + if(d1.gt.rhodmin) exit + call partial_syndrome(me,sp,np,g2,N,K) + nwhsp=sum(ieor(sp(1:np),hdec(k:k+np-1))) + if(nwhsp.le.nsyndmax) then + call mrbencode74(me,ce,g2,N,k) + nxor=ieor(ce,hdec) + dd=sum(nxor*absrx(1:N)) + if( dd .lt. dmin ) then + dmin=dd + rhodmin=rho*dmin + cw=ce + nhardmin=sum(nxor) + nwhspmin=nwhsp + nerr64=sum(nxor(1:K)) + endif + endif +! Get the next test error pattern, iflag will go negative +! when the last pattern with weight iorder has been generated. + call nextpat74(mi,k,iorder,iflag) + enddo + enddo + +998 continue +! Re-order the codeword to [message bits][parity bits] format. + cw(indices)=cw + hdec(indices)=hdec + message74=cw(1:74) + call get_crc24(message74,74,nbadcrc) + if(nbadcrc.eq.0) exit + nhardmin=-nhardmin + enddo ! basis loop + return +end subroutine fastosd240_74 + +subroutine mrbencode74(me,codeword,g2,N,K) + integer*1 me(K),codeword(N),g2(N,K) +! fast encoding for low-weight test patterns + codeword=0 + do i=1,K + if( me(i) .eq. 1 ) then + codeword=ieor(codeword,g2(1:N,i)) + endif + enddo + return +end subroutine mrbencode74 + +subroutine partial_syndrome(me,sp,np,g2,N,K) + integer*1 me(K),sp(np),g2(N,K) +! compute partial syndrome + sp=0 + do i=1,K + if( me(i) .eq. 1 ) then + sp=ieor(sp,g2(K:K+np-1,i)) + endif + enddo + return +end subroutine partial_syndrome + +subroutine nextpat74(mi,k,iorder,iflag) + integer*1 mi(k),ms(k) +! generate the next test error pattern + ind=-1 + do i=1,k-1 + if( mi(i).eq.0 .and. mi(i+1).eq.1) ind=i + enddo + if( ind .lt. 0 ) then ! no more patterns of this order + iflag=ind + return + endif + ms=0 + ms(1:ind-1)=mi(1:ind-1) + ms(ind)=1 + ms(ind+1)=0 + if( ind+1 .lt. k ) then + nz=iorder-sum(ms) + ms(k-nz+1:k)=1 + endif + mi=ms + do i=1,k ! iflag will point to the lowest-index 1 in mi + if(mi(i).eq.1) then + iflag=i + exit + endif + enddo + return +end subroutine nextpat74 + diff --git a/lib/fst4/fst4sim.f90 b/lib/fst4/fst4sim.f90 index 5b8f33bc3..83ac5baed 100644 --- a/lib/fst4/fst4sim.f90 +++ b/lib/fst4/fst4sim.f90 @@ -19,10 +19,10 @@ program fst4sim ! Get command-line argument(s) nargs=iargc() - if(nargs.ne.10) then - print*,'Need 10 arguments, got ',nargs - print*,'Usage: fst4sim "message" TRsec f0 DT h fdop del nfiles snr W' - print*,'Examples: fst4sim "K1JT K9AN EN50" 60 1500 0.0 1 0.1 1.0 10 -15 F' + if(nargs.ne.9) then + print*,'Need 9 arguments, got ',nargs + print*,'Usage: fst4sim "message" TRsec f0 DT fdop del nfiles snr W' + print*,'Examples: fst4sim "K1JT K9AN EN50" 60 1500 0.0 0.1 1.0 10 -15 F' print*,'W (T or F) argument is hint to encoder to use WSPR message when there is abiguity' go to 999 endif @@ -34,16 +34,14 @@ program fst4sim call getarg(4,arg) read(arg,*) xdt !Time offset from nominal (s) call getarg(5,arg) - read(arg,*) hmod !Modulation index, h - call getarg(6,arg) read(arg,*) fspread !Watterson frequency spread (Hz) - call getarg(7,arg) + call getarg(6,arg) read(arg,*) delay !Watterson delay (ms) - call getarg(8,arg) + call getarg(7,arg) read(arg,*) nfiles !Number of files - call getarg(9,arg) + call getarg(8,arg) read(arg,*) snrdb !SNR_2500 - call getarg(10,arg) + call getarg(9,arg) read(arg,*) wspr_hint !0:break ties as 77-bit 1:break ties as 50-bit nfiles=abs(nfiles) @@ -89,8 +87,8 @@ program fst4sim call genfst4(msg37,0,msgsent37,msgbits,itone,iwspr) write(*,*) write(*,'(a9,a37,a3,L2,a7,i2)') 'Message: ',msgsent37,'W:',wspr_hint,' iwspr:',iwspr - write(*,1000) f00,xdt,hmod,txt,snrdb -1000 format('f0:',f9.3,' DT:',f6.2,' hmod:',i6,' TxT:',f6.1,' SNR:',f6.1) + write(*,1000) f00,xdt,txt,snrdb +1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1) write(*,*) if(i3.eq.1) then write(*,*) ' mycall hiscall hisgrid' @@ -106,7 +104,8 @@ program fst4sim ! call sgran() - fsample=12000.0 + fsample=12000.0 + hmod=1 icmplx=1 f0=f00+1.5*hmod*baud call gen_fst4wave(itone,NN,nsps,nwave,fsample,hmod,f0,icmplx,c0,wave) @@ -118,7 +117,8 @@ program fst4sim do ifile=1,nfiles c=c0 - if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c,nwave,NZ,fs,delay,fspread) + if(fspread.gt.0.0 .or. delay.ne.0.0) call watterson(c,nwave,NZ,fs,delay,fspread) + if(fspread.lt.0.0) call lorentzian_fading(c,nwave,fs,-fspread) c=sig*c wave=real(c) if(snrdb.lt.90) then diff --git a/lib/fst4/ldpcsim240_74.f90 b/lib/fst4/ldpcsim240_74.f90 index b488aa6b6..78e8e6b5f 100644 --- a/lib/fst4/ldpcsim240_74.f90 +++ b/lib/fst4/ldpcsim240_74.f90 @@ -101,7 +101,7 @@ write(*,'(24i1)') msgbits(51:74) llr=2.0*rxdata/(ss*ss) apmask=0 dmin=0.0 - maxosd=0 + maxosd=2 call decode240_74(llr, Keff, maxosd, norder, apmask, message74, cw, ntype, nharderror, dmin) if(nharderror.ge.0) then n2err=0 diff --git a/lib/fst4/lorentzian_fading.f90 b/lib/fst4/lorentzian_fading.f90 new file mode 100644 index 000000000..c1bd5c325 --- /dev/null +++ b/lib/fst4/lorentzian_fading.f90 @@ -0,0 +1,43 @@ +subroutine lorentzian_fading(c,npts,fs,fspread) +! +! npts is the total length of the simulated data vector +! + complex c(0:npts-1) + complex cspread(0:npts-1) + complex z + + twopi=8.0*atan(1.0) + df=fs/npts + nh=npts/2 + cspread(0)=1.0 + cspread(nh)=0. + b=6.0 + do i=1,nh + f=i*df + x=b*f/fspread + z=0. + a=0. + if(x.lt.3.0) then + a=sqrt(1.111/(1.0+x*x)-0.1) + phi1=twopi*rran() + z=a*cmplx(cos(phi1),sin(phi1)) + endif + cspread(i)=z + z=0. + if(x.lt.3.0) then + phi2=twopi*rran() + z=a*cmplx(cos(phi2),sin(phi2)) + endif + cspread(npts-i)=z + enddo + + call four2a(cspread,npts,1,1,1) + + s=sum(abs(cspread)**2) + avep=s/npts + fac=sqrt(1.0/avep) + cspread=fac*cspread + c=cspread*c + + return +end subroutine lorentzian_fading diff --git a/lib/fst4_decode.f90 b/lib/fst4_decode.f90 index ba49fb54d..5fb591ffa 100644 --- a/lib/fst4_decode.f90 +++ b/lib/fst4_decode.f90 @@ -33,15 +33,17 @@ contains ndepth,ntrperiod,nexp_decode,ntol,emedelay,lagain,lapcqonly,mycall, & hiscall,iwspr) + use prog_args use timer_module, only: timer use packjt77 use, intrinsic :: iso_c_binding include 'fst4/fst4_params.f90' - parameter (MAXCAND=100) + parameter (MAXCAND=100,MAXWCALLS=100) class(fst4_decoder), intent(inout) :: this procedure(fst4_decode_callback) :: callback character*37 decodes(100) character*37 msg,msgsent + character*20 wcalls(MAXWCALLS), wpart character*77 c77 character*12 mycall,hiscall character*12 mycall0,hiscall0 @@ -56,8 +58,7 @@ contains logical lagain,lapcqonly integer itone(NN) integer hmod - integer ipct(0:7) - integer*1 apmask(240),cw(240) + integer*1 apmask(240),cw(240),hdec(240) integer*1 message101(101),message74(74),message77(77) integer*1 rvec(77) integer apbits(240) @@ -66,11 +67,12 @@ contains integer mcq(29),mrrr(19),m73(19),mrr73(19) logical badsync,unpk77_success,single_decode - logical first,nohiscall,lwspr,ex + logical first,nohiscall,lwspr + logical new_callsign,plotspec_exists,wcalls_exists,do_k50_decode + logical decdata_exists integer*2 iwave(30*60*12000) - data ipct/0,8,14,4,12,2,10,6/ data mcq/0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0/ data mrrr/0,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,1/ data m73/0,1,1,1,1,1,1,0,1,0,0,1,0,1,0,0,0,0,1/ @@ -80,6 +82,7 @@ contains 0,1,0,1,0,1,1,0,1,1,1,1,1,0,0,0,1,0,1/ data first/.true./,hmod/1/ save first,apbits,nappasses,naptypes,mycall0,hiscall0 + save wcalls,nwcalls this%callback => callback dxcall13=hiscall ! initialize for use in packjt77 @@ -88,6 +91,20 @@ contains if(iwspr.ne.0.and.iwspr.ne.1) return if(first) then +! read the fst4_calls.txt file + inquire(file=trim(data_dir)//'/fst4w_calls.txt',exist=wcalls_exists) + if( wcalls_exists ) then + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + do i=1,MAXWCALLS + wcalls(i)='' + read(42,fmt='(a)',end=2867) wcalls(i) + wcalls(i)=adjustl(wcalls(i)) + if(len(trim(wcalls(i))).eq.0) exit + enddo +2867 nwcalls=i-1 + close(42) + endif + mcq=2*mod(mcq+rvec(1:29),2)-1 mrrr=2*mod(mrrr+rvec(59:77),2)-1 m73=2*mod(m73+rvec(59:77),2)-1 @@ -213,17 +230,22 @@ contains allocate( cframe(0:160*nss-1) ) jittermax=2 + do_k50_decode=.false. if(ndepth.eq.3) then nblock=4 jittermax=2 + do_k50_decode=.true. elseif(ndepth.eq.2) then - nblock=3 - jittermax=0 + nblock=4 + jittermax=2 + do_k50_decode=.false. elseif(ndepth.eq.1) then - nblock=1 + nblock=4 jittermax=0 + do_k50_decode=.false. endif +! Noise blanker setup ndropmax=1 single_decode=iand(nexp_decode,32).ne.0 npct=0 @@ -239,33 +261,40 @@ contains inb2=1 !Try NB = 0, 1, 2,... 20% else inb1=0 !Fixed NB value, 0 to 25% - ipct(0)=npct endif + +! nfa,nfb: define the noise-baseline analysis window +! fa, fb: define the signal search window +! We usually make nfafb so that noise baseline analysis +! window extends outside of the [fa,fb] window where we think the signals are. +! if(iwspr.eq.1) then !FST4W - !300 Hz wide noise-fit window - nfa=max(100,nint(nfqso+1.5*baud-150)) - nfb=min(4800,nint(nfqso+1.5*baud+150)) + nfa=max(100,nfqso-ntol-100) + nfb=min(4800,nfqso+ntol+100) fa=max(100,nint(nfqso+1.5*baud-ntol)) ! signal search window fb=min(4800,nint(nfqso+1.5*baud+ntol)) - else if(single_decode) then - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) - else - fa=max(100,nint(nfa+1.5*baud)) - fb=min(4800,nint(nfb+1.5*baud)) - ! extend noise fit 100 Hz outside of search window - nfa=max(100,nfa-100) - nfb=min(4800,nfb+100) + else if(iwspr.eq.0) then + if(single_decode) then + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) + else + fa=max(100,nint(nfa+1.5*baud)) + fb=min(4800,nint(nfb+1.5*baud)) + ! extend noise fit 100 Hz outside of search window + nfa=max(100,nfa-100) + nfb=min(4800,nfb+100) + endif endif - + ndecodes=0 decodes=' ' + new_callsign=.false. do inb=0,inb1,inb2 - if(nb.lt.0) npct=inb + if(nb.lt.0) npct=inb ! we are looping over blanker settings call blanker(iwave,nfft1,ndropmax,npct,c_bigfft) ! The big fft is done once and is used for calculating the smoothed spectrum @@ -275,23 +304,22 @@ contains nsyncoh=8 minsync=1.20 if(ntrperiod.eq.15) minsync=1.15 - + ! Get first approximation of candidate frequencies call get_candidates_fst4(c_bigfft,nfft1,nsps,hmod,fs,fa,fb,nfa,nfb, & - minsync,ncand,candidates0) + minsync,ncand,candidates0) isbest=0 fc2=0. do icand=1,ncand fc0=candidates0(icand,1) if(iwspr.eq.0 .and. nb.lt.0 .and. npct.ne.0 .and. & - abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle + abs(fc0-(nfqso+1.5*baud)).gt.ntol) cycle ! blanker loop only near nfqso detmet=candidates0(icand,2) ! Downconvert and downsample a slice of the spectrum centered on the ! rough estimate of the candidates frequency. ! Output array c2 is complex baseband sampled at 12000/ndown Sa/sec. ! The size of the downsampled c2 array is nfft2=nfft1/ndown - call timer('dwnsmpl ',0) call fst4_downsample(c_bigfft,nfft1,ndown,fc0,sigbw,c2) call timer('dwnsmpl ',1) @@ -330,9 +358,9 @@ contains endif enddo ncand=ic - -! If FST4 and Single Decode is not checked, then find candidates within -! 20 Hz of nfqso and put them at the top of the list + +! If FST4 mode and Single Decode is not checked, then find candidates +! within 20 Hz of nfqso and put them at the top of the list if(iwspr.eq.0 .and. .not.single_decode) then nclose=count(abs(candidates0(:,3)-(nfqso+1.5*baud)).le.20) k=0 @@ -368,12 +396,13 @@ contains if(ijitter.eq.1) ioffset=1 if(ijitter.eq.2) ioffset=-1 is0=isbest+ioffset - if(is0.lt.0) cycle - cframe=c2(is0:is0+160*nss-1) + iend=is0+160*nss-1 + if( is0.lt.0 .or. iend.gt.(nfft2-1) ) cycle + cframe=c2(is0:iend) bitmetrics=0 call timer('bitmetrc',0) call get_fst4_bitmetrics(cframe,nss,nblock,nhicoh,bitmetrics, & - s4,nsync_qual,badsync) + s4,nsync_qual,badsync) call timer('bitmetrc',1) if(badsync) cycle @@ -384,10 +413,10 @@ contains llrs(181:240,il)=bitmetrics(245:304, il) enddo - apmag=maxval(abs(llrs(:,1)))*1.1 + apmag=maxval(abs(llrs(:,4)))*1.1 ntmax=nblock+nappasses(nQSOProgress) if(lapcqonly) ntmax=nblock+1 - if(ndepth.eq.1) ntmax=nblock + if(ndepth.eq.1) ntmax=nblock ! no ap for ndepth=1 apmask=0 if(iwspr.eq.1) then ! 50-bit msgs, no ap decoding @@ -405,7 +434,7 @@ contains iaptype=0 endif - if(itry.gt.nblock) then ! do ap passes + if(itry.gt.nblock .and. iwspr.eq.0) then ! do ap passes llr=llrs(:,nblock) ! Use largest blocksize as the basis for AP passes iaptype=naptypes(nQSOProgress,itry-nblock) if(lapcqonly) iaptype=1 @@ -428,7 +457,7 @@ contains apmask(1:58)=1 llr(1:58)=apmag*apbits(1:58) endif - + if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype .eq.6) then apmask=0 apmask(1:77)=1 @@ -438,7 +467,7 @@ contains if(iaptype.eq.6) llr(59:77)=apmag*mrr73(1:19) endif endif - + dmin=0.0 nharderrors=-1 unpk77_success=.false. @@ -448,83 +477,142 @@ contains norder=3 call timer('d240_101',0) call decode240_101(llr,Keff,maxosd,norder,apmask,message101, & - cw,ntype,nharderrors,dmin) + cw,ntype,nharderrors,dmin) call timer('d240_101',1) - elseif(iwspr.eq.1) then - maxosd=2 - call timer('d240_74 ',0) - Keff=64 - norder=4 - call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & - ntype,nharderrors,dmin) - call timer('d240_74 ',1) - endif - - if(nharderrors .ge.0) then if(count(cw.eq.1).eq.0) then nharderrors=-nharderrors cycle endif - if(iwspr.eq.0) then - write(c77,'(77i1)') mod(message101(1:77)+rvec,2) - call unpack77(c77,1,msg,unpk77_success) - else + write(c77,'(77i1)') mod(message101(1:77)+rvec,2) + call unpack77(c77,1,msg,unpk77_success) + elseif(iwspr.eq.1) then +! Try decoding with Keff=66 + maxosd=2 + call timer('d240_74 ',0) + Keff=66 + norder=3 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(nharderrors.lt.0) goto 3465 + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif + write(c77,'(50i1)') message74(1:50) + c77(51:77)='000000000000000000000110000' + call unpack77(c77,1,msg,unpk77_success) + if(unpk77_success .and. do_k50_decode) then +! If decode was obtained with Keff=66, save call/grid in fst4w_calls.txt if not there already. + i1=index(msg,' ') + i2=i1+index(msg(i1+1:),' ') + wpart=trim(msg(1:i2)) +! Only save callsigns/grids from type 1 messages + if(index(wpart,'/').eq.0 .and. index(wpart,'<').eq.0) then + ifound=0 + do i=1,nwcalls + if(index(wcalls(i),wpart).ne.0) ifound=1 + enddo + + if(ifound.eq.0) then ! This is a new callsign + new_callsign=.true. + if(nwcalls.lt.MAXWCALLS) then + nwcalls=nwcalls+1 + wcalls(nwcalls)=wpart + else + wcalls(1:nwcalls-1)=wcalls(2:nwcalls) + wcalls(nwcalls)=wpart + endif + endif + endif + endif +3465 continue + +! If no decode then try Keff=50 + iaptype=0 + if( .not. unpk77_success .and. do_k50_decode ) then + maxosd=1 + call timer('d240_74 ',0) + Keff=50 + norder=4 + call decode240_74(llr,Keff,maxosd,norder,apmask,message74,cw, & + ntype,nharderrors,dmin) + call timer('d240_74 ',1) + if(count(cw.eq.1).eq.0) then + nharderrors=-nharderrors + cycle + endif write(c77,'(50i1)') message74(1:50) c77(51:77)='000000000000000000000110000' call unpack77(c77,1,msg,unpk77_success) +! No CRC in this mode, so only accept the decode if call/grid have been seen before + if(unpk77_success) then + unpk77_success=.false. + do i=1,nwcalls + if(index(msg,trim(wcalls(i))).gt.0) then + unpk77_success=.true. + endif + enddo + endif endif - if(unpk77_success) then - idupe=0 - do i=1,ndecodes - if(decodes(i).eq.msg) idupe=1 - enddo - if(idupe.eq.1) goto 800 - ndecodes=ndecodes+1 - decodes(ndecodes)=msg - - if(iwspr.eq.0) then - call get_fst4_tones_from_bits(message101,itone,0) - else - call get_fst4_tones_from_bits(message74,itone,1) - endif - inquire(file='plotspec',exist=ex) - fmid=-999.0 - call timer('dopsprd ',0) - if(ex) then - call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & - isbest,fc_synced,fmid,w50) - endif - call timer('dopsprd ',1) - xsig=0 - do i=1,NN - xsig=xsig+s4(itone(i),i) - enddo - base=candidates(icand,5) - arg=600.0*(xsig/base)-1.0 - if(arg.gt.0.0) then - xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) - if(ntrperiod.eq. 15) xsnr=xsnr+2 - if(ntrperiod.eq. 30) xsnr=xsnr+1 - if(ntrperiod.eq. 900) xsnr=xsnr+1 - if(ntrperiod.eq.1800) xsnr=xsnr+2 - else - xsnr=-99.9 - endif + + endif + + if(nharderrors .ge.0 .and. unpk77_success) then + idupe=0 + do i=1,ndecodes + if(decodes(i).eq.msg) idupe=1 + enddo + if(idupe.eq.1) goto 800 + ndecodes=ndecodes+1 + decodes(ndecodes)=msg + + if(iwspr.eq.0) then + call get_fst4_tones_from_bits(message101,itone,0) else - cycle + call get_fst4_tones_from_bits(message74,itone,1) + endif + inquire(file='plotspec',exist=plotspec_exists) + fmid=-999.0 + call timer('dopsprd ',0) + if(plotspec_exists) then + call dopspread(itone,iwave,nsps,nmax,ndown,hmod, & + isbest,fc_synced,fmid,w50) + endif + call timer('dopsprd ',1) + xsig=0 + do i=1,NN + xsig=xsig+s4(itone(i),i) + enddo + base=candidates(icand,5) + arg=600.0*(xsig/base)-1.0 + if(arg.gt.0.0) then + xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0) + if(ntrperiod.eq. 15) xsnr=xsnr+2 + if(ntrperiod.eq. 30) xsnr=xsnr+1 + if(ntrperiod.eq. 900) xsnr=xsnr+1 + if(ntrperiod.eq.1800) xsnr=xsnr+2 + else + xsnr=-99.9 endif nsnr=nint(xsnr) - qual=0. + qual=0.0 fsig=fc_synced - 1.5*baud - if(ex) then + inquire(file=trim(data_dir)//'/decdata',exist=decdata_exists) + if(decdata_exists) then + hdec=0 + where(llrs(:,1).ge.0.0) hdec=1 + nhp=count(hdec.ne.cw) ! # hard errors wrt N=1 soft symbols + hd=sum(ieor(hdec,cw)*abs(llrs(:,1))) ! weighted distance wrt N=1 symbols + open(21,file=trim(data_dir)//'/fst4_decodes.dat',status='unknown',position='append') write(21,3021) nutc,icand,itry,nsyncoh,iaptype, & - ijitter,ntype,nsync_qual,nharderrors,dmin, & - sync,xsnr,xdt,fsig,w50,trim(msg) -3021 format(i6.6,6i3,2i4,f6.1,f7.2,f6.1,f6.2,f7.1,f7.3,1x,a) - flush(21) + ijitter,npct,ntype,Keff,nsync_qual,nharderrors,dmin,nhp,hd, & + sync,xsnr,xdt,fsig,w50,trim(msg) +3021 format(i6.6,i4,6i3,3i4,f6.1,i4,f6.1,f9.2,f6.1,f6.2,f7.1,f7.3,1x,a) + close(21) endif call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & - iaptype,qual,ntrperiod,lwspr,fmid,w50) + iaptype,qual,ntrperiod,lwspr,fmid,w50) if(iwspr.eq.0 .and. nb.lt.0) go to 900 goto 800 endif @@ -532,9 +620,17 @@ contains enddo ! istart jitter 800 enddo !candidate list enddo ! noise blanker loop - + + if(new_callsign .and. do_k50_decode) then ! re-write the fst4w_calls.txt file + open(42,file=trim(data_dir)//'/fst4w_calls.txt',status='unknown') + do i=1,nwcalls + write(42,'(a20)') trim(wcalls(i)) + enddo + close(42) + endif + 900 return - end subroutine decode + end subroutine decode subroutine sync_fst4(cd0,i0,f0,hmod,ncoh,np,nss,ntr,fs,sync) @@ -726,8 +822,8 @@ contains do i=ina,inb !Compute CCF of s() and 4 tones s2(i)=s(i-hmod*3) + s(i-hmod) +s(i+hmod) +s(i+hmod*3) enddo - npct=30 - call fst4_baseline(s2,nnw,ina+hmod*3,inb-hmod*3,npct,sbase) + npctile=30 + call fst4_baseline(s2,nnw,ina+hmod*3,inb-hmod*3,npctile,sbase) if(any(sbase(ina:inb).le.0.0)) return s2(ina:inb)=s2(ina:inb)/sbase(ina:inb) !Normalize wrt noise level @@ -902,6 +998,6 @@ contains enddo return - end subroutine dopspread + end subroutine dopspread end module fst4_decode diff --git a/lib/ft8/get_spectrum_baseline.f90 b/lib/ft8/get_spectrum_baseline.f90 index 9cf4e637c..f815eba14 100644 --- a/lib/ft8/get_spectrum_baseline.f90 +++ b/lib/ft8/get_spectrum_baseline.f90 @@ -35,8 +35,19 @@ subroutine get_spectrum_baseline(dd,nfa,nfb,sbase) savg=savg + s(1:NH1,j) !Average spectrum enddo - if(nfa.lt.100) nfa=100 - if(nfb.gt.4910) nfb=4910 + nwin=nfb-nfa + if(nfa.lt.100) then + nfa=100 + if(nwin.lt.100) then ! nagain + nfb=nfa+nwin + endif + endif + if(nfb.gt.4910) then + nfb=4910 + if(nwin.lt.100) then + nfa=nfb-nwin + endif + endif call baseline(savg,nfa,nfb,sbase) return diff --git a/lib/ft8_decode.f90 b/lib/ft8_decode.f90 index 26b12d6c9..73d0f8c2a 100644 --- a/lib/ft8_decode.f90 +++ b/lib/ft8_decode.f90 @@ -118,7 +118,7 @@ contains dd1=dd go to 900 endif - if(nzhsym.eq.50 .and. ndec_early.ge.1) then + if(nzhsym.eq.50 .and. ndec_early.ge.1 .and. .not.nagain) then n=47*3456 dd(1:n)=dd1(1:n) dd(n+1:)=iwave(n+1:) @@ -131,9 +131,10 @@ contains endif ifa=nfa ifb=nfb - if(nagain) then - ifa=nfqso-10 - ifb=nfqso+10 + if(nzhsym.eq.50 .and. nagain) then + dd=iwave + ifa=nfqso-20 + ifb=nfqso+20 endif ! For now: diff --git a/lib/gran.c b/lib/gran.c index 24b986503..ac41c7fe4 100644 --- a/lib/gran.c +++ b/lib/gran.c @@ -26,3 +26,9 @@ float gran_() iset++; return v2*fac; } + +/* Generates evenly distributed numbers between 0 and 1. */ +float rran_() +{ + return (float)rand()/(float)RAND_MAX; +} diff --git a/lib/wsprd/wsprd.c b/lib/wsprd/wsprd.c index 2e3b385da..8ef66fd19 100644 --- a/lib/wsprd/wsprd.c +++ b/lib/wsprd/wsprd.c @@ -71,7 +71,7 @@ unsigned long readc2file(char *ptr_to_infile, float *idat, float *qdat, float *buffer; double dfreq; int i,ntrmin; - char *c2file[15]; + char c2file[15]; size_t nr; FILE* fp; @@ -875,10 +875,12 @@ int main(int argc, char *argv[]) } } - if( stackdecoder ) { - stack=calloc(stacksize,sizeof(struct snode)); + if( access(data_dir, R_OK | W_OK)) { + fprintf(stderr, "Error: inaccessible data directory: '%s'\n", data_dir); + usage(); + return EXIT_FAILURE; } - + if( optind+1 > argc) { usage(); return 1; @@ -886,6 +888,10 @@ int main(int argc, char *argv[]) ptr_to_infile=argv[optind]; } + if( stackdecoder ) { + stack=calloc(stacksize,sizeof(struct snode)); + } + // setup metric table for(i=0; i<256; i++) { mettab[0][i]=round( 10*(metric_tables[2][i]-bias) ); diff --git a/main.cpp b/main.cpp index 021e327b4..c6dd0ccbf 100644 --- a/main.cpp +++ b/main.cpp @@ -76,7 +76,13 @@ namespace switch (static_cast (v.type ())) { case QMetaType::QByteArray: - os << "0x" << v.toByteArray ().toHex (':').toStdString (); + os << "0x" +#if QT_VERSION >= QT_VERSION_CHECK (5, 9, 0) + << v.toByteArray ().toHex (':').toStdString () +#else + << v.toByteArray ().toHex ().toStdString () +#endif + ; break; case QMetaType::QBitArray: @@ -98,7 +104,6 @@ namespace int main(int argc, char *argv[]) { - ::qInstallMessageHandler (&WSJTXLogging::qt_log_handler); init_random_seed (); // make the Qt type magic happen @@ -205,7 +210,9 @@ int main(int argc, char *argv[]) multiple = true; } - // now we have the application name we can open the settings + // now we have the application name we can open the logging and settings + WSJTXLogging lg; + LOG_INFO (program_title (revision ()) << " - Program startup"); MultiSettings multi_settings {parser.value (cfg_option)}; // find the temporary files path @@ -241,9 +248,6 @@ int main(int argc, char *argv[]) } } - WSJTXLogging lg; - LOG_INFO (program_title (revision ()) << " - Program startup"); - // load UI translations L10nLoader l10n {&a, locale, parser.value (lang_option)}; diff --git a/models/FrequencyList.cpp b/models/FrequencyList.cpp index 3c4a43012..b14dae6f9 100644 --- a/models/FrequencyList.cpp +++ b/models/FrequencyList.cpp @@ -580,6 +580,7 @@ auto FrequencyList_v2::impl::frequency_list (FrequencyItems frequency_list) -> F return frequency_list; } +// add a frequency returning the new model index QModelIndex FrequencyList_v2::impl::add (Item f) { // Any Frequency that isn't in the list may be added diff --git a/translations/wsjtx_ca.ts b/translations/wsjtx_ca.ts index e8e99b115..2b7fbabbd 100644 --- a/translations/wsjtx_ca.ts +++ b/translations/wsjtx_ca.ts @@ -634,7 +634,8 @@ Format: Not found audio device missing - + falta un dispositiu d'àudio + No trobat @@ -2712,12 +2713,12 @@ Si no està marcat, pots veure els resultats de la calibració. F High - + F Alt F Low - + F Baixa @@ -2964,12 +2965,12 @@ La llista es pot mantenir a la configuració (F2). SWL Mode - + Mode SWL Hide lower panel controls to maximize deocde windows - + Amaga els controls del panell inferior per a maximitzar les finestres de descodificació Calling CQ @@ -3868,7 +3869,7 @@ La llista es pot mantenir a la configuració (F2). Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Mostres caigudes excessives - %1 (%2 sec) fotogrames d'àudio caiguts en el període inicial %3 @@ -3893,7 +3894,7 @@ La llista es pot mantenir a la configuració (F2). Enumerating audio devices - + Enumeració de dispositius d’àudio @@ -4079,9 +4080,9 @@ La llista es pot mantenir a la configuració (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Si fas un ús raonable de qualsevol part de WSJT-X segons els termes de la Llicència Pública General de GNU, has de mostrar de manera destacada el següent avís de copyright en el teu treball derivat: -"Els algoritmes, codi font, aspecte de WSJT-X i programes relacionats i les especificacions de protocol per als modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 són Copyright (C) 2001-2020 per un o més dels següents autors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q i altres membres del grup de desenvolupament de WSJT. " +"Els algoritmes, codi font, aspecte de WSJT-X i programes relacionats i les especificacions de protocol per als modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 són Copyright (C) 2001-2021 per un o més dels següents autors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q i altres membres del grup de desenvolupament de WSJT. " diff --git a/translations/wsjtx_da.ts b/translations/wsjtx_da.ts index 3acc2f102..3bff69ce9 100644 --- a/translations/wsjtx_da.ts +++ b/translations/wsjtx_da.ts @@ -20,8 +20,8 @@ Are you sure you want to delete the %n selected QSO(s) from the log? - Er du sikker på at du vil slette de %n valgte QSO(er) fra loggen? - + Sikker på du vil slette de %n valgte QSO(er) fra loggen? + Er du sikker på du vil slette de %n valgte QSO(s) fra loggen? @@ -247,7 +247,7 @@ <html><head/><body><p>Right-click here for available actions.</p></body></html> - <html><head/><body> <p> Højreklik her for tilgængelige muligheder. </p> </body> </html> + <html><head/><body><p> Højreklik her for tilgængelige muligheder.</p></body></html> @@ -318,7 +318,7 @@ New Call - Ny kaldesignal + Nyt kaldesignal @@ -626,7 +626,7 @@ Format: Not found audio device missing - + Audio device mangler @@ -2197,7 +2197,7 @@ Fejl(%2): %3 &Decode - &Dekod + &Dekode @@ -2492,7 +2492,7 @@ Gul er for lavt Fast - Fast + Hurtig @@ -2711,12 +2711,12 @@ Når den ikke er markeret, kan du se kalibreringsresultaterne. F High - + F Høj F Low - + F Lav @@ -2964,12 +2964,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). SWL Mode - + SWL Mode Hide lower panel controls to maximize deocde windows - + Skjul nederste del af Control Panel for at maksimere dekoder vinduet Calling CQ @@ -3864,7 +3864,8 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + For store tabte prøver -% 1 (% 2 sek) lydrammer faldt i perioden startende med% 3 + For stort tab i - %1 (%2 sec) audio frames stoppet i periode startende %3 @@ -3889,7 +3890,7 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Enumerating audio devices - + Opsumering af audio enheder @@ -4075,9 +4076,9 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Hvis du gør brug af nogen del af WSJT-X under betingelserne i GNU General Public License, skal du vise følgende copyright-meddelelse fremtrædende i din egen udgave: -"Algoritmerne, kildekoden, udseendet og funktionen af ​​WSJT-X og relaterede programmer og protokolspecifikationer for Mode FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 er Copyright (C) 2001-2020 af en eller flere af følgende forfattere: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; og andre medlemmer af WSJT Development Group. " +"Algoritmerne, kildekoden, udseendet og funktionen af ​​WSJT-X og relaterede programmer og protokolspecifikationer for Mode FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 er Copyright (C) 2001-2021 af en eller flere af følgende forfattere: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; og andre medlemmer af WSJT Development Group. " @@ -4147,7 +4148,57 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + Hjælpetekst til Tastetur genveje + <tabelcelleafstand = 1> + <tr><td> <b> Esc </b></td> <td> Stop Tx, afbryd QSO, ryd kø ved næste kald </td> </tr> + <tr><td> <b> F1 </b></td> <td> Online brugervejledning (Alt: transmitter Tx6) </td> </tr> + <tr><td> <b> Shift + F1 </b></td> <td> Meddelelse om ophavsret </td> </tr> + <tr><td> <b> Ctrl + F1 </b></td> <td> Om WSJT-X </td> </tr> + <tr><td> <b> F2 </b></td> <td> Åbn indstillingsvinduet (Alt: send Tx2) </td> </tr> + <tr><td> <b> F3 </b></td> <td> Vis tastaturgenveje (Alt: transmitter Tx3) </td> </tr> + <tr><td> <b> F4 </b></td> <td> Ryd DX Call, DX Grid, Tx meddelelser 1-4 (Alt: send Tx4) </td> </tr> + <tr><td> <b> Alt + F4 </b></td> <td> Afslutningsprogram </td> </tr> + <tr><td> <b> F5 </b></td> <td> Vis specielle musekommandoer (Alt: transmitter Tx5) </td> </tr> +<tr><td> <b> F6 </b></td> <td> Åbn næste fil i biblioteket (Alt: skift "Call 1st") </td> </tr> + <tr><td> <b> Shift + F6 </b></td> <td> Dekod alle resterende filer i biblioteket </td> </tr> + <tr><td> <b> F7 </b></td> <td> Vis vindue for gennemsnitsmeddelelse </td> </tr> + <tr><td> <b> F11 </b></td> <td> Flyt Rx-frekvensen ned 1 Hz </td> </tr> + <tr><td> <b> Ctrl + F11 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser ned 1 Hz </td> </tr> + <tr><td> <b> Shift + F11 </b></td> <td> Flyt Tx-frekvensen 60 Hz ned (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F11 </b></td> <td> Flyt kaldefrekvensen 2000 Hz ned </td> </tr> + <tr><td> <b> F12 </b></td> <td> Flyt Rx-frekvensen 1 Hz op </td> </tr> + <tr><td> <b> Ctrl + F12 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser 1 Hz op </td> </tr> +<tr><td> <b> Ctrl + F11 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser ned 1 Hz </td> </tr> + <tr><td> <b> Shift + F11 </b></td> <td> Flyt Tx-frekvensen ned 60 Hz (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F11 </b></td> <td> Flyt kaldefrekvensen ned 2000 Hz </td> </tr> + <tr><td> <b> F12 </b></td> <td> Flyt Rx-frekvensen op 1 Hz </td> </tr> + <tr><td> <b> Ctrl + F12 </b></td> <td> Flyt identiske Rx- og Tx-frekvenser 1 Hz op </td> </tr> + <tr><td> <b> Shift + F12 </b></td> <td> Flyt Tx-frekvensen 60 Hz op (FT8) eller 90 Hz (FT4) </td> </tr> + <tr><td> <b> Ctrl + Shift + F12 </b></td> <td> Flyt kaldefrekvensen 2000 Hz op</td> </tr> + <tr><td> <b> Alt + 1-6 </b></td> <td> Indstil NU transmission til dette nummer på fane 1 </td> </tr> + <tr><td> <b> Ctl + 1-6 </b></td> <td> Indstil næste transmission til dette nummer på fane 1 </td> </tr> + <tr><td> <b> Alt + B </b></td> <td> Skift status "Bedste S + P" </td> </tr> + <tr><td> <b> Alt + C </b></td> <td> Skift afkrydsningsfelt "Kald 1st" </td> </tr> + <tr><td> <b> Alt + D </b></td> <td> Dekod igen ved QSO-frekvens </td> </tr> + <tr><td> <b> Shift + D </b></td> <td> Fuld Dekodning (begge vinduer) </td> </tr> +<tr><td> <b> Ctrl + E </b></td> <td> Aktiver TX lige / 1. </td> </tr> + <tr><td> <b> Shift + E </b></td> <td> Deaktiver TX lige / 1. </td> </tr> + <tr><td> <b> Alt + E </b></td><td>Sætning</td> </tr> + <tr><td> <b> Ctrl + F </b></td> <td> Rediger fri tekstmeddelelsesfelt </td> </tr> + <tr><td> <b> Alt + G </b></td> <td> Generer standardmeddelelser </td> </tr> + <tr><td> <b> Alt + H </b></td> <td> Stop Tx </td> </tr> + <tr><td> <b> Ctrl + L </b></td> <td> Opslag af kaldesignal i database, generer standardbeskeder </td> </tr> + <tr><td> <b> Alt + M </b></td><td> Skærm</td> </tr> + <tr><td> <b> Alt + N </b></td> <td> Aktivér Tx </td> </tr> + <tr><td> <b> Ctrl + O </b></td> <td> Åbn en .wav-fil </td> </tr> + <tr><td> <b> Alt + O </b></td> <td> Skift operatør </td> </tr> + <tr><td> <b> Alt + Q </b></td> <td> Log QSO </td> </tr> + <tr><td> <b> Ctrl + R </b></td> <td> Indstil Tx4-besked til RRR (ikke i FT4) </td> </tr> + <tr><td> <b> Alt + R </b></td> <td> Indstil Tx4-besked til RR73 </td> </tr> + <tr><td> <b> Alt + S </b></td> <td> Stop overvågning </td> </tr> + <tr><td> <b> Alt + T </b></td> <td> Skift Tune status </td> </tr> + <tr><td> <b> Alt + Z </b></td> <td> Ryd fyldt buffer dekoderstatus </td> </tr> +</tabel> <table cellspacing=1> @@ -5527,7 +5578,7 @@ Fejl(%2): %3 Monitor returns to last used frequency - Montor til seneste brugte frekvens + Monitor til seneste brugte frekvens @@ -5622,7 +5673,7 @@ den stille periode, når dekodningen er udført. Serial Port Parameters - Seriek Port Parametre + Seriel Port Parametre @@ -5723,7 +5774,7 @@ den stille periode, når dekodningen er udført. Default - Deafult + Default diff --git a/translations/wsjtx_en.ts b/translations/wsjtx_en.ts index ed8512833..a2bc82d3a 100644 --- a/translations/wsjtx_en.ts +++ b/translations/wsjtx_en.ts @@ -3831,7 +3831,7 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_en_GB.ts b/translations/wsjtx_en_GB.ts index d51b44d29..08dc1f470 100644 --- a/translations/wsjtx_en_GB.ts +++ b/translations/wsjtx_en_GB.ts @@ -3831,7 +3831,7 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_es.ts b/translations/wsjtx_es.ts index 38da0087a..72c269de4 100644 --- a/translations/wsjtx_es.ts +++ b/translations/wsjtx_es.ts @@ -2904,13 +2904,13 @@ Amarillo cuando esta muy bajo. Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Marca a TX en minutos o secuencias de números pares, a partir de 0; desmarca las secuencias impares. - Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares. + Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares. Tx even/1st Alternar periodo TX Par/Impar - TX segundo par + Tx primer par/1ro @@ -4411,13 +4411,13 @@ Error al cargar datos de usuarios de LotW If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Si haces un uso justo de cualquier parte de WSJT-X bajo los términos de la Licencia Pública General de GNU, debes mostrar el siguiente aviso de copyright de manera destacada en tú trabajo derivado: -"Los algoritmos, el código fuente, la apariencia de WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2020 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". +"Los algoritmos, el código fuente, la apariencia de WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2021 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". Si haces un uso justo de cualquier parte de WSJT-X bajo los términos de la Licencia Pública General de GNU, debes mostrar el siguiente aviso de derechos de autor (copyright) de manera destacada en tu trabajo derivado: -"Los algoritmos, el código fuente, la apariencia y comportamiento del WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2020 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". +"Los algoritmos, el código fuente, la apariencia y comportamiento del WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2021 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". diff --git a/translations/wsjtx_it.ts b/translations/wsjtx_it.ts index 3e7b28528..778e1c3b4 100644 --- a/translations/wsjtx_it.ts +++ b/translations/wsjtx_it.ts @@ -4063,10 +4063,10 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." Se si utilizza in modo equo qualsiasi parte di WSJT-X in base ai termini della GNU General Public License, è necessario visualizzare in modo evidente la seguente nota sul copyright nell'opera derivata: -"Gli algoritmi, il codice sorgente, l'aspetto di WSJT-X e dei relativi programmi e le specifiche del protocollo per le modalità FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 sono Copyright (C) 2001-2020 di uno o più dei seguenti autori: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q e altri membri del WSJT Development Group. " +"Gli algoritmi, il codice sorgente, l'aspetto di WSJT-X e dei relativi programmi e le specifiche del protocollo per le modalità FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 sono Copyright (C) 2001-2021 di uno o più dei seguenti autori: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q e altri membri del WSJT Development Group. " diff --git a/translations/wsjtx_ja.ts b/translations/wsjtx_ja.ts index 0cf5f52bb..d8927464f 100644 --- a/translations/wsjtx_ja.ts +++ b/translations/wsjtx_ja.ts @@ -625,7 +625,7 @@ Format: Not found audio device missing - + 見つかりません @@ -2703,12 +2703,12 @@ When not checked you can view the calibration results. F High - + F 高 F Low - + F 低 @@ -2962,12 +2962,12 @@ ENTERを押してテキストを登録リストに追加. SWL Mode - + SWLモード Hide lower panel controls to maximize deocde windows - + 下部制御パネルを非表示にしてデコードウィンドウを最大化 Calling CQ @@ -3825,7 +3825,7 @@ ENTERを押してテキストを登録リストに追加. Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + サンプル大量欠落 - %3から始まる%1個(%2秒)のオーディオフレームが欠落 @@ -3850,7 +3850,7 @@ ENTERを押してテキストを登録リストに追加. Enumerating audio devices - + オーディオデバイスを列挙 @@ -4032,7 +4032,7 @@ ENTERを押してテキストを登録リストに追加. If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index cc7652ad6..90e083071 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -388,7 +388,7 @@ path: "%1% - 目錄: "%1% + 目录: "%1% @@ -504,7 +504,12 @@ Format: 您必须输入有效的 ARRL RTTY Roundup 交换数据 - + + Pending DNS lookup, please try again later + 等待域名系统查找,请稍后再试 + + + Reset Decode Highlighting 重置解码突出显示 @@ -519,7 +524,17 @@ Format: WSJT-X 解码文本字体选择 - + + UDP server DNS lookup failed + UDP服务器域名系统查找失败 + + + + MAC-ambiguous multicast groups addresses not supported + 不支持媒体访问控制不明确的多播组地址 + + + Load Working Frequencies 载入工作频率 @@ -2670,12 +2685,12 @@ Not available to nonstandard callsign holders. <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - <html><head/><body><p>子模式確定音調間距; A 最窄.</p></body></html> + <html><head/><body><p>子模式确定音调间距离; A 最窄.</p></body></html> Submode determines tone spacing; A is narrowest. - 子模式確定音調間距; A 最窄. + 子模式确定音调间距离; A 最窄. @@ -3664,12 +3679,12 @@ list. The list can be maintained in Settings (F2). 降低系统负载 - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 - + Error Scanning ADIF Log 扫描 ADIF 日志错误 @@ -3870,16 +3885,16 @@ list. The list can be maintained in Settings (F2). "fmt.all" 文件将重命名为 "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: -"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." +"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2021 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." - + No data read from disk. Wrong file format? 没有从磁盘读取数据. 文件格式出错误? @@ -3899,42 +3914,7 @@ list. The list can be maintained in Settings (F2). 键盘快捷键 - - Special Mouse Commands - 特殊鼠标组合 - - - - No more files to open. - 没有要打开的文件. - - - - Spotting to PSK Reporter unavailable - 无法发送至PSK Reporter - - - - Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - 请选择其他发射频率. WSJT-X 不会故意传输另一个模式在 WSPR 30米子波段上. - - - - WSPR Guard Band - WSPR保护波段 - - - - Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - 请选择其它频率. WSJT-X 不会运行狐狸模式在标准 FT8 波段. - - - - Fox Mode warning - 狐狸模式警告 - - - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4028,7 +4008,12 @@ list. The list can be maintained in Settings (F2). </table> - + + Special Mouse Commands + 特殊鼠标组合 + + + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4092,6 +4077,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> + + + No more files to open. + 没有要打开的文件. + + + + Spotting to PSK Reporter unavailable + 发送到 Pskreporter 不可用 + + + + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. + 请选择另一个发射频率. WSJT-X 不会故意在 30m 的 WSPR 子频段中传输另一种模式. + + + + WSPR Guard Band + WSPR 守护波段 + + + + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. + 请选择另一个频率. WSJT-X在标准的FT8子带中不会以狐狸模式工作. + + + + Fox Mode warning + 狐狸模式警告 + Last Tx: %1 @@ -5409,6 +5424,11 @@ quiet period when decoding is done. Data bits 数据位元 + + + Data Bits + 数据位元 + D&efault @@ -5434,6 +5454,11 @@ quiet period when decoding is done. Stop bits 停止位元 + + + Stop Bits + 停止位元 + @@ -5615,7 +5640,7 @@ or bandwidth is selected). None - + @@ -5748,7 +5773,32 @@ transmitting periods. 向外发射输出. - + + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> + <html><head/><body><p>输入WSJT-X应该向其发送更新的UDP服务器的服务端口号. 如果该值为零则不会发送任何更新.</p></body></html> + + + + Outgoing interfaces: + 传出接口: + + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + <html><head/><body><p>向多播组地址发送更新时需要指定将更新发送到哪个网络接口. 如果环回接口支持多播那么将至少选择该接口.</p><p>对于大多数用户来说环回接口是他们所需要的, 这将允许同一台机器上的多个其他应用程序与WSJT-X进行互操作. 如果运行在其他主机上的应用程序要接收状态更新则应使用合适的网络接口.</p><p>在某些Linux系统上可能需要在环回网络接口上启用多播.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + <html><head/><body><p>设置允许多点传送数据报的资料元或路由器资料元. 几乎每个人都应该将该值设置为 1 以保持出站多点传送流量在本地子网中.</p></body></html> + + + + Multicast TTL: + 多点传送 TTL: + + + Days since last upload 自上次上传以来的天数 @@ -5808,7 +5858,7 @@ both here. 启用甚高频和子模式功能 - + Ou&tput: 输出(&t): @@ -6525,7 +6575,7 @@ Right click for insert and delete options. <html><head/><body><p>Generate Tx audio with four times the normal tone spacing. Intended for special LF/MF transmitters that use a divide-by-4 before generating RF.</p></body></html> - <html><head/><body><p>具有正常音調間距四倍的發射音頻. 適用於在產生射頻之前使用除以 4 的特殊 LF/MF 發射器.</p></body></html> + <html><head/><body><p>具有正常音调间距四倍的发射音频. 适用于在产生射频之前使用除以 4 的特殊 LF/MF 发射器.</p></body></html> diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index 7bfff1f4e..a4507e9a2 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -504,7 +504,12 @@ Format: 您必須輸入有效的 ARRL RTTY Roundup 交換數據 - + + Pending DNS lookup, please try again later + 等待 DNS 查找, 請稍後再試 + + + Reset Decode Highlighting 重置解碼突出顯示 @@ -519,7 +524,17 @@ Format: WSJT-X 解碼文本字體選擇 - + + UDP server DNS lookup failed + UDP 伺服器 DNS 尋找失敗 + + + + MAC-ambiguous multicast groups addresses not supported + MAC 模棱兩可的多播組位址不受支援 + + + Load Working Frequencies 載入工作頻率 @@ -1956,7 +1971,7 @@ Error: %2 - %3 Satellite - 卫星 + 衛星 @@ -2434,7 +2449,7 @@ Yellow when too low If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. - 如果橙色或红色出现表示无线电设备控制故障, 请单击以重置并读取频率. S 表示异频模式. + 如果橙色或紅色出現表示無線電設備控制故障, 請按下以重置並讀取頻率. S 表示異頻模式. @@ -3873,13 +3888,13 @@ list. The list can be maintained in Settings (F2). If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2021 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: -"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." +"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2021 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." - + No data read from disk. Wrong file format? 沒有從磁盤讀取數據. 檔案格式錯誤? @@ -3899,7 +3914,7 @@ list. The list can be maintained in Settings (F2). 鍵盤快捷鍵 - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -3993,7 +4008,7 @@ list. The list can be maintained in Settings (F2). </table> - + Special Mouse Commands 特殊滑鼠組合 @@ -5410,6 +5425,11 @@ quiet period when decoding is done. Data bits 數據位元 + + + Data Bits + 數據位元 + D&efault @@ -5435,6 +5455,11 @@ quiet period when decoding is done. Stop bits 停止位元 + + + Stop Bits + 停止位元 + @@ -5465,7 +5490,7 @@ quiet period when decoding is done. &None - 無(&N) + @@ -5749,7 +5774,32 @@ transmitting periods. 向外發射輸出. - + + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> + <html><head/><body><p>輸入 WSJT-X 應向其發送更新的 UDP 伺服器的服務埠號. 如果這是零將不發送任何更新.</p></body></html> + + + + Outgoing interfaces: + 傳出介面: + + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + <html><head/><body><p>向組播組地址發送更新時需要指定要將其發送到哪個網路介面. 如果環回介面支援組播則至少將選擇該介面.</p><p>對於大多數用戶來說迴圈回式介面是所有需要的, 將允許同一台電腦上的多個其他應用程式與 WSJT-X 進行互通. 如果在其他主機上運行的應用程式要接收狀態更新則應使用合適的網路介面.</p><p>在某些 Linux 系統上可能需要在環回網路介面上啟用組播.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + <html><head/><body><p>設置允許組播數據報進行的數位或路由器躍點. 幾乎每個人都應該將此設置為 1 以保持傳出的組播流量與本地子網.</p></body></html> + + + + Multicast TTL: + 組播 TTL TTL: + + + Days since last upload 自上次上傳以來的天數 @@ -5809,7 +5859,7 @@ both here. 啟用甚高頻和子模式功能 - + Ou&tput: 輸出(&t): @@ -6001,7 +6051,7 @@ and DX Grid fields when a 73 or free text message is sent. Log automatically (contesting only) - 日誌自記錄 (僅限競赛) + 日誌自動記錄 (僅限競赛) diff --git a/widgets/MultiGeometryWidget.hpp b/widgets/MultiGeometryWidget.hpp new file mode 100644 index 000000000..a9386189c --- /dev/null +++ b/widgets/MultiGeometryWidget.hpp @@ -0,0 +1,92 @@ +#ifndef MULTI_GEOMETRY_WIDGET_HPP__ +#define MULTI_GEOMETRY_WIDGET_HPP__ + +#include +#include +#include + +#include +#include +#include + +// +// Class MultiGeometryWidget - Decorate a QWidget type with +// switchable geometries +// +// The abstract base class imbues a Qt Widget type with N alternative +// geometries. Sub-classes can initialise the currently selected +// geometry and the initial geometries using geometries. To switch +// geometry call select_geometry(n) which saves the current geometry +// and switches to the n'th saved geometry. +// +template +class MultiGeometryWidget + : public Widget +{ +public: + template + explicit MultiGeometryWidget (Args&&... args) + : Widget {std::forward (args)...} + , current_geometry_ {0} + { + } + + void geometries (std::size_t current + , std::array const& the_geometries = std::array {}) + { + Q_ASSERT (current < the_geometries.size ()); + saved_geometries_ = the_geometries; + current_geometry_ = current; + Widget::restoreGeometry (saved_geometries_[current_geometry_]); + } + + std::array const& geometries () const {return saved_geometries_;} + std::size_t current () {return current_geometry_;} + + // Call this to select a new geometry denoted by the 'n' argument, + // any actual layout changes should be made in the implementation of + // the change_layout operation below. + void select_geometry (std::size_t n) + { + Q_ASSERT (n < N); + auto geometry = Widget::saveGeometry (); + change_layout (n); + saved_geometries_[current_geometry_] = geometry; + current_geometry_ = n; + + // Defer restoration of the window geometry until the layour + // request event has been processed, this is necessary otherwise + // the final geometry may be affected by widgets not shown in the + // new layout. + desired_geometry_ = saved_geometries_[n]; + } + +protected: + virtual ~MultiGeometryWidget () {} + +private: + // Override this operation to implement any layout changes for the + // geometry specified by the argument 'n'. + virtual void change_layout (std::size_t n) = 0; + + bool event (QEvent * e) override + { + auto ret = Widget::event (e); + if (QEvent::LayoutRequest == e->type () + && desired_geometry_.size ()) + { + // Restore the new desired geometry and flag that we have done + // so by clearing the desired_geometry_ member variable. + QByteArray geometry; + std::swap (geometry, desired_geometry_); + Widget::restoreGeometry (geometry); + } + return ret; + } + + std::size_t current_geometry_; + std::array saved_geometries_; + QByteArray desired_geometry_; +}; + +#endif diff --git a/widgets/about.cpp b/widgets/about.cpp index b8e0fab43..7989f5c9b 100644 --- a/widgets/about.cpp +++ b/widgets/about.cpp @@ -18,12 +18,12 @@ CAboutDlg::CAboutDlg(QWidget *parent) : + " " + revision ()}.simplified () + "
" "WSJT-X implements a number of digital modes designed for
" "weak-signal Amateur Radio communication.

" - "© 2001-2020 by Joe Taylor, K1JT, Bill Somerville, G4WJS,
" + "© 2001-2021 by Joe Taylor, K1JT, Bill Somerville, G4WJS,
" "and Steve Franke, K9AN.

" "We gratefully acknowledge contributions from AC6SL, AE4JY,
" "DF2ET, DJ0OT, G3WDG, G4KLA, IV3NWV, IW3RAB, KA1GT, K3WYC,
" "KA6MAL, KA9Q, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR,
" - "VE1SKY, VK3ACF, VK4BDJ, VK7MO, W4TI, W4TV, and W9MDB.

" + "VE1SKY, VK3ACF, VK4BDJ, VK7MO, W3DJS, W4TI, W4TV, and W9MDB.

" "WSJT-X is licensed under the terms of Version 3
" "of the GNU General Public License (GPL)

" "" diff --git a/widgets/colorhighlighting.cpp b/widgets/colorhighlighting.cpp index 6ad0bd4da..e7e9deddb 100644 --- a/widgets/colorhighlighting.cpp +++ b/widgets/colorhighlighting.cpp @@ -1,7 +1,7 @@ #include "colorhighlighting.h" #include -#include +#include #include "SettingsGroup.hpp" #include "models/DecodeHighlightingModel.hpp" @@ -113,16 +113,16 @@ void ColorHighlighting::set_items (DecodeHighlightingModel const& highlighting_m default: continue; } - auto palette = example->parentWidget ()->palette (); + auto style_sheet = example->parentWidget ()->styleSheet (); if (Qt::NoBrush != item.background_.style ()) { - palette.setColor (QPalette::Window, item.background_.color ()); + style_sheet += QString {"; background-color: #%1"}.arg (item.background_.color ().rgb (), 8, 16, QLatin1Char {'0'}); } if (Qt::NoBrush != item.foreground_.style ()) { - palette.setColor (QPalette::WindowText, item.foreground_.color ()); + style_sheet += QString {"; color: #%1"}.arg (item.foreground_.color ().rgb (), 8, 16, QLatin1Char {'0'}); } - example->setPalette (palette); + example->setStyleSheet (style_sheet); example->setEnabled (item.enabled_); label->setText (DecodeHighlightingModel::highlight_name (item.type_)); label->setEnabled (item.enabled_); diff --git a/widgets/displaytext.cpp b/widgets/displaytext.cpp index d498f180e..b083defc0 100644 --- a/widgets/displaytext.cpp +++ b/widgets/displaytext.cpp @@ -15,6 +15,7 @@ #include #include "Configuration.hpp" +#include "Decoder/decodedtext.h" #include "Network/LotWUsers.hpp" #include "models/DecodeHighlightingModel.hpp" #include "logbook/logbook.h" diff --git a/widgets/displaytext.h b/widgets/displaytext.h index 3b577e619..773901cea 100644 --- a/widgets/displaytext.h +++ b/widgets/displaytext.h @@ -8,11 +8,10 @@ #include #include -#include "Decoder/decodedtext.h" - class QAction; class Configuration; class LogBook; +class DecodedText; class DisplayText : public QTextEdit diff --git a/widgets/logqso.cpp b/widgets/logqso.cpp index 7a74b86cf..f49274494 100644 --- a/widgets/logqso.cpp +++ b/widgets/logqso.cpp @@ -1,5 +1,6 @@ #include "logqso.h" +#include #include #include #include @@ -61,6 +62,9 @@ LogQSO::LogQSO(QString const& programTitle, QSettings * settings ui->comboBoxPropMode->addItem (prop_mode.name_, prop_mode.id_); } loadSettings (); + auto date_time_format = QLocale {}.dateFormat (QLocale::ShortFormat) + " hh:mm:ss"; + ui->start_date_time->setDisplayFormat (date_time_format); + ui->end_date_time->setDisplayFormat (date_time_format); ui->grid->setValidator (new MaidenheadLocatorValidator {this}); } diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index cd260df5b..bec116e6e 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -211,8 +211,8 @@ namespace QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"}; auto quint32_max = std::numeric_limits::max (); constexpr int N_WIDGETS {36}; - constexpr int rx_chunk_size {3456}; // audio samples at 12000 Hz - constexpr int tx_audio_buffer_size {48000 / 5}; // audio frames at 48000 Hz + constexpr int default_rx_audio_buffer_frames {-1}; // lets Qt decide + constexpr int default_tx_audio_buffer_frames {-1}; // lets Qt decide bool message_is_73 (int type, QStringList const& msg_parts) { @@ -236,7 +236,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, unsigned downSampleFactor, QSplashScreen * splash, QProcessEnvironment const& env, QWidget *parent) : - QMainWindow(parent), + MultiGeometryWidget {parent}, m_env {env}, m_network_manager {this}, m_valid {true}, @@ -265,6 +265,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_soundInput {new SoundInput}, m_modulator {new Modulator {TX_SAMPLE_RATE, NTMAX}}, m_soundOutput {new SoundOutput}, + m_rx_audio_buffer_frames {0}, + m_tx_audio_buffer_frames {0}, m_msErase {0}, m_secBandChanged {0}, m_freqNominal {0}, @@ -455,6 +457,11 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_modulator->moveToThread (&m_audioThread); m_soundInput->moveToThread (&m_audioThread); m_detector->moveToThread (&m_audioThread); + bool ok; + auto buffer_size = env.value ("WSJT_RX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); + m_rx_audio_buffer_frames = ok && buffer_size ? buffer_size : default_rx_audio_buffer_frames; + buffer_size = env.value ("WSJT_TX_AUDIO_BUFFER_FRAMES", "0").toInt (&ok); + m_tx_audio_buffer_frames = ok && buffer_size ? buffer_size : default_tx_audio_buffer_frames; // hook up sound output stream slots & signals and disposal connect (this, &MainWindow::initializeAudioOutputStream, m_soundOutput, &SoundOutput::setFormat); @@ -935,14 +942,14 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, if (!m_config.audio_input_device ().isNull ()) { Q_EMIT startAudioInputStream (m_config.audio_input_device () - , rx_chunk_size * m_downSampleFactor + , m_rx_audio_buffer_frames , m_detector, m_downSampleFactor, m_config.audio_input_channel ()); } if (!m_config.audio_output_device ().isNull ()) { Q_EMIT initializeAudioOutputStream (m_config.audio_output_device () , AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2 - , tx_audio_buffer_size); + , m_tx_audio_buffer_frames); } Q_EMIT transmitFrequency (ui->TxFreqSpinBox->value () - m_XIT); @@ -1022,10 +1029,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, } ui->pbBestSP->setVisible(m_mode=="FT4"); - if(!ui->cbMenus->isChecked()) { - ui->cbMenus->setChecked(true); - ui->cbMenus->setChecked(false); - } + // this must be the last statement of constructor if (!m_valid) throw std::runtime_error {"Fatal initialization exception"}; } @@ -1035,9 +1039,9 @@ void MainWindow::not_GA_warning_message () MessageBox::critical_message (this, "This is a pre-release version of WSJT-X 2.3.0 made\n" "available for testing purposes. By design it will\n" - "be nonfunctional after 0000 UTC on Jan 19, 2021."); + "be nonfunctional after 0000 UTC on Jan 26, 2021."); auto now = QDateTime::currentDateTimeUtc (); - if (now >= QDateTime {{2021, 1, 19}, {0, 0}, Qt::UTC}) { + if (now >= QDateTime {{2021, 1, 26}, {0, 0}, Qt::UTC}) { Q_EMIT finished (); } } @@ -1094,8 +1098,33 @@ MainWindow::~MainWindow() void MainWindow::writeSettings() { m_settings->beginGroup("MainWindow"); - m_settings->setValue ("geometry", saveGeometry ()); - m_settings->setValue ("geometryNoControls", m_geometryNoControls); + if (ui->actionSWL_Mode->isChecked ()) + { + m_settings->setValue ("SWLView", true); + m_settings->setValue ("ShowMenus", ui->cbMenus->isChecked ()); + m_settings->setValue ("geometry", geometries ()[0]); + m_settings->setValue ("SWLModeGeometry", saveGeometry ()); + m_settings->setValue ("geometryNoControls", geometries ()[2]); + } + else + { + if (ui->cbMenus->isChecked()) + { + m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); + m_settings->setValue ("ShowMenus", true); + m_settings->setValue ("geometry", saveGeometry ()); + m_settings->setValue ("SWLModeGeometry", geometries ()[1]); + m_settings->setValue ("geometryNoControls", geometries ()[2]); + } + else + { + m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); + m_settings->setValue ("ShowMenus", false); + m_settings->setValue ("geometry", geometries ()[0]); + m_settings->setValue ("SWLModeGeometry", geometries ()[1]); + m_settings->setValue ("geometryNoControls", saveGeometry ()); + } + } m_settings->setValue ("state", saveState ()); m_settings->setValue("MRUdir", m_path); m_settings->setValue("TxFirst",m_txFirst); @@ -1105,7 +1134,6 @@ void MainWindow::writeSettings() m_settings->setValue ("MsgAvgDisplayed", m_msgAvgWidget && m_msgAvgWidget->isVisible ()); m_settings->setValue ("FoxLogDisplayed", m_foxLogWindow && m_foxLogWindow->isVisible ()); m_settings->setValue ("ContestLogDisplayed", m_contestLogWindow && m_contestLogWindow->isVisible ()); - m_settings->setValue("ShowMenus",ui->cbMenus->isChecked()); m_settings->setValue("CallFirst",ui->cbFirst->isChecked()); m_settings->setValue("HoundSort",ui->comboBoxHoundSort->currentIndex()); m_settings->setValue("FoxNlist",ui->sbNlist->value()); @@ -1159,9 +1187,8 @@ void MainWindow::writeSettings() m_settings->setValue("pwrBandTuneMemory",m_pwrBandTuneMemory); m_settings->setValue ("FT8AP", ui->actionEnable_AP_FT8->isChecked ()); m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ()); - m_settings->setValue("SplitterState",ui->splitter->saveState()); + m_settings->setValue("SplitterState",ui->decodes_splitter->saveState()); m_settings->setValue("Blanker",ui->sbNB->value()); - m_settings->setValue ("SWLView", ui->actionSWL_Mode->isChecked ()); { QList coeffs; // suitable for QSettings @@ -1180,8 +1207,17 @@ void MainWindow::readSettings() ui->cbAutoSeq->setVisible(false); ui->cbFirst->setVisible(false); m_settings->beginGroup("MainWindow"); - restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); - m_geometryNoControls = m_settings->value ("geometryNoControls",saveGeometry()).toByteArray(); + std::array the_geometries; + the_geometries[0] = m_settings->value ("geometry", saveGeometry ()).toByteArray (); + the_geometries[1] = m_settings->value ("SWLModeGeometry", saveGeometry ()).toByteArray (); + the_geometries[2] = m_settings->value ("geometryNoControls", saveGeometry ()).toByteArray (); + auto SWL_mode = m_settings->value ("SWLView", false).toBool (); + auto show_menus = m_settings->value ("ShowMenus", true).toBool (); + ui->actionSWL_Mode->setChecked (SWL_mode); + ui->cbMenus->setChecked (show_menus); + auto current_view_mode = SWL_mode ? 1 : show_menus ? 0 : 2; + change_layout (current_view_mode); + geometries (current_view_mode, the_geometries); restoreState (m_settings->value ("state", saveState ()).toByteArray ()); ui->dxCallEntry->setText (m_settings->value ("DXcall", QString {}).toString ()); ui->dxGridEntry->setText (m_settings->value ("DXgrid", QString {}).toString ()); @@ -1191,7 +1227,6 @@ void MainWindow::readSettings() auto displayMsgAvg = m_settings->value ("MsgAvgDisplayed", false).toBool (); auto displayFoxLog = m_settings->value ("FoxLogDisplayed", false).toBool (); auto displayContestLog = m_settings->value ("ContestLogDisplayed", false).toBool (); - ui->cbMenus->setChecked(m_settings->value("ShowMenus",true).toBool()); ui->cbFirst->setChecked(m_settings->value("CallFirst",true).toBool()); ui->comboBoxHoundSort->setCurrentIndex(m_settings->value("HoundSort",3).toInt()); ui->sbNlist->setValue(m_settings->value("FoxNlist",12).toInt()); @@ -1265,10 +1300,8 @@ void MainWindow::readSettings() m_pwrBandTuneMemory=m_settings->value("pwrBandTuneMemory").toHash(); ui->actionEnable_AP_FT8->setChecked (m_settings->value ("FT8AP", false).toBool()); ui->actionEnable_AP_JT65->setChecked (m_settings->value ("JT65AP", false).toBool()); - ui->splitter->restoreState(m_settings->value("SplitterState").toByteArray()); + ui->decodes_splitter->restoreState(m_settings->value("SplitterState").toByteArray()); ui->sbNB->setValue(m_settings->value("Blanker",0).toInt()); - ui->actionSWL_Mode->setChecked (m_settings->value ("SWLView", false).toBool ()); - on_actionSWL_Mode_triggered (ui->actionSWL_Mode->isChecked ()); { auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients" , QList {0., 0., 0., 0., 0.}).toList (); @@ -1567,7 +1600,7 @@ void MainWindow::dataSink(qint64 frames) m_saveWAVWatcher.setFuture (QtConcurrent::run (std::bind (&MainWindow::save_wave_file, this, m_fnameWE, &dec_data.d2[0], samples, m_config.my_callsign(), m_config.my_grid(), m_mode, m_nSubMode, m_freqNominal, m_hisCall, m_hisGrid))); - if (m_mode=="WSPR" or m_mode=="FST4W") { + if (m_mode=="WSPR") { QString c2name_string {m_fnameWE + ".c2"}; int len1=c2name_string.length(); char c2name[80]; @@ -1821,7 +1854,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog if(m_config.restart_audio_input () && !m_config.audio_input_device ().isNull ()) { Q_EMIT startAudioInputStream (m_config.audio_input_device () - , rx_chunk_size * m_downSampleFactor + , m_rx_audio_buffer_frames , m_detector, m_downSampleFactor , m_config.audio_input_channel ()); } @@ -1829,7 +1862,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog if(m_config.restart_audio_output () && !m_config.audio_output_device ().isNull ()) { Q_EMIT initializeAudioOutputStream (m_config.audio_output_device () , AudioDevice::Mono == m_config.audio_output_channel () ? 1 : 2 - , tx_audio_buffer_size); + , m_tx_audio_buffer_frames); } displayDialFrequency (); @@ -2561,44 +2594,59 @@ void MainWindow::on_actionCopyright_Notice_triggered() "\"The algorithms, source code, look-and-feel of WSJT-X and related " "programs, and protocol specifications for the modes FSK441, FT8, JT4, " "JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) " - "2001-2020 by one or more of the following authors: Joseph Taylor, " + "2001-2021 by one or more of the following authors: Joseph Taylor, " "K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, " "IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; " "Philip Karn, KA9Q; and other members of the WSJT Development Group.\""); MessageBox::warning_message(this, message); } +// Implement the MultiGeometryWidget::change_layout() operation. +void MainWindow::change_layout (std::size_t n) +{ + switch (n) + { + case 1: // SWL view + ui->menuBar->show (); + ui->lower_panel_widget->hide (); + trim_view (false); // ensure we can switch back + break; + + case 2: // hide menus view + ui->menuBar->hide (); + ui->lower_panel_widget->show (); + trim_view (true); + break; + + default: // normal view + ui->menuBar->setVisible (ui->cbMenus->isChecked ()); + ui->lower_panel_widget->show (); + trim_view (!ui->cbMenus->isChecked ()); + break; + } +} + void MainWindow::on_actionSWL_Mode_triggered (bool checked) { - ui->lower_panel_widget->setVisible (!checked); - if (checked) - { - hideMenus (false); // make sure we can be turned off - } + select_geometry (checked ? 1 : ui->cbMenus->isChecked () ? 0 : 2); } // This allows the window to shrink by removing certain things // and reducing space used by controls -void MainWindow::hideMenus(bool checked) +void MainWindow::trim_view (bool checked) { int spacing = checked ? 1 : 6; if (checked) { statusBar ()->removeWidget (&auto_tx_label); - minimumSize().setHeight(450); - minimumSize().setWidth(700); - restoreGeometry(m_geometryNoControls); - updateGeometry(); } else { - m_geometryNoControls = saveGeometry(); statusBar ()->addWidget(&auto_tx_label); - minimumSize().setHeight(520); - minimumSize().setWidth(770); } - ui->menuBar->setVisible(!checked); - if(m_mode!="FreqCal" and m_mode!="WSPR" and m_mode!="FST4W") { + if (m_mode != "FreqCal" && m_mode != "WSPR" && m_mode != "FST4W") { ui->lh_decodes_title_label->setVisible(!checked); + ui->rh_decodes_title_label->setVisible(!checked); } ui->lh_decodes_headings_label->setVisible(!checked); + ui->rh_decodes_headings_label->setVisible(!checked); ui->gridLayout_5->layout()->setSpacing(spacing); ui->horizontalLayout_2->layout()->setSpacing(spacing); ui->horizontalLayout_5->layout()->setSpacing(spacing); @@ -3025,8 +3073,8 @@ void MainWindow::decode() //decode() dec_data.params.nutc=dec_data.params.nutc/100; } if(dec_data.params.nagain==0 && dec_data.params.newdat==1 && (!m_diskData)) { - auto t_start = qt_truncate_date_time_to (QDateTime::currentDateTimeUtc (), m_TRperiod * 1.e3); - auto t = t_start.time (); + m_dateTimeSeqStart = qt_truncate_date_time_to (QDateTime::currentDateTimeUtc (), m_TRperiod * 1.e3); + auto t = m_dateTimeSeqStart.time (); dec_data.params.nutc = t.hour () * 100 + t.minute (); if (m_TRperiod < 60.) { @@ -3400,19 +3448,21 @@ void MainWindow::readFromStdout() //readFromStdout ui->cbCQonly->isVisible() && ui->cbCQonly->isChecked(), haveFSpread, fSpread); - if(m_bBestSPArmed and m_mode=="FT4") { + if(m_bBestSPArmed && m_mode=="FT4" && CALLING == m_QSOProgress) { QString messagePriority=ui->decodedTextBrowser->CQPriority(); if(messagePriority!="") { if(messagePriority=="New Call on Band" and m_BestCQpriority!="New Call on Band" and m_BestCQpriority!="New Multiplier") { m_BestCQpriority="New Call on Band"; + m_bDoubleClicked = true; processMessage(decodedtext0); } if(messagePriority=="New DXCC" and m_BestCQpriority!="New DXCC" and m_BestCQpriority!="New Multiplier") { m_BestCQpriority="New DXCC"; + m_bDoubleClicked = true; processMessage(decodedtext0); } } @@ -3521,7 +3571,16 @@ void MainWindow::readFromStdout() //readFromStdout decodedtext.deCallAndGrid(/*out*/deCall,grid); { auto t = Radio::base_callsign (ui->dxCallEntry->text ()); - if ((t == deCall || ui->dxCallEntry->text () == deCall || !t.size ()) && rpt.size ()) m_rptRcvd = rpt; + auto const& dx_call = decodedtext.call (); + if (rpt.size () // report in message + && (m_baseCall == Radio::base_callsign (dx_call) // for us + || "DE" == dx_call) // probably for us + && (t == deCall // DX station base call is QSO partner + || ui->dxCallEntry->text () == deCall // DX station full call is QSO partner + || !t.size ())) // not in QSO + { + m_rptRcvd = rpt; + } } // extract details and send to PSKreporter int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; @@ -4085,7 +4144,14 @@ void MainWindow::guiUpdate() } } - m_currentMessage = QString::fromLatin1(msgsent); + { + auto temp = m_currentMessage; + m_currentMessage = QString::fromLatin1(msgsent); + if (m_currentMessage != temp) // check if tx message changed + { + statusUpdate (); + } + } m_bCallingCQ = CALLING == m_QSOProgress || m_currentMessage.contains (QRegularExpression {"^(CQ|QRZ) "}); if(m_mode=="FT8" or m_mode=="FT4") { @@ -5918,7 +5984,11 @@ void MainWindow::displayWidgets(qint64 n) if(i==31) ui->cbRxAll->setVisible(b); if(i==32) ui->cbCQonly->setVisible(b); if(i==33) ui->sbTR_FST4W->setVisible(b); - if(i==34) ui->sbF_Low->setVisible(b); + if (34 == i) // adjust the stacked widget + { + ui->opt_controls_stack->setCurrentIndex (b ? 1 : 0); + ui->sbF_Low->setVisible(b); + } if(i==35) ui->sbF_High->setVisible(b); j=j>>1; } @@ -7562,10 +7632,6 @@ void MainWindow::on_sbTR_valueChanged(int value) progressBar.setMaximum (value); } if(m_mode=="FST4") chk_FST4_freq_range(); - if(m_monitoring) { - on_stopButton_clicked(); - on_monitorButton_clicked(true); - } if(m_transmitting) { on_stopTxButton_clicked(); } @@ -8348,7 +8414,8 @@ void MainWindow::statusUpdate () const m_hisGrid, m_tx_watchdog, submode != QChar::Null ? QString {submode} : QString {}, m_bFastMode, static_cast (m_config.special_op_id ()), - ftol, tr_period, m_multi_settings->configuration_name ()); + ftol, tr_period, m_multi_settings->configuration_name (), + m_currentMessage); } void MainWindow::childEvent (QChildEvent * e) @@ -8431,7 +8498,7 @@ void MainWindow::update_watchdog_label () void MainWindow::on_cbMenus_toggled(bool b) { - hideMenus(!b); + select_geometry (!b ? 2 : ui->actionSWL_Mode->isChecked () ? 1 : 0); } void MainWindow::on_cbCQonly_toggled(bool) diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index c51a418de..7dfbf8a7e 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -26,6 +26,7 @@ #include #include +#include "MultiGeometryWidget.hpp" #include "NonInheritingProcess.hpp" #include "Audio/AudioDevice.hpp" #include "commons.h" @@ -94,7 +95,8 @@ class MultiSettings; class EqualizationToolsDialog; class DecodedText; -class MainWindow : public QMainWindow +class MainWindow + : public MultiGeometryWidget<3, QMainWindow> { Q_OBJECT; @@ -130,7 +132,8 @@ public slots: void msgAvgDecode2(); void fastPick(int x0, int x1, int y); -protected: +private: + void change_layout (std::size_t) override; void keyPressEvent (QKeyEvent *) override; void closeEvent(QCloseEvent *) override; void childEvent(QChildEvent *) override; @@ -353,7 +356,7 @@ private: void astroUpdate (); void writeAllTxt(QString message); void auto_sequence (DecodedText const& message, unsigned start_tolerance, unsigned stop_tolerance); - void hideMenus(bool b); + void trim_view (bool b); void foxTest(); void setColorHighlighting(); void chkFT4(); @@ -401,6 +404,8 @@ private: SoundInput * m_soundInput; Modulator * m_modulator; SoundOutput * m_soundOutput; + int m_rx_audio_buffer_frames; + int m_tx_audio_buffer_frames; QThread m_audioThread; qint64 m_msErase; diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 6ffcf9a24..948bfc68f 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -2,20 +2,6 @@ MainWindow - - - 0 - 0 - 805 - 589 - - - - - 0 - 0 - - WSJT-X by K1JT @@ -25,13 +11,7 @@ - - - - 0 - 2 - - + Qt::Horizontal @@ -154,18 +134,6 @@ - - - 0 - 10 - - - - - 200 - 100 - - QFrame::StyledPanel @@ -313,18 +281,6 @@ true - - - 0 - 10 - - - - - 200 - 100 - - Qt::ScrollBarAlwaysOn @@ -342,6 +298,12 @@ + + + 0 + 0 + + 0 @@ -590,7 +552,7 @@ - + @@ -773,7 +735,7 @@ Yellow when too low
0 - + @@ -865,7 +827,17 @@ Yellow when too low - + + + + Add callsign and locator to database + + + Add + + + + @@ -887,20 +859,17 @@ Yellow when too low - - + + - Callsign of station to be worked + Search for callsign in database - - - - Qt::AlignCenter + &Lookup - + @@ -992,20 +961,10 @@ Yellow when too low - - + + - Search for callsign in database - - - &Lookup - - - - - - - Locator of station to be worked + Callsign of station to be worked @@ -1015,13 +974,16 @@ Yellow when too low - - + + - Add callsign and locator to database + Locator of station to be worked - Add + + + + Qt::AlignCenter @@ -1116,7 +1078,7 @@ Yellow when too low - + 0 @@ -1130,187 +1092,140 @@ Yellow when too low 0 - - - + + + - - - - 0 - 0 - - - - - 20 - 0 - - - - - 50 - 20 - + + + false - Set Tx frequency to Rx Frequency + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> - - Set Tx frequency to Rx Frequency - - - - - - - - - - Frequency tolerance (Hz) - - - Qt::AlignCenter + + Frequency to call CQ on in kHz above the current MHz - F Tol + Tx CQ 1 - 1000 + 999 - 10 + 260 - - - - 0 - 0 - - - - - 20 - 0 - - - - - 50 - 20 - + + + false - Set Rx frequency to Tx Frequency + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> - - Set Rx frequency to Tx Frequency + + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. +Not available to nonstandard callsign holders. - + + + + + + + + Rx All Freqs - - - - true - - - - 0 - 0 - - - - Toggle Tx mode - - - Tx JT9 @ - - + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + Fox + + + Qt::AlignCenter + + + + + + + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> + + + Check to monitor Sh messages. + + + SWL + + + + + + + Enable auto response to the first decode from a new DXCC or new call on the current band. + + + QPushButton:checked { + color: rgb(0, 0, 0); + background-color: red; + border-style: outset; + border-width: 1px; + border-radius: 5px; + border-color: black; + min-width: 5em; + padding: 3px; +} + + + Best S+P + + + true + + + + + + + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> + + + Check this to start recording calibration data. +While measuring calibration correction is disabled. +When not checked you can view the calibration results. + + + Measure + + + + - - - - Audio Tx frequency - - - Qt::AlignCenter - - - Hz - - - Tx - - - 200 - - - 5000 - - - 1500 - - - - - - - <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - - - Submode determines tone spacing; A is narrowest. - - - Qt::AlignCenter - - - Submode - - - 0 - - - 7 - - - - - - - Qt::AlignCenter - - - - - - F High - - - 100 - - - 5000 - - - 50 - - - 1400 - - - - + @@ -1379,319 +1294,429 @@ Yellow when too low - - - - Qt::AlignCenter - - - F Low - - - 100 - - - 5000 - - - 50 - - - 600 - - - - - - - <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> - - - Double-click on another caller to queue that call for your next QSO. - - - Next Call - - - Qt::AlignCenter - - - - - - - Audio Rx frequency - - - Qt::AlignCenter - - - Hz - - - Rx - - - 200 - - - 5000 - - - 1500 - - - - - - - <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> - - - Tx/Rx or Frequency calibration sequence length - - - Qt::AlignCenter - - - s - - - T/R - - - 5 - - - 1800 - - - 30 - - - - - - - - - false - - - <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> - - - Frequency to call CQ on in kHz above the current MHz - - - Tx CQ - - - 1 - - - 999 - - - 260 - - - - - - - false - - - <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> - - - Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. -Not available to nonstandard callsign holders. - - - - - - - - - - Rx All Freqs - - - - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Tx# - - - 1 - - - 4095 - - - - - - - <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> - - - Check to keep Tx frequency fixed when double-clicking on decoded text. - - - Hold Tx Freq - - - - - - - <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> - - - Synchronizing threshold. Lower numbers accept weaker sync signals. - - - Qt::AlignCenter - - - Sync - - - -1 - - - 10 - - - 1 - - - - - - <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> - - - Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. - - - Tx even/1st - - - - - + - - - - 0 - 0 - + + + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> - - - 100 - 16777215 - + + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. - Fox + Tx even/1st + + + + + + + Audio Tx frequency Qt::AlignCenter + + Hz + + + Tx + + + 200 + + + 5000 + + + 1500 + - + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 50 + 20 + + + + Set Tx frequency to Rx Frequency + + + Set Tx frequency to Rx Frequency + + + + + + + + + + Frequency tolerance (Hz) + + + Qt::AlignCenter + + + F Tol + + + 1 + + + 1000 + + + 10 + + + + + + + + 0 + 0 + + + + + 20 + 0 + + + + + 50 + 20 + + + + Set Rx frequency to Tx Frequency + + + Set Rx frequency to Tx Frequency + + + + + + + + + + - <html><head/><body><p>Check to monitor Sh messages.</p></body></html> + Audio Rx frequency + + + Qt::AlignCenter + + + Hz + + + Rx + + + 200 + + + 5000 + + + 1500 + + + + + + + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - Check to monitor Sh messages. + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - - SWL + + Qt::AlignCenter + + + Report + + + -50 + + + 49 + + + -15 - - - QPushButton:checked { - color: rgb(0, 0, 0); - background-color: red; - border-style: outset; - border-width: 1px; - border-radius: 5px; - border-color: black; - min-width: 5em; - padding: 3px; -} - - - Best S+P - - - true - - - - - + - <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> - Check this to start recording calibration data. -While measuring calibration correction is disabled. -When not checked you can view the calibration results. + Tx/Rx or Frequency calibration sequence length - - Measure + + Qt::AlignCenter + + + s + + + T/R + + + 5 + + + 1800 + + + 30 - - - - <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - - - Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - - - Qt::AlignCenter - - - Report - - - -50 - - - 49 - - - -15 - - + + + + + + true + + + + 0 + 0 + + + + Toggle Tx mode + + + Tx JT9 @ + + + + + + + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> + + + Check to keep Tx frequency fixed when double-clicking on decoded text. + + + Hold Tx Freq + + + + + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> + + + Double-click on another caller to queue that call for your next QSO. + + + Next Call + + + Qt::AlignCenter + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Tx# + + + 1 + + + 4095 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::AlignCenter + + + F Low + + + 100 + + + 5000 + + + 50 + + + 600 + + + + + + + Qt::AlignCenter + + + + + + F High + + + 100 + + + 5000 + + + 50 + + + 1400 + + + + + + + + + + + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> + + + Submode determines tone spacing; A is narrowest. + + + Qt::AlignCenter + + + Submode + + + 0 + + + 7 + + + + + + + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> + + + Synchronizing threshold. Lower numbers accept weaker sync signals. + + + Qt::AlignCenter + + + Sync + + + -1 + + + 10 + + + 1 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + - + Qt::Vertical @@ -1730,84 +1755,6 @@ When not checked you can view the calibration results. - - - - Send this message in next Tx interval - - - margin-left: 10%; margin-right: 0% - - - - - - Ctrl+2 - - - - - - - <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - - - Send this message in next Tx interval -Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - - - margin-left: 10%; margin-right: 0% - - - - - - Ctrl+1 - - - - - - - Switch to this Tx message NOW - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &2 - - - Alt+2 - - - - - - - - - - <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - - - Switch to this Tx message NOW -Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - - - Qt::LeftToRight - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &1 - - - Alt+1 - - - @@ -1827,59 +1774,24 @@ Double click to toggle the use of the Tx1 message to start a QSO with a station - - - - - + + - <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> - - - Send this message in next Tx interval -Double-click to reset to the standard 73 message - - - margin-left: 10%; margin-right: 0% + Queue up the next Tx message - + Next - - Ctrl+5 + + Qt::AlignCenter - - - - Send this message in next Tx interval - - - margin-left: 10%; margin-right: 0% - + + - - Ctrl+3 - - - - - - - Switch to this Tx message NOW - - - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% - - - Tx &3 - - - Alt+3 - @@ -1903,24 +1815,30 @@ RR73 messages should only be used when you are reasonably confident that no mess - - + + - <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - Switch to this Tx message NOW -Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) -RR73 messages should only be used when you are reasonably confident that no message repetitions will be required + Send this message in next Tx interval +Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + margin-left: 10%; margin-right: 0% - Tx &4 + - Alt+4 + Ctrl+1 + + + + + + + @@ -1944,8 +1862,24 @@ Double-click to reset to the standard 73 message - - + + + + Switch to this Tx message NOW + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &2 + + + Alt+2 + + + + + @@ -1960,6 +1894,28 @@ Double-click to reset to the standard 73 message + + + + Send this message in next Tx interval + + + margin-left: 10%; margin-right: 0% + + + + + + Ctrl+2 + + + + + + + + + @@ -1970,6 +1926,66 @@ Double-click to reset to the standard 73 message + + + + Switch to this Tx message NOW + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &3 + + + Alt+3 + + + + + + + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> + + + Switch to this Tx message NOW +Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) +RR73 messages should only be used when you are reasonably confident that no message repetitions will be required + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &4 + + + Alt+4 + + + + + + + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> + + + Switch to this Tx message NOW +Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) + + + Qt::LeftToRight + + + padding-left: 15%; padding-right: 15%; padding-top: 3%; padding-bottom: 3% + + + Tx &1 + + + Alt+1 + + + @@ -1986,6 +2002,22 @@ Double-click to reset to the standard 73 message + + + + Send this message in next Tx interval + + + margin-left: 10%; margin-right: 0% + + + + + + Ctrl+3 + + + @@ -2002,30 +2034,23 @@ list. The list can be maintained in Settings (F2). - - - - - - - - - - - - - - - - + + - Queue up the next Tx message + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> + + + Send this message in next Tx interval +Double-click to reset to the standard 73 message + + + margin-left: 10%; margin-right: 0% - Next + - - Qt::AlignCenter + + Ctrl+5 @@ -2803,7 +2828,7 @@ list. The list can be maintained in Settings (F2). 0 0 - 805 + 834 21 diff --git a/widgets/widegraph.cpp b/widgets/widegraph.cpp index a369f6296..fa3f1320e 100644 --- a/widgets/widegraph.cpp +++ b/widgets/widegraph.cpp @@ -13,12 +13,6 @@ #include "SettingsGroup.hpp" #include "moc_widegraph.cpp" -namespace -{ - auto user_defined = QObject::tr ("User Defined"); - float swide[MAX_SCREENSIZE]; -} - WideGraph::WideGraph(QSettings * settings, QWidget *parent) : QDialog(parent), ui(new Ui::WideGraph), @@ -26,7 +20,8 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : m_palettes_path {":/Palettes"}, m_tr0 {0.0}, m_n {0}, - m_bHaveTransmitted {false} + m_bHaveTransmitted {false}, + m_user_defined {tr ("User Defined")} { ui->setupUi(this); @@ -103,8 +98,8 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : if(t==m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); index++; } - ui->paletteComboBox->addItem (user_defined); - if (user_defined == m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); + ui->paletteComboBox->addItem (m_user_defined); + if (m_user_defined == m_waterfallPalette) ui->paletteComboBox->setCurrentIndex(index); readPalette (); } @@ -147,7 +142,7 @@ void WideGraph::saveSettings() //saveS void WideGraph::drawRed(int ia, int ib) { - ui->widePlot->drawRed(ia,ib,swide); + ui->widePlot->drawRed(ia,ib,m_swide); } void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dataSink2 @@ -181,8 +176,8 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dat ss += sp; smax=qMax(smax,sp); } -// swide[j]=nbpp*smax; - swide[j]=nbpp*ss; +// m_swide[j]=nbpp*smax; + m_swide[j]=nbpp*ss; } // Time according to this computer @@ -192,7 +187,7 @@ void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dat float flagValue=1.0e30; if(m_bHaveTransmitted) flagValue=2.0e30; for(int i=0; iwidePlot->draw(swide,true,false); + ui->widePlot->draw(m_swide,true,false); } } @@ -238,7 +233,7 @@ void WideGraph::keyPressEvent(QKeyEvent *e) //F1 void WideGraph::setRxFreq(int n) //setRxFreq { ui->widePlot->setRxFreq(n); - ui->widePlot->draw(swide,false,false); + ui->widePlot->draw(m_swide,false,false); } int WideGraph::rxFreq() //rxFreq @@ -384,7 +379,7 @@ void WideGraph::readPalette () //readPalette { try { - if (user_defined == m_waterfallPalette) + if (m_user_defined == m_waterfallPalette) { ui->widePlot->setColours (WFPalette {m_userPalette}.interpolate ()); } @@ -437,7 +432,7 @@ void WideGraph::on_adjust_palette_push_button_clicked (bool) //Adjust Palette { if (m_userPalette.design ()) { - m_waterfallPalette = user_defined; + m_waterfallPalette = m_user_defined; ui->paletteComboBox->setCurrentText (m_waterfallPalette); readPalette (); } @@ -479,8 +474,8 @@ void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2 { ui->widePlot->setPlot2dGain(value); if(ui->widePlot->scaleOK ()) { - ui->widePlot->draw(swide,false,false); - if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true); + ui->widePlot->draw(m_swide,false,false); + if(m_mode=="QRA64") ui->widePlot->draw(m_swide,false,true); } } @@ -488,8 +483,8 @@ void WideGraph::on_zero2dSlider_valueChanged(int value) //Zero2 { ui->widePlot->setPlot2dZero(value); if(ui->widePlot->scaleOK ()) { - ui->widePlot->draw(swide,false,false); - if(m_mode=="QRA64") ui->widePlot->draw(swide,false,true); + ui->widePlot->draw(m_swide,false,false); + if(m_mode=="QRA64") ui->widePlot->draw(m_swide,false,true); } } diff --git a/widgets/widegraph.h b/widgets/widegraph.h index f5f70c281..421fc8213 100644 --- a/widgets/widegraph.h +++ b/widgets/widegraph.h @@ -117,6 +117,8 @@ private: QString m_mode; QString m_modeTx; QString m_waterfallPalette; + float m_swide[MAX_SCREENSIZE]; + QString m_user_defined; }; #endif // WIDEGRAPH_H diff --git a/wsjtx_log_config.ini b/wsjtx_log_config.ini index f4e8ed339..cd97bb2ee 100644 --- a/wsjtx_log_config.ini +++ b/wsjtx_log_config.ini @@ -20,15 +20,15 @@ AutoFlush="false" # Line Formats available: TimeStamp, Uptime, Severity, LineID (counter), ProcessID, ThreadID, Line, File, Function # TimeStamp and Uptime support boost date time format: # http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags -Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %File%(%Line%) %Function%: %Message%" +Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Channel%][%Severity%] %File%(%Line%) %Function%: %Message%" # Target directory in which rotated files will be stored. -Target="${AppLocalDataLocation}/old_logs" +Target="${AppLocalDataLocation}/logs" # FileName pattern to use. %N is a counter for files. FileName="${AppLocalDataLocation}/wsjtx_syslog.log" -TargetFileName="${AppLocalDataLocation}/old_logs/wsjtx_syslog_%Y-%m-%d_%H-%M-%S.%N.log" +TargetFileName="${AppLocalDataLocation}/old_logs/wsjtx_syslog_%Y-%m_%2N.log" # RotationSize in bytes, File size, in bytes, upon which file rotation will be performed. # Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs. -RotationSize="1048576" +RotationSize="5242880" # 5 Mbyte # If Append is true then do not start a new log file for each session Append="true" # EnableFinalRotation will rotate on close, make this false if using Append true @@ -36,10 +36,10 @@ EnableFinalRotation="false" # Matching used so that only files matching FileName pattern are deleted. ScanForFiles="Matching" # MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted. -#MaxSize=100485760 +MaxSize="1073741824" # 1 Gbyte total # MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted. -#MinFreeSpace=1485760 -MaxFiles="10" +MinFreeSpace="42949672960" # 40 Gbyte +MaxFiles="50" # Specify level of log, options are: trace, debug, info, warning, error, fatal # Since Channel not part of filter all log output will be included. # If only SYSLOG logging desired, change to: Filter="%Severity% >= trace & %Channel% matches \"SYSLOG\"" @@ -58,20 +58,20 @@ Append="true" # http://www.boost.org/doc/libs/1_60_0/doc/html/date_time/date_time_io.html#date_time.format_flags Format="[%TimeStamp(format=\"%Y-%m-%d %H:%M:%S.%f\")%][%Uptime(format=\"%O:%M:%S.%f\")%][%Severity%] %Message%" # Target directory in which rotated files will be stored. -Target="${AppLocalDataLocation}/old_logs" +Target="${AppLocalDataLocation}/logs" # FileName pattern to use. %N is a counter for files. FileName="${AppLocalDataLocation}/wsjtx_datalog.log" TargetFileName="wsjtx_datalog_%5N.log" # RotationSize in bytes, File size, in bytes, upon which file rotation will be performed. # Time based rotation also available via RotationInterval and RotationTimePoint see boost log docs. -RotationSize="1048576" +RotationSize="5242880" EnableFinalRotation="false" # Matching used so that only files matching FileName pattern are deleted. ScanForFiles="Matching" # MaxSize - Total size of files in the target directory in bytes upon which the oldest file will be deleted. -#MaxSize=100485760 +MaxSize="1073741824" # MinFreeSpace - Minimum free space in the Target directory in bytes. Above this value oldest file is deleted. -#MinFreeSpace=1485760 +MinFreeSpace="42949672960" MaxFiles="10" # Specify level of log, options are: trace, debug, info, warning, error, fatal # Specify Channel otherwise all log output will be included.