Compare commits

..

No commits in common. "master" and "wsjtx-2.6.1" have entirely different histories.

219 changed files with 5868 additions and 32776 deletions

View File

@ -45,7 +45,7 @@ if (POLICY CMP0075)
endif ()
project (wsjtx
VERSION 2.7.0.0
VERSION 2.6.1.0
LANGUAGES C CXX Fortran
)
set (PROJECT_DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio")
@ -71,7 +71,7 @@ message (STATUS "******************************************************")
include (set_build_type)
# RC 0 or omitted is a development build, GA is a General Availability release build
set_build_type (RC 4)
set_build_type (GA)
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
#
@ -161,6 +161,7 @@ endif ()
set (WSJT_PLUGIN_DESTINATION ${PLUGIN_DESTINATION} CACHE PATH "Path for plugins")
set (WSJT_QT_CONF_DESTINATION ${QT_CONF_DESTINATION} CACHE PATH "Path for the qt.conf file")
#
# Project sources
#
@ -221,7 +222,6 @@ set (wsjt_qt_CXXSRCS
widgets/DoubleClickablePushButton.cpp
widgets/DoubleClickableRadioButton.cpp
Network/LotWUsers.cpp
Network/FileDownload.cpp
models/DecodeHighlightingModel.cpp
widgets/DecodeHighlightingListView.cpp
models/FoxLog.cpp
@ -327,7 +327,6 @@ set (wsjt_FSRCS
lib/ft8_decode.f90
lib/ft4_decode.f90
lib/fst4_decode.f90
lib/get_q3list.f90
lib/jt9_decode.f90
lib/options.f90
lib/packjt.f90
@ -362,7 +361,6 @@ set (wsjt_FSRCS
lib/bpdecode128_90.f90
lib/ft8/bpdecode174_91.f90
lib/baddata.f90
lib/cablog.f90
lib/calibrate.f90
lib/ccf2.f90
lib/ccf65.f90
@ -492,7 +490,6 @@ set (wsjt_FSRCS
lib/msk144sim.f90
lib/mskrtd.f90
lib/nuttal_window.f90
lib/decode_msk144.f90
lib/ft4/ft4sim.f90
lib/ft4/ft4sim_mult.f90
lib/ft4/ft4_downsample.f90
@ -512,7 +509,6 @@ set (wsjt_FSRCS
lib/qra/q65/q65_ap.f90
lib/qra/q65/q65_loops.f90
lib/qra/q65/q65_set_list.f90
lib/qra/q65/q65_set_list2.f90
lib/refspectrum.f90
lib/savec2.f90
lib/save_dxbase.f90
@ -584,7 +580,6 @@ set (wsjt_FSRCS
lib/fst4/fastosd240_74.f90
lib/fst4/get_crc24.f90
lib/fst4/fst4_baseline.f90
lib/77bit/hash22calc.f90
)
# temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit
@ -977,10 +972,7 @@ if (Fortran_COMPILER_NAME MATCHES "gfortran.*")
set (CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE} -fbounds-check -funroll-all-loops -fno-f2c -ffpe-summary=invalid,zero,overflow,underflow ${General_FFLAGS}")
### TEMPORARY: Let Fortran use RElEASE flags for DEBUG builds
#set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -g -fbacktrace -fbounds-check -fno-f2c -ffpe-summary=invalid,zero,overflow,underflow ${General_FFLAGS}")
set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_RELEASE} -fbounds-check -funroll-all-loops -fno-f2c -ffpe-summary=invalid,zero,overflow,underflow ${General_FFLAGS}")
set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -g -fbacktrace -fbounds-check -fno-f2c -ffpe-summary=invalid,zero,overflow,underflow ${General_FFLAGS}")
# FPE traps currently disabled in Debug configuration builds until
# we decide if they are meaningful, without these FP instructions
@ -1144,9 +1136,6 @@ target_link_libraries (jt65sim wsjt_fort wsjt_cxx)
add_executable (sumsim lib/sumsim.f90)
target_link_libraries (sumsim wsjt_fort wsjt_cxx)
add_executable (cablog lib/cablog.f90)
target_link_libraries (cablog)
add_executable (test_snr lib/test_snr.f90)
target_link_libraries (test_snr wsjt_fort)
@ -1183,9 +1172,6 @@ target_link_libraries (wsprcode wsjt_fort wsjt_cxx)
add_executable (encode77 lib/77bit/encode77.f90)
target_link_libraries (encode77 wsjt_fort wsjt_cxx)
add_executable (hash22calc lib/77bit/hash22calc.f90)
target_link_libraries (hash22calc wsjt_fort wsjt_cxx)
add_executable (wsprsim ${wsprsim_CSRCS})
target_link_libraries (wsprsim ${LIBM_LIBRARIES})
@ -1434,10 +1420,10 @@ else (${OPENMP_FOUND} OR APPLE)
endif (${OPENMP_FOUND} OR APPLE)
if (WIN32)
# build map65
find_package (Portaudio REQUIRED)
add_subdirectory (map65)
endif ()
add_subdirectory (qmap)
# build the main application
generate_version_info (wsjtx_VERSION_RESOURCES
@ -1603,7 +1589,7 @@ install (TARGETS jt9 wsprd fmtave fcal fmeasure
if(WSJT_BUILD_UTILS)
install (TARGETS ft8code jt65code jt9code jt4code msk144code
q65code fst4sim q65sim echosim hash22calc cablog
q65code fst4sim q65sim echosim
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)
@ -1645,7 +1631,6 @@ install (FILES
cty.dat
cty.dat_copyright.txt
contrib/Ephemeris/JPLEPH
eclipse.txt
DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}
#COMPONENT runtime
)

View File

@ -173,6 +173,7 @@
#include <QJsonDocument>
#include <QJsonArray>
#include "pimpl_impl.hpp"
#include "Logger.hpp"
#include "qt_helpers.hpp"
@ -200,7 +201,6 @@
#include "models/DecodeHighlightingModel.hpp"
#include "logbook/logbook.h"
#include "widgets/LazyFillComboBox.hpp"
#include "Network/FileDownload.hpp"
#include "ui_Configuration.h"
#include "moc_Configuration.cpp"
@ -244,9 +244,6 @@ namespace
|X85|X86|X87|X88|X89|X90|X91
|X92|X93|X94|X95|X96|X97|X98
|X99
|[0][0][0][1-9] # 4-digit numbers
|[0][0-9][1-9][0-9] # between 0001
|[1-7][0-9][0-9][0-9] # and 7999
)
)", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption};
@ -279,6 +276,7 @@ namespace
constexpr quint32 qrg_version_100 {100};
}
//
// Dialog to get a new Frequency item
//
@ -331,9 +329,9 @@ public:
connect (button_box, &QDialogButtonBox::accepted, this, &FrequencyDialog::accept);
connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
connect (start_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect (end_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect (enable_dates_checkbox_, &QCheckBox::stateChanged, this, &FrequencyDialog::toggleValidity);
connect(start_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect(end_date_time_edit_, &QDateTimeEdit::dateTimeChanged, this, &FrequencyDialog::checkSaneDates);
connect(enable_dates_checkbox_, &QCheckBox::stateChanged, this, &FrequencyDialog::toggleValidity);
toggleValidity();
}
@ -386,6 +384,7 @@ private:
QDateTimeEdit *start_date_time_edit_;
};
//
// Dialog to get a new Station item
//
@ -458,6 +457,9 @@ public:
}
};
// Internal implementation of the Configuration class.
class Configuration::impl final
: public QDialog
@ -562,9 +564,6 @@ private:
Q_SLOT void on_add_macro_line_edit_editingFinished ();
Q_SLOT void delete_macro ();
void delete_selected_macros (QModelIndexList);
void after_CTY_downloaded();
void set_CTY_DAT_version(QString const& version);
void error_during_CTY_download (QString const& reason);
Q_SLOT void on_udp_server_line_edit_textChanged (QString const&);
Q_SLOT void on_udp_server_line_edit_editingFinished ();
Q_SLOT void on_save_path_select_push_button_clicked (bool);
@ -575,14 +574,7 @@ private:
Q_SLOT void handle_transceiver_failure (QString const& reason);
Q_SLOT void on_reset_highlighting_to_defaults_push_button_clicked (bool);
Q_SLOT void on_rescan_log_push_button_clicked (bool);
Q_SLOT void on_CTY_download_button_clicked (bool);
Q_SLOT void on_LotW_CSV_fetch_push_button_clicked (bool);
Q_SLOT void on_hamlib_download_button_clicked (bool);
Q_SLOT void on_revert_update_button_clicked (bool);
void error_during_hamlib_download (QString const& reason);
void after_hamlib_downloaded();
void display_file_information();
Q_SLOT void on_cbx2ToneSpacing_clicked(bool);
Q_SLOT void on_cbx4ToneSpacing_clicked(bool);
Q_SLOT void on_prompt_to_log_check_box_clicked(bool);
@ -686,7 +678,6 @@ private:
QString FD_exchange_;
QString RTTY_exchange_;
QString Contest_Name_;
QString hamlib_backed_up_;
qint32 id_interval_;
qint32 ntrials_;
@ -755,12 +746,13 @@ private:
QAudioDeviceInfo next_audio_output_device_;
AudioDevice::Channel audio_output_channel_;
AudioDevice::Channel next_audio_output_channel_;
FileDownload cty_download;
friend class Configuration;
};
#include "Configuration.moc"
// delegate to implementation class
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, LogBook * logbook, QWidget * parent)
@ -867,11 +859,6 @@ bool Configuration::highlight_73 () const {return m_->highlight_73_;}
bool Configuration::highlight_DXcall () const {return m_->highlight_DXcall_;}
bool Configuration::highlight_DXgrid () const {return m_->highlight_DXgrid_;}
void Configuration::set_CTY_DAT_version(QString const& version)
{
m_->set_CTY_DAT_version(version);
}
void Configuration::set_calibration (CalibrationParams params)
{
m_->calibration_ = params;
@ -1010,15 +997,6 @@ void Configuration::set_location (QString const& grid_descriptor)
m_->dynamic_grid_ = grid_descriptor.trimmed ();
}
void Configuration::setSpecial_Q65_Pileup()
{
m_->bSpecialOp_=true;
m_->ui_->gbSpecialOpActivity->setChecked(m_->bSpecialOp_);
m_->ui_->rbQ65pileup->setChecked(true);
m_->SelectedActivity_ = static_cast<int> (SpecialOperatingActivity::Q65_PILEUP);
m_->write_settings();
}
void Configuration::setSpecial_Hound()
{
m_->bSpecialOp_=true;
@ -1041,7 +1019,6 @@ void Configuration::setSpecial_None()
{
m_->bSpecialOp_=false;
m_->ui_->gbSpecialOpActivity->setChecked(m_->bSpecialOp_);
m_->SelectedActivity_ = static_cast<int> (SpecialOperatingActivity::HOUND); // brings backward compatibility to versions without Q65_PILEUP
m_->write_settings();
}
namespace
@ -1197,13 +1174,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
// set up LoTW users CSV file fetching
connect (&lotw_users_, &LotWUsers::load_finished, [this] () {
ui_->LotW_CSV_fetch_push_button->setEnabled (true);
});
connect(&lotw_users_, &LotWUsers::progress, [this] (QString const& msg) {
ui_->LotW_CSV_status_label->setText(msg);
});
ui_->LotW_CSV_fetch_push_button->setEnabled (true);
});
lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv"));
//
@ -1255,7 +1227,6 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
ui_->special_op_activity_button_group->setId (ui_->rbARRL_Digi, static_cast<int> (SpecialOperatingActivity::ARRL_DIGI));
ui_->special_op_activity_button_group->setId (ui_->rbFox, static_cast<int> (SpecialOperatingActivity::FOX));
ui_->special_op_activity_button_group->setId (ui_->rbHound, static_cast<int> (SpecialOperatingActivity::HOUND));
ui_->special_op_activity_button_group->setId (ui_->rbQ65pileup, static_cast<int> (SpecialOperatingActivity::Q65_PILEUP));
//
// setup PTT port combo box drop down content
@ -1571,9 +1542,6 @@ void Configuration::impl::read_settings ()
Contest_Name_ = settings_->value ("Contest_Name",QString {}).toString ();
ui_->Field_Day_Exchange->setText(FD_exchange_);
ui_->RTTY_Exchange->setText(RTTY_exchange_);
ui_->Contest_Name->setText(Contest_Name_);
hamlib_backed_up_ = settings_->value ("HamlibBackedUp",QString {}).toString ();
if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
&& next_font_ != font_)
{
@ -1749,18 +1717,6 @@ void Configuration::impl::read_settings ()
pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool ();
highlight_DXcall_ = settings_->value("highlight_DXcall",false).toBool ();
highlight_DXgrid_ = settings_->value("highlight_DXgrid",false).toBool ();
#ifdef WIN32
QTimer::singleShot (2500, [=] {display_file_information ();});
#else
ui_->hamlib_groupBox->setTitle("Hamlib Version");
ui_->rbHamlib64->setVisible(false);
ui_->rbHamlib32->setVisible(false);
ui_->hamlib_download_button->setVisible(false);
ui_->revert_update_button->setVisible(false);
ui_->backed_up_text->setVisible(false);
ui_->backed_up->setVisible(false);
QTimer::singleShot (2500, [=] {display_file_information ();});
#endif
}
void Configuration::impl::find_audio_devices ()
@ -2446,45 +2402,9 @@ void Configuration::impl::on_reset_highlighting_to_defaults_push_button_clicked
void Configuration::impl::on_rescan_log_push_button_clicked (bool /*clicked*/)
{
if (logbook_) {
logbook_->rescan ();
}
if (logbook_) logbook_->rescan ();
}
void Configuration::impl::on_CTY_download_button_clicked (bool /*clicked*/)
{
ui_->CTY_download_button->setEnabled (false); // disable button until download is complete
QDir dataPath {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
cty_download.configure(network_manager_,
"http://www.country-files.com/bigcty/cty.dat",
dataPath.absoluteFilePath("cty.dat"),
"WSJT-X CTY Downloader");
// set up LoTW users CSV file fetching
connect (&cty_download, &FileDownload::complete, this, &Configuration::impl::after_CTY_downloaded, Qt::UniqueConnection);
connect (&cty_download, &FileDownload::error, this, &Configuration::impl::error_during_CTY_download, Qt::UniqueConnection);
cty_download.start_download();
}
void Configuration::impl::set_CTY_DAT_version(QString const& version)
{
ui_->CTY_file_label->setText(QString{"CTY File Version: %1"}.arg(version));
}
void Configuration::impl::error_during_CTY_download (QString const& reason)
{
MessageBox::warning_message (this, tr ("Error Loading CTY.DAT"), reason);
after_CTY_downloaded();
}
void Configuration::impl::after_CTY_downloaded ()
{
ui_->CTY_download_button->setEnabled (true);
if (logbook_) {
logbook_->rescan ();
ui_->CTY_file_label->setText(QString{"CTY File Version: %1"}.arg(logbook_->cty_version()));
}
}
void Configuration::impl::on_LotW_CSV_fetch_push_button_clicked (bool /*checked*/)
{
lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), true, true);
@ -2499,113 +2419,6 @@ void Configuration::impl::on_decoded_text_font_push_button_clicked ()
);
}
void Configuration::impl::on_hamlib_download_button_clicked (bool /*clicked*/)
{
#ifdef WIN32
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
SettingsGroup g {settings_, "Configuration"};
settings_->setValue ("HamlibBackedUp", hamlib);
settings_->sync ();
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f1 {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
QFile f2 {dataPath.absolutePath() + "/" + "libhamlib-4_new.dll"};
if (f1.exists()) f1.remove();
if (f2.exists()) f2.remove();
ui_->hamlib_download_button->setEnabled (false);
ui_->revert_update_button->setEnabled (false);
if (ui_->rbHamlib32->isChecked()) {
cty_download.configure(network_manager_,
"https://n0nb.users.sourceforge.net/dll32/libhamlib-4.dll",
dataPath.absoluteFilePath("libhamlib-4_new.dll"),
"Downloading latest libhamlib-4.dll");
} else {
cty_download.configure(network_manager_,
"https://n0nb.users.sourceforge.net/dll64/libhamlib-4.dll",
dataPath.absoluteFilePath("libhamlib-4_new.dll"),
"Downloading latest libhamlib-4.dll");
}
connect (&cty_download, &FileDownload::complete, this, &Configuration::impl::after_hamlib_downloaded, Qt::UniqueConnection);
connect (&cty_download, &FileDownload::error, this, &Configuration::impl::error_during_hamlib_download, Qt::UniqueConnection);
cty_download.start_download();
#else
MessageBox::warning_message (this, tr ("Hamlib update only available on Windows."));
#endif
}
void Configuration::impl::error_during_hamlib_download (QString const& reason)
{
QDir dataPath = QCoreApplication::applicationDirPath();
MessageBox::warning_message (this, tr ("Error Loading libhamlib-4.dll"), reason);
ui_->hamlib_download_button->setEnabled (true);
ui_->revert_update_button->setEnabled (true);
}
void Configuration::impl::after_hamlib_downloaded ()
{
QDir dataPath = QCoreApplication::applicationDirPath();
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QTimer::singleShot (1000, [=] {
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4_new.dll", dataPath.absolutePath() + "/" + "libhamlib-4.dll");
});
QTimer::singleShot (2000, [=] {
MessageBox::information_message (this, tr ("Hamlib Update successful \n\nNew Hamlib will be used after restart"));
ui_->revert_update_button->setEnabled (true);
ui_->hamlib_download_button->setEnabled (true);
});
}
void Configuration::impl::on_revert_update_button_clicked (bool /*clicked*/)
{
#ifdef WIN32
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (f.exists()) {
ui_->revert_update_button->setEnabled (false);
ui_->hamlib_download_button->setEnabled (false);
QFile::rename(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_new.dll");
QTimer::singleShot (1000, [=] {
QFile::copy(dataPath.absolutePath() + "/" + "libhamlib-4_old.dll", dataPath.absolutePath() + "/" + "libhamlib-4.dll");
});
QTimer::singleShot (2000, [=] {
MessageBox::information_message (this, tr ("Hamlib successfully reverted \n\nReverted Hamlib will be used after restart"));
ui_->revert_update_button->setEnabled (true);
ui_->hamlib_download_button->setEnabled (true);
});
} else {
MessageBox::warning_message (this, tr ("No Hamlib update found that could be reverted"));
}
#else
MessageBox::warning_message (this, tr ("Hamlib update only available on Windows."));
#endif
}
void Configuration::impl::display_file_information ()
{
#ifdef WIN32
QDir dataPath = QCoreApplication::applicationDirPath();
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
ui_->in_use->setText(hamlib);
QFileInfo fi2(dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QString birthTime2 = fi2.birthTime().toString("yyyy-MM-dd hh:mm");
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (f.exists()) {
if (hamlib_backed_up_=="") {
ui_->backed_up->setText(QString{"no hamlib data available, file saved %1"}.arg(birthTime2));
} else {
ui_->backed_up->setText(hamlib_backed_up_);
}
} else {
ui_->backed_up->setText("");
}
#else
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
ui_->in_use->setText(hamlib);
#endif
}
void Configuration::impl::on_PTT_port_combo_box_activated (int /* index */)
{
set_rig_invariants ();

View File

@ -183,7 +183,6 @@ public:
bool highlight_only_fields () const;
bool include_WAE_entities () const;
bool highlight_73 () const;
void setSpecial_Q65_Pileup();
void setSpecial_Hound();
void setSpecial_Fox();
void setSpecial_None();
@ -191,8 +190,8 @@ public:
bool highlight_DXgrid () const;
bool Individual_Contest_Name() const;
// 0 1 2 3 4 5 6 7 8 9
enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, WW_DIGI, FOX, HOUND, ARRL_DIGI, Q65_PILEUP};
// 0 1 2 3 4 5 6 7 8
enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, WW_DIGI, FOX, HOUND, ARRL_DIGI};
SpecialOperatingActivity special_op_id () const;
struct CalibrationParams
@ -225,7 +224,8 @@ public:
// This method queries if a CAT and PTT connection is operational.
bool is_transceiver_online () const;
// Start the rig connection, safe and normal to call when rig is already open.
// Start the rig connection, safe and normal to call when rig is
// already open.
bool transceiver_online ();
// check if a real rig is configured
@ -243,8 +243,6 @@ public:
// Close down connection to rig.
void transceiver_offline ();
void set_CTY_DAT_version(QString const& version);
// Set transceiver frequency in Hertz.
Q_SLOT void transceiver_frequency (Frequency);

File diff suppressed because it is too large Load Diff

View File

@ -6,34 +6,27 @@ you change the name in the Applications folder from WSJT-X to WSJT-X_previous
before proceeding.
I recommend that you follow the installation instructions especially if you
are moving from v2.5 to v2.6 or later, of WSJT-X or you have upgraded macOS.
are moving from v2.3 to v2.4 or later, of WSJT-X or you have upgraded macOS.
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
Make sure that you leave this window open for the remaining installation steps.
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
Along with this ReadMe file there is a file: com.wsjtx.sysctl.plist which must be copied to a
system area by typing these lines in the Terminal window and then pressing the Return key after
each line.
system area by typing this line in the Terminal window and then pressing the Return key.
sudo cp /Volumes/WSJT-X/com.wsjtx.sysctl.plist /Library/LaunchDaemons
sudo chown root:wheel /Library/LaunchDaemons/com.wsjtx.sysctl.plist
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.)
IMPORTANT: Now re-boot your Mac otherwise these changes will not take effect.
After the reboot you should re-open the Terminal window as before and you can check
that the change has been made by typing:
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
If shmmax is not shown as 52428800 then contact me since WSJT-X will fail to load with
an error message: "Unable to create shared memory segment". If the value of shmmax
is shown as 20971520 then it is probable that you have download JTDX. WSJT-X and JTDX
cannot both control the shmmax paramter. Contact me for advice.
If shmmax is not shown as 52428800 then contact me since WSJT-X might fail to load with
an error message: "Unable to create shared memory segment".
You can now close the Terminal window. It will not be necessary to repeat this procedure
again, even when you download an updated version of WSJT-X. It might be necessary if you
@ -65,17 +58,8 @@ and how to access them.
Finally, visit the Radio panel. WSJT-X is most effective when operated with CAT
control. You will need to install the relevant Mac device driver for your rig,
and then re-launch WSJT-X. Return to the Radio panel in Preferences and in
the "Serial port" panel select your driver from the list that is presented.
You may need a device driver for your Mac. The USB/UART Bridge chip inside the Icom,
Yaesu and Kenwood radios is a Silicon Labs USB to UART Bridge Controller and the Mac
drivers are available here:
https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
Visit the SiLabs site and download v6 for a Mac. Then in WSJT-X if you use the drop-down menu
for Serial Port you should see something like /dev/tty.SLAB_USBtoUART if the driver has been
installed correctly. Make sure you read the release notes that come with the driver.
the "Serial port" panel select your driver from the list that is presented. If you
do not know where to get an appropriate driver, contact me.
WSJT-X needs the Mac clock to be accurate. Visit System Preferences > Date & Time
and make sure that Date and Time are set automatically. The drop-down menu will
@ -88,7 +72,9 @@ Please email me if you have problems.
--- John G4KLA (g4kla@rmnjmn.co.uk)
Addendum: Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X.
Additional Notes:
1. Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X
WSJT-X makes use of a block of memory which is shared between different parts of
the code. The normal allocation of shared memory on a Mac is insufficient and this
@ -113,10 +99,15 @@ be changed.
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 specify more than one interface. I recommend you consult Apple's guide
on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000.
on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000.
2. Preventing WSJT-X from being put into 'sleep' mode (App Nap).
In normal circumstances an application which has not been directly accessed for a while can be
In normal circumstances an application which has not been directly accessed for a while can be
subject to App Nap which means it is suspended until such time as its windows are accessed. If
it is intended that WSJT-X should be submitting continued reports to, for example, PSK Reporter
then reporting will be interrupted. App Nap can be disabled as follows, but first quit WSJT-X:
Open a Terminal window and type: defaults write org.k1jt.wsjtx NSAppSleepDisable -bool YES
If you type: defaults read org.k1jt.wsjtx then the response will be: NSAppSleepDisable = 1;
Close the Terminal window and launch WSJT-X. (If you 'Hide' WSJT-X, this scheme will be suspended.)

36
INSTALL
View File

@ -16,7 +16,8 @@ Installing WSJT-X
Binary packages of WSJT-X are available from the project web site:
https://wsjt.sourceforge.io/wsjtx.html
http://www.physics.princeton.edu/pulsar/K1JT/wsjtx.html
Building from Source
====================
@ -27,7 +28,7 @@ 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.12 or later is required to build WSJT-X.
Qt v5, preferably v5.9 or later is required to build WSJT-X.
Qt v5 multimedia support, serial port, and Linguist is necessary as
well as the core Qt v5 components, normally installing the Qt
@ -50,13 +51,15 @@ 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. WSJT-X can be built with any version
of the Hamlib git master. To build Hamlib from sources something
like the following recipe should suffice:
The Hamlib library is required. Currently WSJT-X needs to be built
using a forked version of the Hamlib git master. This fork contains
patches not yet accepted by the Hamlib development team which are
essential for correct operation of WSJT-X. To build the Hamlib fork
from sources something like the following recipe should suffice:
$ mkdir ~/hamlib-prefix
$ cd ~/hamlib-prefix
$ git clone https://github.com/Hamlib/Hamlib src
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -111,13 +114,13 @@ Building from Source on MS Windows
Because building on MS Windows is quite complicated there is an
Software Development Kit available that provides all the prerequisite
libraries and tools for building WSJT-X. This SDK is called HAMLIB SDK
libraries and tools for building WSJT-X. This SDK is called JT-SDK-QT
which is documented here:
https://sourceforge.net/projects/hamlib-sdk/
http://physics.princeton.edu/pulsar/K1JT/wsjtx-doc/dev-guide-main.html
If you need to build Hamlib rather than use the Hamlib kit included in
the HAMLIB SDK the following recipe should help. Reasons for building
the JT-SDK the following recipe should help. Reasons for building
Hamlib from source might include picking up the very latest patches or
building a different branch that you wish to contribute to.
@ -141,7 +144,7 @@ In an MSYS shell:-
$ mkdir ~/hamib-prefix
$ cd ~/hamlib-prefix
$ git clone https://github.com/Hamlib/Hamlib src
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -176,6 +179,10 @@ Hamlib binary location as one of the paths in CMAKE_PREFIX_PATH.
Building from Source on Apple Mac
=================================
These instructions are adapted from my Evernote page at:
https://www.evernote.com/pub/bsomervi/wsjt-xmacbuilds
There are several ways to get the required GNU and other open source
tools and libraries installed, my preference is MacPorts because it is
easy to use and does everything we need.
@ -222,11 +229,12 @@ instructions are here:
Hamlib
------
First fetch hamlib from the git master repository:
First fetch hamlib from the repository, in this case my fork of Hamlib
3 until the official repository has all the fixes we need:
$ mkdir -p ~/hamlib-prefix/build
$ cd ~/hamlib-prefix
$ git clone https://github.com/Hamlib/Hamlib src
$ git clone git://git.code.sf.net/u/bsomervi/hamlib src
$ cd src
$ git checkout integration
$ ./bootstrap
@ -345,8 +353,8 @@ which installs the WSJT-X application bundle into ~/wsjtx-prefix
Updating and Rebuilding Hamlib
==============================
From time to time new fixes will be pushed to the Hamlib git
master repository. To pick them up type:
From time to time new fixes will be pushed to the Hamlib fork
repository integration branch. To pick them up type:
$ cd ~/hamlib-prefix/src
$ git pull

203
NEWS
View File

@ -9,208 +9,7 @@
\$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc4
March 11, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 4 brings some improvements for Fox-mode
operators, new features for companion program QMAP, and a number of
relatively minor enhancements and bug fixes.
QMAP enhancements -- of particular interest to EME operators:
- QMAP now decodes Q65 submodes with both 60-second and 30-second T/R
sequence lengths. Clicking on a resulting line in the WSJT-X Active
Stations window automatically sets dial frequency and working
submode as needed to call that station.
- QMAP operates in 60-second receive sequences, and its Q65 decoder
starts at t=19.5, 30.0, 49.5, and 58.5 s into the sequence. Most
decoded messages are displayed well before the end of the relevant
time slot.
- A new, more compact file format is now used for wideband data
files. A "Save decoded" option has been added to the Save menu.
- An option has been added to allow exporting a 3 kHz portion of a
wideband data file as a standard WSJT-X *.wav file.
- CTRL+click on QMAP's upper waterfall sends an integer kHz dial
frequency request to WSJT-X.
- With focus on the WSJT-X main window, hit Alt+A on the keyboard to
clear the Active Stations window.
- Many minor enhancements to the User Interface.
WSJT-X:
- Enable decoding of MSK144 from the jt9[.exe] executable.
- Several changes to reduce problems experienced when (contrary to
our recommendations) messages with short (10-bit) callsign hashes
are used in standard FT4/FT8 sub-bands.
Release: WSJT-X 2.7.0-rc3
January 1, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 3 brings some new features, as well as
numerous detail improvements and bug fixes, such as:
- Added a new "Update Hamlib" function. On Windows, it allows the user to
update Hamlib directly from the program. The previously used version is
backed up, so the user can easily revert a hamlib update.
- The Hamlib version in use is now displayed (also on Linux and macOS).
- The FT Roundup Messages protocol has been enhanced. It now allows also
the exchange of static 4-digit numbers instead of serial numbers. This
extends the usability of the FT RU protocol for other contest types.
- Improved direct switching between modes. Submode, as well as the status
of the "Sh" and "Fast" checkboxes are now saved and restored by mode.
- Some right-click events were made more intuitive and consistent.
- Right-clicking the Q65 button enables Q65 Pileup mode, a left-click
brings you back to the normal Q65 mode.
- Right-click the JT65 button to switch to JT9 mode.
- For Q65, all messages for us are now displayed in the right window.
- Message averaging is now allowed only when VHF features are
enabled, and label texts are changed to "Single Period Decodes" and
"Average Decodes" only if averaging is enabled.
- Some improvements to the Hamlib Transceiver code. Behavior is now
more stable when Rig Split has been selected.
- Prevented redundant network communication between WSJT-X and DX Lab
Suite Commander.
- Download of the LotW file now works without OpenSSL libraries.
- Made the spot counter work for WSPR.
- Prevented insertion of an individual contest name when in Fox mode.
- WAE entities are now assigned to the correct DXCC when "Include
extra WAE entities" is not selected.
- Added a utility program 'cablog' which can be used to convert the
wsjtx.log file to Cabrillo format for the ARRL EME contest.
- Minor improvements to the Active Stations window.
- The Rx/Tx frequency for Echo mode has been fixed at 1500 Hz.
- Some corrections and updates to the INSTALL instructions for Linux.
- Updated CTY.DAT file.
Release: WSJT-X 2.7.0-rc2
July 7, 2023
-------------------------
WSJT-X 2.7.0 Release Candidate 2 introduces several minor improvements
and bug fixes.
- CTRL+SHIFT+F11/F12 now changes dial frequency by 1000 Hz instead of
2000 Hz.
- Improved spotting to PSK Reporter for upcoming HamSCI Festivals of
Eclipse Ionospheric Science.
- Added optional Hungarian translation of the user interface.
- Fixed a flaw that could produce false decodes in Q65 submodes D and E.
- Fixed a flaw with the QSO start time. It is now reset when the DX
Call changes.
- Fixed a flaw that prevented contest logging of the ARRL Digi Contest.
- Right-clicking the Q65 mode button to toggle the Q65 Pileup mode on/off
now also works on macOS.
- Fixed a compilation error on macOS Ventura.
- WSPR and FST4W band hopping now works again.
- It is now ensured that "U.S.A." is displayed when using certain
cty.dat files.
- Corrected the problem with duplicated FT8 entries in ActiveStations
window.
Release: WSJT-X 2.7.0-rc1
May 12, 2023
-------------------------
WSJT-X 2.7.0 Release Candidate 1 introduces a new program called QMAP,
a new Special Operating Activity known as Q65 Pileup, and a number of
other enhancements and fixes.
- QMAP and Q65 Pileup mode are of particular interest to those
engaged in Earth-Moon-Earth (EME) communication, but other
applications may be found for them as well.
- QMAP is derived from MAP65, an older program used since 2007 for
EME, mainly on the 2 m band. QMAP provides single-polarization
receive-only capabilities for any one of the 60-second submodes
of Q65. It allows you to monitor all traffic in a 90 kHz subband
while conducting EME QSOs in the usual way with WSJT-X.
- Q65 Pileup mode is a new feature in WSJT-X that will assist DX
operators using Q65 in pileup circumstances with many
simultaneous callers and very weak signals, such as those
experienced by 6-meter EME DXpeditions.
- Further details on QMAP and Q65 Pileup mode are available in a
Quick-Start guide posted here:
https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf
- WSJT-X now provides more efficient spotting to PSK Reporter.
Redundant spots are omitted, and posting of spots is now spread
more widely in time. (Temporarily, in support of the HamSCI
Festivals of Eclipse Ionospheric Science, spots will be transmitted
more frequently during the upcoming solar eclipses.)
- WSJT-X is now able to process more than 100 FT8 decodes in a single
reception interval.
- Improvements to the Fox mode:
- More convenient and efficient handling of the two queues.
- Fox Log window now displays statistical data on the QSO rate.
- When the station locator is changed (e.g during portable
operations), the new locator will be sent automatically to PSK
Reporter.
- The cty.dat file can now be updated by clicking a button on the
Settings -> Colors tab.
- A new status display appears when fetching a new LotW file.
- Multi-streamed messages transmitted by MSHV are now handled
properly when WSJT-X is in Hound mode.
- Auto-sequencing now has better protection against unwanted effects
caused by late FT8 decodes.
- Fixed an inconsistency in which Contest Name was not correctly
remembered.
- Other minor bug fixes.
- Updated hyperlinks to our homepage and to our new WSJT GROUP User
Forum (https://groups.io/g/wsjtgroup/) can now also be found in the
User Guide.
- The build instructions for macOS have been clarified.
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.6.1
January 16, 2023

View File

@ -1,229 +0,0 @@
#include "FileDownload.hpp"
#include <QCoreApplication>
#include <QUrl>
#include <QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QFileInfo>
#include <QDir>
#include <QIODevice>
#include "qt_helpers.hpp"
#include "Logger.hpp"
FileDownload::FileDownload() : QObject(nullptr)
{
redirect_count_ = 0;
url_valid_ = false;
}
FileDownload::~FileDownload()
{
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
void FileDownload::errorOccurred(QNetworkReply::NetworkError code)
{
LOG_INFO(QString{"FileDownload [%1]: errorOccurred %2 -> %3"}.arg(user_agent_).arg(code).arg(reply_->errorString()));
Q_EMIT error (reply_->errorString ());
destfile_.cancelWriting ();
destfile_.commit ();
}
#else
void FileDownload::obsoleteError()
{
LOG_INFO(QString{"FileDownload [%1]: error -> %3"}.arg(user_agent_).arg(reply_->errorString()));
Q_EMIT error (reply_->errorString ());
destfile_.cancelWriting ();
destfile_.commit ();
}
#endif
void FileDownload::configure(QNetworkAccessManager *network_manager, const QString &source_url, const QString &destination_path, const QString &user_agent)
{
manager_ = network_manager;
source_url_ = source_url;
destination_filename_ = destination_path;
user_agent_ = user_agent;
}
void FileDownload::store()
{
if (destfile_.isOpen())
destfile_.write (reply_->read (reply_->bytesAvailable ()));
else
LOG_INFO(QString{ "FileDownload [%1]: file is not open."}.arg(user_agent_));
}
void FileDownload::replyComplete()
{
QFileInfo destination_file(destination_filename_);
QDir tmpdir_(destination_file.absoluteFilePath());
LOG_DEBUG(QString{ "FileDownload [%1]: replyComplete"}.arg(user_agent_));
if (!reply_)
{
Q_EMIT load_finished ();
return; // we probably deleted it in an earlier call
}
QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()};
if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ())
{
if ("https" == redirect_url.scheme () && !QSslSocket::supportsSsl ())
{
Q_EMIT download_error (tr ("Network Error - SSL/TLS support not installed, cannot fetch:\n\'%1\'")
.arg (redirect_url.toDisplayString ()));
url_valid_ = false; // reset
Q_EMIT load_finished ();
}
else if (++redirect_count_ < 10) // maintain sanity
{
// follow redirect
download (reply_->url ().resolved (redirect_url));
}
else
{
Q_EMIT download_error (tr ("Network Error - Too many redirects:\n\'%1\'")
.arg (redirect_url.toDisplayString ()));
url_valid_ = false; // reset
Q_EMIT load_finished ();
}
}
else if (reply_->error () != QNetworkReply::NoError)
{
destfile_.cancelWriting();
destfile_.commit();
url_valid_ = false; // reset
// report errors that are not due to abort
if (QNetworkReply::OperationCanceledError != reply_->error ())
{
Q_EMIT download_error (tr ("Network Error:\n%1")
.arg (reply_->errorString ()));
}
Q_EMIT load_finished ();
}
else
{
if (!url_valid_)
{
// now get the body content
url_valid_ = true;
download (reply_->url ().resolved (redirect_url));
}
else // the body has completed. Save it.
{
url_valid_ = false; // reset
// load the database asynchronously
// future_load_ = std::async (std::launch::async, &LotWUsers::impl::load_dictionary, this, csv_file_.fileName ());
LOG_INFO(QString{ "FileDownload [%1]: complete. File path is %2"}.arg(user_agent_).arg(destfile_.fileName()));
destfile_.commit();
emit complete(destination_filename_);
}
}
if (reply_ && reply_->isFinished ())
{
reply_->deleteLater ();
}
}
void FileDownload::downloadComplete(QNetworkReply *data)
{
// make a temp file in the same place as the file we're downloading. Needs to be on the same
// filesystem as where we eventually want to 'mv' it.
QUrl r = request_.url();
LOG_INFO(QString{"FileDownload [%1]: finished %2 of %3 -> %4 (%5)"}.arg(user_agent_).arg(data->operation()).arg(source_url_).arg(destination_filename_).arg(r.url()));
#ifdef DEBUG_FILEDOWNLOAD
LOG_INFO("Request Headers:");
Q_FOREACH (const QByteArray& hdr, request_.rawHeaderList()) {
LOG_INFO(QString{ "%1 -> %2"}.arg(QString(hdr)).arg(QString(request_.rawHeader(hdr))));
}
LOG_INFO("Response Headers:");
Q_FOREACH (const QByteArray& hdr, reply_->rawHeaderList()) {
LOG_INFO(QString{ "%1 -> %2"}.arg(QString(hdr)).arg(QString(reply_->rawHeader(hdr))));
}
#endif
data->deleteLater();
}
void FileDownload::start_download()
{
url_valid_ = false;
download(QUrl(source_url_));
}
void FileDownload::download(QUrl qurl)
{
request_.setUrl(qurl);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != manager_->networkAccessible ())
{
// try and recover network access for QNAM
manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
LOG_INFO(QString{"FileDownload [%1]: Starting download of %2 to %3"}.arg(user_agent_).arg(source_url_).arg(destination_filename_));
request_.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request_.setRawHeader("Accept", "*/*");
request_.setRawHeader ("User-Agent", user_agent_.toLocal8Bit()); // Must have a UA for some sites, like country-files
if (!url_valid_)
{
reply_ = manager_->head(request_);
}
else
{
reply_ = manager_->get (request_);
}
QObject::connect(manager_, &QNetworkAccessManager::finished, this, &FileDownload::downloadComplete, Qt::UniqueConnection);
QObject::connect(reply_, &QNetworkReply::downloadProgress, this, &FileDownload::downloadProgress, Qt::UniqueConnection);
QObject::connect(reply_, &QNetworkReply::finished, this, &FileDownload::replyComplete, Qt::UniqueConnection);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
QObject::connect(reply_, &QNetworkReply::errorOccurred,this, &FileDownload::errorOccurred, Qt::UniqueConnection);
#else
QObject::connect(reply_, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &FileDownload::obsoleteError, Qt::UniqueConnection);
#endif
QObject::connect(reply_, &QNetworkReply::readyRead, this, &FileDownload::store, Qt::UniqueConnection);
QFileInfo destination_file(destination_filename_);
QString const tmpfile_base = destination_file.fileName();
QString const &tmpfile_path = destination_file.absolutePath();
QDir tmpdir{};
if (!tmpdir.mkpath(tmpfile_path))
{
LOG_INFO(QString{"FileDownload [%1]: Directory %2 does not exist"}.arg(user_agent_).arg(tmpfile_path).arg(
destfile_.errorString()));
}
if (url_valid_) {
destfile_.setFileName(destination_file.absoluteFilePath());
if (!destfile_.open(QSaveFile::WriteOnly | QIODevice::WriteOnly)) {
LOG_INFO(QString{"FileDownload [%1]: Unable to open %2: %3"}.arg(user_agent_).arg(destfile_.fileName()).arg(
destfile_.errorString()));
return;
}
}
}
void FileDownload::downloadProgress(qint64 received, qint64 total)
{
LOG_DEBUG(QString{"FileDownload: [%1] Progress %2 from %3, total %4, so far %5"}.arg(user_agent_).arg(destination_filename_).arg(source_url_).arg(total).arg(received));
Q_EMIT progress(QString{"%4 bytes downloaded"}.arg(received));
}
void FileDownload::abort ()
{
if (reply_ && reply_->isRunning ())
{
reply_->abort ();
}
}

View File

@ -1,54 +0,0 @@
#ifndef WSJTX_FILEDOWNLOAD_H
#define WSJTX_FILEDOWNLOAD_H
#include <QObject>
#include <QString>
#include <QPointer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QTemporaryFile>
#include <QSaveFile>
class FileDownload : public QObject {
Q_OBJECT
public:
explicit FileDownload();
~FileDownload();
void configure(QNetworkAccessManager *network_manager, const QString& source_url, const QString& destination_filename, const QString& user_agent);
private:
QNetworkAccessManager *manager_;
QString source_url_;
QString destination_filename_;
QString user_agent_;
QPointer<QNetworkReply> reply_;
QNetworkRequest request_;
QSaveFile destfile_;
bool url_valid_;
int redirect_count_;
signals:
void complete(QString filename);
void progress(QString filename);
void load_finished() const;
void download_error (QString const& reason) const;
void error(QString const& reason) const;
public slots:
void start_download();
void download(QUrl url);
void store();
void abort();
void downloadComplete(QNetworkReply* data);
void downloadProgress(qint64 recieved, qint64 total);
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
void errorOccurred(QNetworkReply::NetworkError code);
#else
void obsoleteError();
#endif
void replyComplete();
};
#endif //WSJTX_FILEDOWNLOAD_H

View File

@ -16,9 +16,7 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>
#include "qt_helpers.hpp"
#include "Logger.hpp"
#include "FileDownload.hpp"
#include "pimpl_impl.hpp"
#include "moc_LotWUsers.cpp"
@ -41,7 +39,6 @@ public:
, url_valid_ {false}
, redirect_count_ {0}
, age_constraint_ {365}
, connected_ {false}
{
}
@ -51,36 +48,14 @@ public:
auto csv_file_name = csv_file_.fileName ();
auto exists = QFileInfo::exists (csv_file_name);
if (fetch && (!exists || forced_fetch))
{
current_url_.setUrl(url);
if (current_url_.isValid() && !QSslSocket::supportsSsl())
{
current_url_.setScheme("http");
}
redirect_count_ = 0;
Q_EMIT self_->progress (QString("Starting download from %1").arg(url));
lotw_downloader_.configure(network_manager_,
url,
csv_file_name,
"WSJT-X LotW User Downloader");
if (!connected_)
{
connect(&lotw_downloader_, &FileDownload::complete, [this, csv_file_name] {
LOG_INFO(QString{"LotWUsers: Loading LotW file %1"}.arg(csv_file_name));
future_load_ = std::async(std::launch::async, &LotWUsers::impl::load_dictionary, this, csv_file_name);
});
connect(&lotw_downloader_, &FileDownload::error, [this] (QString const& msg) {
LOG_INFO(QString{"LotWUsers: Error downloading LotW file: %1"}.arg(msg));
Q_EMIT self_->LotW_users_error (msg);
});
connect( &lotw_downloader_, &FileDownload::progress, [this] (QString const& msg) {
Q_EMIT self_->progress (msg);
});
connected_ = true;
}
lotw_downloader_.start_download();
current_url_.setUrl (url);
if (current_url_.isValid () && !QSslSocket::supportsSsl ())
{
current_url_.setScheme ("http");
}
redirect_count_ = 0;
download (current_url_);
}
else
{
@ -92,9 +67,142 @@ public:
}
}
void download (QUrl url)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ())
{
// try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
QNetworkRequest request {url};
request.setRawHeader ("User-Agent", "WSJT LotW User Downloader");
request.setOriginatingObject (this);
// this blocks for a second or two the first time it is used on
// Windows - annoying
if (!url_valid_)
{
reply_ = network_manager_->head (request);
}
else
{
reply_ = network_manager_->get (request);
}
connect (reply_.data (), &QNetworkReply::finished, this, &LotWUsers::impl::reply_finished);
connect (reply_.data (), &QNetworkReply::readyRead, this, &LotWUsers::impl::store);
}
void reply_finished ()
{
if (!reply_)
{
Q_EMIT self_->load_finished ();
return; // we probably deleted it in an earlier call
}
QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()};
if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ())
{
if ("https" == redirect_url.scheme () && !QSslSocket::supportsSsl ())
{
Q_EMIT self_->LotW_users_error (tr ("Network Error - SSL/TLS support not installed, cannot fetch:\n\'%1\'")
.arg (redirect_url.toDisplayString ()));
url_valid_ = false; // reset
Q_EMIT self_->load_finished ();
}
else if (++redirect_count_ < 10) // maintain sanity
{
// follow redirect
download (reply_->url ().resolved (redirect_url));
}
else
{
Q_EMIT self_->LotW_users_error (tr ("Network Error - Too many redirects:\n\'%1\'")
.arg (redirect_url.toDisplayString ()));
url_valid_ = false; // reset
Q_EMIT self_->load_finished ();
}
}
else if (reply_->error () != QNetworkReply::NoError)
{
csv_file_.cancelWriting ();
csv_file_.commit ();
url_valid_ = false; // reset
// report errors that are not due to abort
if (QNetworkReply::OperationCanceledError != reply_->error ())
{
Q_EMIT self_->LotW_users_error (tr ("Network Error:\n%1")
.arg (reply_->errorString ()));
}
Q_EMIT self_->load_finished ();
}
else
{
if (url_valid_ && !csv_file_.commit ())
{
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot commit changes to:\n\"%1\"")
.arg (csv_file_.fileName ()));
url_valid_ = false; // reset
Q_EMIT self_->load_finished ();
}
else
{
if (!url_valid_)
{
// now get the body content
url_valid_ = true;
download (reply_->url ().resolved (redirect_url));
}
else
{
url_valid_ = false; // reset
// load the database asynchronously
future_load_ = std::async (std::launch::async, &LotWUsers::impl::load_dictionary, this, csv_file_.fileName ());
}
}
}
if (reply_ && reply_->isFinished ())
{
reply_->deleteLater ();
}
}
void store ()
{
if (url_valid_)
{
if (!csv_file_.isOpen ())
{
// create temporary file in the final location
if (!csv_file_.open (QSaveFile::WriteOnly))
{
abort ();
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot open file:\n\"%1\"\nError(%2): %3")
.arg (csv_file_.fileName ())
.arg (csv_file_.error ())
.arg (csv_file_.errorString ()));
}
}
if (csv_file_.write (reply_->read (reply_->bytesAvailable ())) < 0)
{
abort ();
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot write to file:\n\"%1\"\nError(%2): %3")
.arg (csv_file_.fileName ())
.arg (csv_file_.error ())
.arg (csv_file_.errorString ()));
}
}
}
void abort ()
{
lotw_downloader_.abort();
if (reply_ && reply_->isRunning ())
{
reply_->abort ();
}
}
// Load the database from the given file name
@ -114,14 +222,12 @@ public:
auto pos = l.indexOf (',');
result[l.left (pos)] = QDate::fromString (l.mid (pos + 1, l.indexOf (',', pos + 1) - pos - 1), "yyyy-MM-dd");
}
// qDebug () << "LotW User Data Loaded";
}
else
{
throw std::runtime_error {QObject::tr ("Failed to open LotW users CSV file: '%1'").arg (f.fileName ()).toStdString ()};
}
LOG_INFO(QString{"LotWUsers: Loaded %1 records from %2"}.arg(result.size()).arg(lotw_csv_file));
Q_EMIT self_->progress (QString{"Loaded %1 records from LotW."}.arg(result.size()));
Q_EMIT self_->load_finished();
return result;
}
@ -135,8 +241,6 @@ public:
std::future<dictionary> future_load_;
dictionary last_uploaded_;
qint64 age_constraint_; // days
FileDownload lotw_downloader_;
bool connected_;
};
#include "LotWUsers.moc"
@ -145,7 +249,6 @@ LotWUsers::LotWUsers (QNetworkAccessManager * network_manager, QObject * parent)
: QObject {parent}
, m_ {this, network_manager}
{
}
LotWUsers::~LotWUsers ()

View File

@ -31,7 +31,6 @@ public:
bool user (QString const& call) const;
Q_SIGNAL void LotW_users_error (QString const& reason) const;
Q_SIGNAL void progress (QString const& reason) const;
Q_SIGNAL void load_finished () const;
private:

View File

@ -6,8 +6,6 @@
//
// Reports will be sent in batch mode every 5 minutes.
#include <fstream>
#include <iostream>
#include <cmath>
#include <QObject>
#include <QString>
@ -20,7 +18,6 @@
#include <QByteArray>
#include <QDataStream>
#include <QTimer>
#include <QDir>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#endif
@ -32,26 +29,19 @@
#include "moc_PSKReporter.cpp"
#define DEBUGECLIPSE 0
namespace
{
QLatin1String HOST {"report.pskreporter.info"};
// QLatin1String HOST {"127.0.0.1"};
quint16 SERVICE_PORT {4739};
// quint16 SERVICE_PORT {14739};
int MIN_SEND_INTERVAL {120}; // in seconds
int FLUSH_INTERVAL {MIN_SEND_INTERVAL + 5}; // in send intervals
int MIN_SEND_INTERVAL {15}; // in seconds
int FLUSH_INTERVAL {4 * 5}; // in send intervals
bool ALIGNMENT_PADDING {true};
int MIN_PAYLOAD_LENGTH {508};
int MAX_PAYLOAD_LENGTH {10000};
int CACHE_TIMEOUT {300}; // default to 5 minutes for repeating spots
QMap<QString, time_t> spot_cache;
int MAX_PAYLOAD_LENGTH {1400};
}
static int added;
static int removed;
class PSKReporter::impl final
: public QObject
{
@ -93,7 +83,6 @@ public:
send_receiver_data_ = 3; // three times
}
});
eclipse_load(config->data_dir ().absoluteFilePath ("eclipse.txt"));
}
void check_connection ()
@ -178,7 +167,7 @@ public:
if (!report_timer_.isActive ())
{
report_timer_.start (MIN_SEND_INTERVAL+1 * 1000); // we add 1 to give some more randomization
report_timer_.start (MIN_SEND_INTERVAL * 1000);
}
if (!descriptor_timer_.isActive ())
{
@ -199,8 +188,6 @@ public:
void send_report (bool send_residue = false);
void build_preamble (QDataStream&);
void eclipse_load(QString filename);
bool eclipse_active(QDateTime now = QDateTime::currentDateTime());
bool flushing ()
{
@ -209,14 +196,6 @@ public:
return flush;
}
QString getStringFromQDateTime(const QString& dateTimeString, const QString& format)
{
QDateTime dateTime = QDateTime::fromString(dateTimeString, format);
return dateTime.toString();
}
QList<QDateTime> eclipseDates;
logger_type mutable logger_;
PSKReporter * self_;
Configuration const * config_;
@ -293,69 +272,6 @@ namespace
}
}
bool PSKReporter::impl::eclipse_active(QDateTime timeutc)
{
#ifdef DEBUGECLIPSE
std::ofstream mylog("/temp/eclipse.log", std::ios_base::app);
#endif
QDateTime dateNow = QDateTime::currentDateTimeUtc();
for (int i=0; i< eclipseDates.size(); ++i)
{
QDateTime check = eclipseDates.at(i); // already in UTC time
// +- 6 hour window
qint64 secondsDiff = qAbs(check.secsTo(dateNow));
if (secondsDiff <= 3600*6) // 6 hour check
{
#ifdef DEBUGECLIPSE
mylog << dateNow.toString(Qt::ISODate) << " Eclipse! " << "secondsDiff=" << secondsDiff << std::endl;
#endif
return true;
}
}
#ifdef DEBUGECLIPSE
mylog << timeutc.toString("yyyy-MM-dd HH:mm:ss") << " no eclipse" << "\n";
#endif
return false;
}
void PSKReporter::impl::eclipse_load(QString eclipse_file)
{
std::ifstream fs(qPrintable(eclipse_file));
std::string mydate,mytime,myline;
#ifdef DEBUGECLIPSE
std::ofstream mylog("c:/temp/eclipse.log");
mylog << "eclipse_file=" << eclipse_file << std::endl;
#endif
if (fs.is_open())
{
while(!fs.eof())
{
std::getline(fs, myline);
if (myline[0] != '#' && myline.length() > 2) // make sure to skip blank lines
{
//QString format = "yyyy-MM-dd hh:mm:ss";
QDateTime qdate = QDateTime::fromString(QString::fromStdString(myline), Qt::ISODate);
QDateTime now = QDateTime::currentDateTimeUtc();
// only add the date if we can cover the whole 12 hours
//if (now < qdate.toUTC().addSecs(-3600*6))
eclipseDates.append(qdate);
#ifdef DEBUGECLIPSE
//else
// mylog << "not adding " << myline << std::endl;
#endif
}
#ifdef DEBUGECLIPSE
mylog << myline << std::endl;
#endif
}
}
#ifdef DEBUGECLIPSE
if (eclipse_active(QDateTime::currentDateTime().toUTC())) mylog << "Eclipse is active" << std::endl;
else mylog << "Eclipse is not active" << std::endl;
#endif
}
void PSKReporter::impl::build_preamble (QDataStream& message)
{
// Message Header
@ -600,11 +516,6 @@ void PSKReporter::reconnect ()
m_->reconnect ();
}
bool PSKReporter::eclipse_active(QDateTime now)
{
return m_->eclipse_active(now);
}
void PSKReporter::setLocalStation (QString const& call, QString const& gridSquare, QString const& antenna)
{
LOG_LOG_LOCATION (m_->logger_, trace, "call: " << call << " grid: " << gridSquare << " ant: " << antenna);
@ -631,45 +542,7 @@ bool PSKReporter::addRemoteStation (QString const& call, QString const& grid, Ra
{
reconnect ();
}
// remove any earlier spots of this call to reduce pskreporter load
#ifdef DEBUGPSK
static std::fstream fs;
if (!fs.is_open()) fs.open("/temp/psk.log", std::fstream::in | std::fstream::out | std::fstream::app);
#endif
added++;
QDateTime qdateNow = QDateTime::currentDateTime().toUTC();
// we allow all spots through +/- 6 hours around an eclipse for the HamSCI group
if (!spot_cache.contains(call) || freq > 49000000 || eclipse_active(qdateNow)) // then it's a new spot
{
m_->spots_.enqueue ({call, grid, snr, freq, mode, QDateTime::currentDateTimeUtc ()});
spot_cache.insert(call, time(NULL));
#ifdef DEBUGPSK
if (fs.is_open()) fs << "Adding " << call << " freq=" << freq << " " << spot_cache[call] << " count=" << m_->spots_.count() << std::endl;
#endif
}
else if (time(NULL) - spot_cache[call] > CACHE_TIMEOUT) // then the cache has expired
{
m_->spots_.enqueue ({call, grid, snr, freq, mode, QDateTime::currentDateTimeUtc ()});
#ifdef DEBUGPSK
if (fs.is_open()) fs << "Adding # " << call << spot_cache[call] << " count=" << m_->spots_.count() << std::endl;
#endif
spot_cache[call] = time(NULL);
}
else
{
removed++;
#ifdef DEBUGPSK
if (fs.is_open()) fs << "Removing " << call << " " << time(NULL) << " reduction=" << removed/(double)added*100 << "%" << std::endl;
#endif
}
// remove cached items over 10 minutes old to save a little memory
QMapIterator<QString, time_t> i(spot_cache);
time_t tmptime = time(NULL);
while(i.hasNext()) {
i.next();
if (tmptime - i.value() > 600) spot_cache.remove(i.key());
}
m_->spots_.enqueue ({call, grid, snr, freq, mode, QDateTime::currentDateTimeUtc ()});
return true;
}
return false;

View File

@ -31,10 +31,6 @@ public:
//
void sendReport (bool last = false);
//
// True if current time falls withing a +/- window of a solar eclipse for HamSCI use
bool eclipse_active(QDateTime now);
Q_SIGNAL void errorOccurred (QString const& reason);
private:

View File

@ -9,208 +9,7 @@
\$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc4
March 11, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 4 brings some improvements for Fox-mode
operators, new features for companion program QMAP, and a number of
relatively minor enhancements and bug fixes.
QMAP enhancements -- of particular interest to EME operators:
- QMAP now decodes Q65 submodes with both 60-second and 30-second T/R
sequence lengths. Clicking on a resulting line in the WSJT-X Active
Stations window automatically sets dial frequency and working
submode as needed to call that station.
- QMAP operates in 60-second receive sequences, and its Q65 decoder
starts at t=19.5, 30.0, 49.5, and 58.5 s into the sequence. Most
decoded messages are displayed well before the end of the relevant
time slot.
- A new, more compact file format is now used for wideband data
files. A "Save decoded" option has been added to the Save menu.
- An option has been added to allow exporting a 3 kHz portion of a
wideband data file as a standard WSJT-X *.wav file.
- CTRL+click on QMAP's upper waterfall sends an integer kHz dial
frequency request to WSJT-X.
- With focus on the WSJT-X main window, hit Alt+A on the keyboard to
clear the Active Stations window.
- Many minor enhancements to the User Interface.
WSJT-X:
- Enable decoding of MSK144 from the jt9[.exe] executable.
- Several changes to reduce problems experienced when (contrary to
our recommendations) messages with short (10-bit) callsign hashes
are used in standard FT4/FT8 sub-bands.
Release: WSJT-X 2.7.0-rc3
January 1, 2024
-------------------------
WSJT-X 2.7.0 Release Candidate 3 brings some new features, as well as
numerous detail improvements and bug fixes, such as:
- Added a new "Update Hamlib" function. On Windows, it allows the user to
update Hamlib directly from the program. The previously used version is
backed up, so the user can easily revert a hamlib update.
- The Hamlib version in use is now displayed (also on Linux and macOS).
- The FT Roundup Messages protocol has been enhanced. It now allows also
the exchange of static 4-digit numbers instead of serial numbers. This
extends the usability of the FT RU protocol for other contest types.
- Improved direct switching between modes. Submode, as well as the status
of the "Sh" and "Fast" checkboxes are now saved and restored by mode.
- Some right-click events were made more intuitive and consistent.
- Right-clicking the Q65 button enables Q65 Pileup mode, a left-click
brings you back to the normal Q65 mode.
- Right-click the JT65 button to switch to JT9 mode.
- For Q65, all messages for us are now displayed in the right window.
- Message averaging is now allowed only when VHF features are
enabled, and label texts are changed to "Single Period Decodes" and
"Average Decodes" only if averaging is enabled.
- Some improvements to the Hamlib Transceiver code. Behavior is now
more stable when Rig Split has been selected.
- Prevented redundant network communication between WSJT-X and DX Lab
Suite Commander.
- Download of the LotW file now works without OpenSSL libraries.
- Made the spot counter work for WSPR.
- Prevented insertion of an individual contest name when in Fox mode.
- WAE entities are now assigned to the correct DXCC when "Include
extra WAE entities" is not selected.
- Added a utility program 'cablog' which can be used to convert the
wsjtx.log file to Cabrillo format for the ARRL EME contest.
- Minor improvements to the Active Stations window.
- The Rx/Tx frequency for Echo mode has been fixed at 1500 Hz.
- Some corrections and updates to the INSTALL instructions for Linux.
- Updated CTY.DAT file.
Release: WSJT-X 2.7.0-rc2
July 7, 2023
-------------------------
WSJT-X 2.7.0 Release Candidate 2 introduces several minor improvements
and bug fixes.
- CTRL+SHIFT+F11/F12 now changes dial frequency by 1000 Hz instead of
2000 Hz.
- Improved spotting to PSK Reporter for upcoming HamSCI Festivals of
Eclipse Ionospheric Science.
- Added optional Hungarian translation of the user interface.
- Fixed a flaw that could produce false decodes in Q65 submodes D and E.
- Fixed a flaw with the QSO start time. It is now reset when the DX
Call changes.
- Fixed a flaw that prevented contest logging of the ARRL Digi Contest.
- Right-clicking the Q65 mode button to toggle the Q65 Pileup mode on/off
now also works on macOS.
- Fixed a compilation error on macOS Ventura.
- WSPR and FST4W band hopping now works again.
- It is now ensured that "U.S.A." is displayed when using certain
cty.dat files.
- Corrected the problem with duplicated FT8 entries in ActiveStations
window.
Release: WSJT-X 2.7.0-rc1
May 12, 2023
-------------------------
WSJT-X 2.7.0 Release Candidate 1 introduces a new program called QMAP,
a new Special Operating Activity known as Q65 Pileup, and a number of
other enhancements and fixes.
- QMAP and Q65 Pileup mode are of particular interest to those
engaged in Earth-Moon-Earth (EME) communication, but other
applications may be found for them as well.
- QMAP is derived from MAP65, an older program used since 2007 for
EME, mainly on the 2 m band. QMAP provides single-polarization
receive-only capabilities for any one of the 60-second submodes
of Q65. It allows you to monitor all traffic in a 90 kHz subband
while conducting EME QSOs in the usual way with WSJT-X.
- Q65 Pileup mode is a new feature in WSJT-X that will assist DX
operators using Q65 in pileup circumstances with many
simultaneous callers and very weak signals, such as those
experienced by 6-meter EME DXpeditions.
- Further details on QMAP and Q65 Pileup mode are available in a
Quick-Start guide posted here:
https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf
- WSJT-X now provides more efficient spotting to PSK Reporter.
Redundant spots are omitted, and posting of spots is now spread
more widely in time. (Temporarily, in support of the HamSCI
Festivals of Eclipse Ionospheric Science, spots will be transmitted
more frequently during the upcoming solar eclipses.)
- WSJT-X is now able to process more than 100 FT8 decodes in a single
reception interval.
- Improvements to the Fox mode:
- More convenient and efficient handling of the two queues.
- Fox Log window now displays statistical data on the QSO rate.
- When the station locator is changed (e.g during portable
operations), the new locator will be sent automatically to PSK
Reporter.
- The cty.dat file can now be updated by clicking a button on the
Settings -> Colors tab.
- A new status display appears when fetching a new LotW file.
- Multi-streamed messages transmitted by MSHV are now handled
properly when WSJT-X is in Hound mode.
- Auto-sequencing now has better protection against unwanted effects
caused by late FT8 decodes.
- Fixed an inconsistency in which Contest Name was not correctly
remembered.
- Other minor bug fixes.
- Updated hyperlinks to our homepage and to our new WSJT GROUP User
Forum (https://groups.io/g/wsjtgroup/) can now also be found in the
User Guide.
- The build instructions for macOS have been clarified.
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.6.1
January 16, 2023

View File

@ -659,7 +659,7 @@ int HamlibTransceiver::do_start ()
rmode_t mb;
pbwidth_t w {RIG_PASSBAND_NORMAL};
pbwidth_t wb;
if (m_->freq_query_works_ && m_->mode_query_works_
if (m_->freq_query_works_
&& (!m_->get_vfo_works_ || !rig_get_function_ptr (m_->model_, RIG_FUNCTION_GET_VFO)))
{
// Icom have deficient CAT protocol with no way of reading which
@ -760,7 +760,7 @@ int HamlibTransceiver::do_start ()
m_->reversed_ = RIG_VFO_B == v;
if (m_->mode_query_works_ && !(rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & RIG_TARGETABLE_MODE))
if (m_->mode_query_works_ && !(rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE)))
{
if (RIG_OK == rig_get_mode (m_->rig_.data (), RIG_VFO_CURR, &m, &w))
{
@ -911,9 +911,9 @@ void HamlibTransceiver::do_frequency (Frequency f, MODE m, bool no_ignore)
// to frequency such as the TS-2000 auto mode setting
CAT_TRACE ("rig_set_mode mode=" << rig_strrmode (new_mode));
m_->error_check (rig_set_mode (m_->rig_.data (), target_vfo, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting current VFO mode"));
// set mode on VFOB too if we are in split
if (state ().split()) rig_set_mode (m_->rig_.data (), RIG_VFO_B, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting VFOB mode");
}
// set mode on VFOB too if we are in split
if (state ().split()) rig_set_mode (m_->rig_.data (), RIG_VFO_B, new_mode, RIG_PASSBAND_NOCHANGE), tr ("setting VFOB mode");
update_mode (m);
}
}
@ -1147,7 +1147,7 @@ void HamlibTransceiver::do_poll ()
if ((WSJT_RIG_NONE_CAN_SPLIT || !m_->is_dummy_)
&& state ().split ()
&& (rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & RIG_TARGETABLE_FREQ)
&& (rig_get_caps_int (m_->model_, RIG_CAPS_TARGETABLE_VFO) & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE))
&& !m_->one_VFO_)
{
// only read "other" VFO if in split, this allows rigs like

3927
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,7 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:jtalert: https://hamapps.com/[JTAlert]
:launchpadki7mt: https://launchpad.net/~ki7mt[KI7MT PPA's]
:log4om: https://www.log4om.com[Log4OM]
:lunarEchoes: https://wsjt.sourceforge.io/LunarEchoes_QEX.pdf[QEX]
:lunarEchoes: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/LunarEchoes_QEX.pdf[QEX]
:msk144: https://wsjt.sourceforge.io/MSK144_Protocol_QEX.pdf[QEX]
:msvcpp_redist: https://www.microsoft.com/en-ph/download/details.aspx?id=40784[Microsoft VC++ 2013 Redistributable]
:msys_url: https://sourceforge.net/projects/mingwbuilds/files/external-binary-packages/[MSYS Download]
@ -94,11 +94,11 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
:ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice]
:win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages]
:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1s.msi[Win32 OpenSSL Light Package]
:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1s.msi[Win64 OpenSSL Light Package]
:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1L.msi[Win32 OpenSSL Light Package]
:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1L.msi[Win64 OpenSSL Light Package]
:writelog: https://writelog.com/[Writelog]
:wsjtx_group: https://groups.io/g/wsjtgroup[WSJT GROUP User Forum]
:wsjtx_group2: https://groups.io/g/wsjtgroup/join[join the group]
:wsjtx_group: https://groups.io/g/WSJTX[WSJTX Group]
:wsjtx_group2: https://groups.io/g/WSJTX[join the group]
:wsjtx: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/wsjtx.html[WSJT-X]
:wspr0_guide: https://wsjt.sourceforge.io/WSPR0_Instructions.TXT[WSPR0 Guide]
:wspr: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/wspr.html[WSPR Home Page]
@ -106,7 +106,7 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:wsprnet_activity: https://wsprnet.org/drupal/wsprnet/activity[WSPRnet Activity page]
// Download Links
:cty_dat: https://www.country-files.com/bigcty/cty.dat/[Amateur Radio Country Files]
:cty_dat: https://www.country-files.com/cty/[Amateur Radio Country Files]
:jtbridge: https://jt-bridge.eller.nu/[JT-Bridge]
:jtsdk_doc: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/JTSDK-DOC.exe[Download]
:jtsdk_installer: https://sourceforge.net/projects/jtsdk/files/win32/2.0.0/JTSDK-2.0.0-B2-Win32.exe/download[Download]
@ -121,8 +121,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:svn: https://subversion.apache.org/packages.html#windows[Subversion]
:win32: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/wsjtx-{VERSION}-win32.exe[wsjtx-{VERSION}-win32.exe]
:win64: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/wsjtx-{VERSION}-win64.exe[wsjtx-{VERSION}-win64.exe]
:wsjt-devel: https://sourceforge.net/projects/wsjt/lists/wsjt-devel/[join the group]
:wsjt-devel2: https://sourceforge.net/projects/wsjt/lists/wsjt-devel/[subscribe to the list]
:wsjt-devel: https://sourceforge.net/p/wsjt/mailman/wsjt-devel/[join the group]
:wsjt-devel2: https://sourceforge.net/p/wsjt/mailman/wsjt-devel/[subscribe to the list]
:wsjt_repo: https://sourceforge.net/p/wsjt/wsjt_orig/ci/master/tree/[WSJT Source Repository]
:wspr_code: https://sourceforge.net/projects/wsjt/files/wsjtx-{VERSION}/WSPRcode.exe[WSPRcode.exe]
:wspr_svn: https://sourceforge.net/p/wsjt/wspr/ci/master/tree/[WSPR Source Repository]
@ -134,7 +134,7 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:dev_mail_svn: https://sourceforge.net/auth/subscriptions/[WSJT SVN Archives]
:devmail: mailto:wsjt-devel@lists.sourceforge.net[wsjt-devel@lists.sourceforge.net]
:devmail1: mailto:wsjt-devel@lists.sourceforge.net[Post Message]
:wsjtgroup_mail: mailto:wsjtgroup@groups.io[Post Message]
:wsjtgroup_mail: mailto:WSJTX@groups.io[Post Message]
:greg_beam: mailto:ki7mt@yahoo.com[KI7MT]
:joe_taylor: mailto:joe@princeton.edu[K1JT]
:stuart_rackman: mailto:srackham@gmail.com[Stuart Rackham]

View File

@ -2,9 +2,9 @@
The _WSJT_ project was started by *K1JT* in 2001. Since 2005 it has
been an Open Source project, and it has included the programs _WSJT_,
_MAP65_, _WSPR_, _WSJT-X_, and _QMAP_. *G4WJS* (since 2013), *K9AN*
(since 2015), *IV3NWV* (since 2016), *DG2YCB* (since 2021), and
*N9ADG* (since 2022) have made major contributions to _WSJT-X_.
_MAP65_, _WSPR_, _WSJT-X_, and _WSPR-X_. *G4WJS* (since 2013), *K9AN*
(since 2015), *IV3NWV* (since 2016), *KG4IYS* (since 2021), and
*DG2YCB* (since 2021) have made major contributions to _WSJT-X_.
Together with K1JT they now form the core development team. *G4WJS*
and *W9MDB* have made major contributions to the _hamlib_ library, on
which _WSJT-X_ depends for rig control.
@ -13,12 +13,12 @@ All code in the _WSJT_ project is licensed under the GNU Public
License (GPL). Many users of these programs, too numerous to mention
here individually, have contributed suggestions and advice that have
greatly aided the development of _WSJT_ and its sister programs. For
_WSJT-X_ in particular, in addition to those mentioned above we
acknowledge contributions from *AC6SL, AE4JY, DF2ET, DJ0OT, G3WDG,
G4KLA, IW3RAB, K3WYC, KA1GT, KA6MAL, KA9Q, KB1ZMX, KD6EKQ, KI7MT,
KK1D, ND0B, PY2SDR, VE1SKY, VK3ACF, VK4BDJ, VK7MO, W3DJS, W3SZ, W4TI,
and W4TV*. Each of these amateurs has helped to bring the programs
design, code, testing, and/or documentation to its present state.
_WSJT-X_ in particular, we acknowledge contributions from *AC6SL,
AE4JY, DF2ET, DJ0OT, G3WDG, G4KLA, IW3RAB, K3WYC, KA1GT, KA6MAL, KA9Q,
KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR, VE1SKY, VK3ACF, VK4BDJ,
VK7MO, W3DJS, W3SZ, W4TI, W4TV, and W9MDB*. Each of these amateurs
has helped to bring the programs design, code, testing, and/or
documentation to its present state.
Most of the color palettes for the _WSJT-X_ waterfall were copied from
the excellent, well documented, open-source program _fldigi_, by *W1HKJ*

View File

@ -7,9 +7,7 @@ K1**JT**,`" while the suffix "`*-X*`" indicates that _WSJT-X_ started
as an extended branch of an earlier program, _WSJT_, first released in
2001. Bill Somerville, G4WJS, Steve Franke, K9AN, and Nico Palermo,
IV3NWV, have been major contributors to development of _WSJT-X_ since
2013, 2015, and 2016, respectively. Bill Somerville died suddenly and
unexpectedly in December 2021; Uwe Risse, DG2YCB, joined the core
development team soon afterward, and Brian Moran, N9ADG, in 2022.
2013, 2015, and 2016, respectively.
_WSJT-X_ Version {VERSION_MAJOR}.{VERSION_MINOR} offers eleven
different protocols or modes: *FST4*, *FT4*, *FT8*, *JT4*, *JT9*,

View File

@ -1,60 +1,68 @@
[[NEW_FEATURES]]
=== New in Version {VERSION_MAJOR}.{VERSION_MINOR}
_WSJT-X 2.7_ introduces a new program called *QMAP*, a new Special
Operating Activity *Q65 Pileup*, an option to *Update Hamlib* at the
click of a button, and a number of other enhancements and bug fixes.
- _WSJT-X 2.6_ implements new features supporting the ARRL
International Digital Contest and its distance based scoring. The
*Call 1st* checkbox has been replaced by a drop-down control offering
*CQ Max Dist* as an alternative. A new window labeled *Active
Stations* displays a list of received but unworked callsigns, sorted
in decreasing order of potential contest points. With option *CQ Max
Dist* selected, the program will select the reply to your CQ that
yields the most contest points. You can click on a line in the Active
Stations window to call that station.
- QMAP and Q65 Pileup mode are of particular interest to those engaged
in Earth-Moon-Earth (EME) communication, but other applications may
be found for them as well. QMAP is currently available for Windows
only; it is derived from MAP65, an older program used since 2007 for
EME. QMAP provides single-polarization receive-only capabilities for
any one of the 60-second submodes of Q65. It allows you to monitor
all traffic in a 90 kHz sub-band while conducting EME QSOs in the
usual way with _WSJT-X_. Q65 Pileup mode helps DX operators using
Q65 in pileup circumstances with many simultaneous callers and very
weak signals, such as those experienced by 6-meter EME DXpeditions.
Further details on QMAP and Q65 Pileup mode are available in a
Quick-Start guide posted here:
https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf
- Decoding performance for FT8 and Q65 has been improved in a variety
of situations with available _a priori_ (AP) information.
- A button *Update Hamlib* now appears on the *Settings -> Radio* tab.
On Windows it allows the user to automatically download and install
the latest version of the rig-control features in Hamlib. The
previously used version is backed up, so you can easily revert the
procedure if necessary. Names and dates of the active and backup
versions are clearly displayed.
- *Echo* mode now offers a *Clear Avg* button and produces reliable
measurements of SNR even when Doppler spread is large. Its *Monitor*
function can be used to measure SNR for a received unmodulated carrier
such as a key-down test signal emitted by another station and
reflected from the Moon, and also to measure Sun, Moon, and ground
noise as aids for optimizing an EME station's performance.
- Spotting to *PSK Reporter* has been made more efficient. Redundant
spots are omitted, and all posts are spread more widely in time. If
your station locator is changed, for example during portable
operations, your new locator will be sent automatically to PSK
Reporter.
- New buttons on the main window allow quick changes between modes
FT4, FT8, MSK144, Q65, and JT65, and toggling FT8 Hound mode ON/OFF.
- *Fox* mode now provides more convenient handling of the two callsign
queues, and Fox's Log window displays statistical data on recent QSO
rate. Multi-streamed messages transmitted by _MSHV_ are now handled
properly when _WSJT-X_ is in *Hound* mode.
- New convenience features allow Fox operators to react more quickly
to particular QSO situations. A two-column table in Tab 2 provides an
overview of the queue and of callsigns with QSOs in progress. Fox
operator can change the ordering of callsigns in the queue, allowing
reaction to changes in propagation. Fox now responds automatically
for another two cycles to stations whose report has not been received,
increasing the success rate for difficult QSOs.
- The cty.dat file can now be updated by clicking a button on the
*Settings -> Colors* tab.
- The Working frequency table now offers save/restore capability and
better handling of more than one frequency per mode-band
combination. You can set preferred frequencies, and WSJT-X will select
these when you change band or mode. You can label a tabled frequency
with a description, for example a DXpedition callsign, and set Start
and End date and time so the frequencies automatically appear and
disappear from the displayed options. You can load a publicly
available frequency table from a file, to easily make such DXpedition
data available to the program.
- The FT Roundup message protocol now allows the exchange of static
4-digit numbers in place of serial numbers. This extends the
usability of the FT RU protocol for other contest types.
- Optional color highlighting is provided for specified DX Call and DX
Grid, and for messages containing RR73 or 73.
- Features for main-window switching between modes have been enhanced
so that submode and status of the *Sh* and *Fast* checkboxes are
saved and restored by mode. Right-click events were made more
intuitive and consistent. Right-clicking the Q65 button enables Q65
Pileup mode, and a left-click brings you back to the normal Q65
mode. Right-click on the JT65 button switches to JT9 mode.
- New options are provided for writing to file ALL.TXT. You can
request automatic starting of a new file every month or every year,
and you can disable writing altogether.
- Message averaging is now allowed only when *VHF features* are
enabled. Main window text box labels are changed to read "`Single
Period Decodes`" and "`Average Decodes`" when averaging is enabled.
- Settings for T/R period and Submode are remembered by mode when you
switch directly between modes: for example, MSK144-15, Q65-60A, or
FST4-120.
Further details on minor changes can be found in the Release Notes,
accessible from the _WSJT-X_ *Help* menu.
- Tx and Rx audio frequencies are remembered and restored when you
return from a mode that sets a default frequency 1500 Hz (MSK144,
FST4W, Echo, WSPR, FreqCal), then switching back to FT4, FT8, Q65,
FST4, or JT65.
- Rig control is provided for some new radios, and bug fixes for
controlling others.
- New features in _MAP65_ (available for Windows only) include an aid
for measuring antenna pointing errors and an ability to read the file
wsjtx.log (kept by _WSJT-X_) to recognize EME contest dupes. In
addition, _MAP65_ now sends additional information to file azel.dat
and offers optional digital scaling of input I/Q data.

View File

@ -31,7 +31,7 @@ image::RadioTab.png[align="center",alt="Radio Tab"]
suitable.
* _CAT Control_: To have _WSJT-X_ control the radio directly rather
than through another program, make the following settings:
than though another program, make the following settings:
** Select the *Serial Port* or *Network Server* including the service
port number used to communicate with your radio.

View File

@ -2,17 +2,18 @@
The best source of help in setting up your station or configuring
_WSJT-X_ is the {wsjtx_group} at email address
wsjtgroup@groups.io. The chances are good that someone with
wsjtx@groups.io. The chances are good that someone with
similar interests and equipment has already solved your problem and
will be happy to help. To post messages here you will need to
{wsjtx_group2}.
{wsjt-devel}.
=== Bug Reports
One of your responsibilities as a _WSJT-X_ user is to help the
volunteer programmers to make the program better. Bugs may be
reported preferably to the WSJT Developers email list
(wsjt-devel@lists.sourceforge.net). You will need to {wsjt-devel2}.
reported to the WSJTX forum on Groups.io {wsjtgroup_mail} or the WSJT
Developers list (wsjt-devel@lists.sourceforge.net). Again, you will
need to {wsjtx_group2} or {wsjt-devel2}.
To be useful, bug reports should include at least the following
information:

View File

@ -35,7 +35,7 @@ Rx frequency along with any decodes addressed to *My Call* (K1JT in this case).
The red marker on the waterfall scale indicates your
Tx frequency.
Twenty-one FT8 signals are decoded from the example file. The number
Twenty one FT8 signals are decoded from the example file. The number
of decodes is shown in a box at the bottom of the main window.
When this file was recorded HA5WA was finishing a QSO with K1JT, and
his 73 message is shown in red because it is addressed to *My Call* (in this case K1JT).

View File

@ -34,7 +34,7 @@ frequency control on the main window will be updated accordingly.
frequency marker and its associated control on the main window will
follow your frequency selections.
- Do the same thing with the *Ctrl* key held down. Now both colored
- Do the same thing with the *Ctrl* key held down. Now the both colored
markers and both spinner controls will follow your selections.
- Now double-click on any of the lines of decoded text in the Band

View File

@ -26,7 +26,7 @@ on bands above 1.2 GHz.
To activate the VHF-and-up features:
- On the *Settings | General* tab check *Enable VHF and submode
- On the *Settings | General* tab check *Enable VHF/UHF/Microwave
features* and *Single decode*.
- For EME, check *Decode after EME delay* to allow for extra path
@ -291,16 +291,14 @@ communication.
For lunar echoes, _WSJT_ generates short fixed-frequency transmissions
that alternate with reception intervals at the appropriate
Doppler-shifted frequency. Be sure that *Enable VHF and submode
features* has been checked on the *Settings | General* tab. With
*Split Operation* set to *Rig* or *Fake It* on the *Settings | Radio*
tab, check *Doppler tracking* and *Own Echo* on the Astronomical Data
window. Point your antenna at the Moon and click *Enable Tx* on the
main window to start a sequence of echo measurements. Each cycle
takes 6 seconds. If strong enough, echoes will be visible in the
waterfall. Their average spectrum will be displayed in the Echo Graph
window, and numerical parameters of the measurements appear in the
main window:
Doppler-shifted frequency. With *Split Operation* set to *Rig* or
*Fake It* on the *Settings | Radio* tab, check *Doppler tracking* and
*Own Echo* on the Astronomical Data window. Point your antenna at the
Moon and click *Enable Tx* on the main window to start a sequence of
echo measurements. Each cycle takes 6 seconds. If strong enough,
echoes will be visible in the waterfall. Their average spectrum will
be displayed in the Echo Graph window, and numerical parameters of the
measurements appear in the main window:
image::Echo_1296.png[align="center",alt="Echo 144 MHz"]

View File

@ -1,28 +0,0 @@
# Some test dates added for PSKReporter testing#
2023-06-10T21:30:00Z
2023-06-15T18:00:00Z
2023-07-01T18:00:00Z
2023-07-15T18:00:00Z
2023-08-01T18:00:00Z
2023-08-15T18:00:00Z
2023-09-01T18:00:00Z
2023-09-15T18:00:00Z
2023-10-01T18:00:00Z
# From https://eclipse.gsfc.nasa.gov/SEdecade/SEdecade2021.html
2023-10-14T18:00:40Z
2024-04-08T18:18:29Z
2024-10-02T18:46:13Z
2025-03-29T10:48:36Z
2025-09-21T19:43:04Z
2026-02-17T12:13:05Z
2026-08-12T17:47:05Z
2027-02-06T16:00:47Z
2027-08-02T10:04:49Z
2028-01-26T15:08:58Z
2028-07-22T02:56:39Z
2029-01-14T17:13:47Z
2029-06-12T04:06:13Z
2029-07-11T15:37:18Z
2029-12-05T15:03:57Z
2030-06-01T06:29:13Z
2030-11-25T06:51:37Z

View File

@ -1,42 +0,0 @@
program hash22calc
! Given a valid callsign, calculate and print its 22-bit hash.
use packjt77
character*13 callsign
character*1 c
character*6 basecall
logical cok
nargs=iargc()
if(nargs.ne.1) then
print*,'Given a valid callsign, print its 22-bit hash.'
print*,'Usage: hash22calc <callsign>'
print*,' e.g. hash22calc W9ABC'
go to 999
endif
call getarg(1,callsign)
! convert to upper case
ilen=len(trim(callsign))
do i=1, ilen
c=callsign(i:i)
if(c.ge.'a' .and. c.le.'z') c=char(ichar(c)-32) !Force upper case
callsign(i:i)=c
enddo
! check for a valid callsign
call chkcall(callsign,basecall,cok)
if(.not.cok) then
print*,'Invalid callsign'
print*,'Usage: hash22calc <callsign>'
goto 999
endif
! calculate the hash
n22 = ihashcall(callsign,22)
write(*,'(a,i7.7)') callsign,n22
999 end program hash22calc
include '../chkcall.f90'

View File

@ -370,28 +370,15 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
msg=adjustl(msg)
else if(i3.eq.0 .and. n3.eq.6) then
read(c77(48:50),'(3b1)') j48,j49,j50
! bits 48:50
! itype=1: x00
! itype=2: xx1
! itype=3: 010
if(j50.eq.1) then
itype=2
else if(j49.eq.0) then
itype=1
else if(j48.eq.0) then
itype=3
else
itype=-1
unpk77_success=.false.
endif
read(c77(49:50),'(2b1)') j2a,j2b
itype=2
if(j2b.eq.0 .and. j2a.eq.0) itype=1
if(j2b.eq.0 .and. j2a.eq.1) itype=3
if(itype.eq.1) then
! WSPR Type 1
read(c77,2010) n28,igrid4,idbm
2010 format(b28.28,b15.15,b5.5)
idbm=nint(idbm*10.0/3.0)
if(idbm.lt.0 .or. idbm.gt.60) unpk77_success=.false.
call unpack28(n28,call_1,unpk28_success)
if(.not.unpk28_success) unpk77_success=.false.
call to_grid4(igrid4,grid4,unpkg4_success)
@ -405,7 +392,6 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
read(c77,2020) n28,npfx,idbm
2020 format(b28.28,b16.16,b5.5)
idbm=nint(idbm*10.0/3.0)
if(idbm.lt.0 .or. idbm.gt.60) unpk77_success=.false.
call unpack28(n28,call_1,unpk28_success)
if(.not.unpk28_success) unpk77_success=.false.
write(crpt,'(i3)') idbm
@ -474,17 +460,13 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
i=index(call_1,' ')
if(i.ge.4 .and. ipa.eq.1 .and. i3.eq.1) call_1(i:i+1)='/R'
if(i.ge.4 .and. ipa.eq.1 .and. i3.eq.2) call_1(i:i+1)='/P'
if(i.ge.4) call add_call_to_recent_calls(call_1)
if(i.ge.4) call add_call_to_recent_calls(call_1)
endif
if(index(call_2,'<').le.0) then
i=index(call_2,' ')
if(i.ge.4 .and. ipb.eq.1 .and. i3.eq.1) call_2(i:i+1)='/R'
if(i.ge.4 .and. ipb.eq.1 .and. i3.eq.2) call_2(i:i+1)='/P'
if(i.ge.4) then
call add_call_to_recent_calls(call_2)
! only hash the "from" call
call save_hash_call(call_2,ndum10,ndum12,ndum22)
endif
if(i.ge.4) call add_call_to_recent_calls(call_2)
endif
if(igrid4.le.MAXGRID4) then
call to_grid4(igrid4,grid4,unpkg4_success)
@ -564,7 +546,6 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
call_1=call_3
call_2=adjustl(c11)//' '
call add_call_to_recent_calls(call_2)
call save_hash_call(call_2,ndum10,ndum12,ndum22)
if(nrx.eq.1 .and. &
dxcall13_set .and. mycall13_set .and. &
call_2.eq.dxcall13 .and. &
@ -1545,7 +1526,7 @@ subroutine add_call_to_recent_calls(callsign)
endif
! Make sure that callsign is hashed
! call save_hash_call(callsign,n10,n12,n22) ! commented out - do this in the calling routine:
call save_hash_call(callsign,n10,n12,n22)
return
end subroutine add_call_to_recent_calls

View File

@ -1,142 +0,0 @@
program cablog
character*100 line,infile,outfile
character cband*4,cmode*2,cdate*10,cutc*4,callsign*10,mycall*10
character csent*4,crcvd*4,dsent*4,drcvd*4,g1*4
character*3 cmo(12)
integer icomma(20)
logical map65
logical isgrid,gridx
data cmo/'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep', &
'Oct','Nov','Dec'/
isgrid(g1)=g1(1:1).ge.'A' .and. g1(1:1).le.'R' .and. g1(2:2).ge.'A' .and. &
g1(2:2).le.'R' .and. g1(3:3).ge.'0' .and. g1(3:3).le.'9' .and. &
g1(4:4).ge.'0' .and. g1(4:4).le.'9' .and. g1(1:4).ne.'RR73'
nargs=iargc()
if(nargs.ne.4) then
print*,"Program cablog converts file 'wsjtx.log' written by WSJT-X"
print*,"(or wsjt.log written by MAP65) to a bare-bones Cabrillo"
print*,"log for the ARRL International EME Contest. You will"
print*,"certainly need to edit the header information, and you may"
print*,"edit the log elsewhere as required."
print*,' '
print*,'Usage: cablog <MyCall> <sent> <rcvd> <infile>'
print*,'Examples: cablog W2ZQ -15 -16 wsjtx.log'
print*,' cablog W2ZQ O O wsjt.log'
go to 999
endif
call getarg(1,mycall)
outfile=trim(mycall)//'.log'
call getarg(2,dsent)
gridx=isgrid(dsent)
call getarg(3,drcvd)
call getarg(4,infile)
open(10,file=trim(infile),status='old')
open(12,file=trim(outfile),status='unknown')
write(12,1000)
1000 format('START-OF-LOG: 3.0'/ &
'CONTEST: ARRL-EME'/ &
'CALLSIGN: '/ &
'CATEGORY-OPERATOR: '/ &
'CATEGORY-BAND: '/ &
'CATEGORY-MODE: '/ &
'EMAIL: '/ &
'OPERATORS: '/ &
'CATEGORY-POWER: HIGH'/ &
'CATEGORY-TRANSMITTER: ONE'/ &
'CATEGORY-STATION: FIXED'/ &
'CATEGORY-TIME: 24-HOURS'/ &
'CATEGORY-ASSISTED: ASSISTED'/ &
'LOCATION: SNJ'/ &
'CLAIMED-SCORE: '/ &
'CLUB: '/ &
'NAME: '/ &
'ADDRESS: '/ &
'ADDRESS: '/ &
'ADDRESS: '/ &
'CREATED-BY: cablog (C) K1JT')
n=0
map65=.false.
do nn=1,9999
read(10,'(a100)',end=900) line
if(len(trim(line)).eq.0) cycle
if(line(6:6).ge.'A' .and. line(6:6).le.'Z') map65=.true.
n=n+1
k=0
do j=1,100
if(line(j:j).eq.',') then
k=k+1
icomma(k)=j
endif
enddo
cmode='DG'
if(index(line,',CW,').gt.10) cmode='CW'
if(map65) then
do i=1,12
if(cmo(i).eq.line(6:8)) write(cdate(6:7),'(i2.2)') i
enddo
cdate(1:5)=line(1:5)
cdate(8:10)=line(9:11)
cutc=line(13:14)//line(16:17)
i0=index(line(19:),',')
callsign=line(19:17+i0)
cband='144 '
csent=dsent
crcvd=drcvd
else
cdate=line(1:10)
cutc=line(32:33)//line(35:36)
i0=index(line(41:),',')
callsign=line(41:39+i0)
read(line(icomma(6)+1:icomma(7)-1),*,err=10,end=10) freq
go to 20
10 print*,'***Error at line ',n
print*,trim(line)
20 if(freq.ge.50.0 .and. freq.le.54.0) cband='50 '
if(freq.ge.144.0 .and. freq.le.148.0) cband='144 '
if(freq.ge.28.0 .and. freq.le.29.0) cband='144 '
if(freq.ge.222.0 .and. freq.le.225.0) cband='222 '
if(freq.ge.420.0 .and. freq.le.450.0) cband='432 '
if(freq.ge.902.0 .and. freq.le.928.0) cband='902 '
if(freq.ge.1240.0 .and. freq.le.1300.0) cband='1.2G'
if(freq.ge.2300.0 .and. freq.le.2450.0) cband='2.3G'
if(freq.ge.3300.0 .and. freq.le.3500.0) cband='3.4G'
if(freq.ge.5650.0 .and. freq.le.5925.0) cband='5.7G'
if(freq.ge.10000.0 .and. freq.le.10500.0) cband='10G '
if(freq.ge.24000.0 .and. freq.le.24250.0) cband='24G '
if(icomma(8).eq.icomma(9)-1) then
csent=dsent
else
csent=line(icomma(8)+1:icomma(9)-1)
endif
if(icomma(9).eq.icomma(10)-1) then
crcvd=drcvd
else
crcvd=line(icomma(9)+1:icomma(10)-1)
endif
endif
if(gridx) then
csent=dsent
crcvd=line(icomma(5)+1:icomma(6)-1)
endif
write(12,1030) cband,cmode,cdate,cutc,mycall,csent,callsign,crcvd
1030 format('QSO: ',a4,1x,a2,1x,a10,1x,a4,1x,a6,1x,a4,4x,a10,1x,a4)
enddo
900 write(12,1900)
1900 format('END-OF-LOG:')
write(*,1910) n,trim(outfile)
1910 format('Processed',i5,' QSOs.'/'Output file: ',a)
999 end program cablog
!2023-10-28,00:17:00,2023-10-28,00:21:00,G7TZZ,IO92,1296.083100,Q65,-17,-17,,,,
!2023-Nov-30,20:31,W8WN,EM77,0,Q65A

View File

@ -1,57 +0,0 @@
subroutine decode_msk144(audio_samples, params, data_dir)
include 'jt9com.f90'
! constants
integer, parameter :: SAMPLING_RATE = 12000
integer, parameter :: BLOCK_SIZE = 7168
integer, parameter :: STEP_SIZE = BLOCK_SIZE / 2
integer, parameter :: CALL_LENGTH = 12
! aguments
integer*2 audio_samples(NMAX)
type(params_block) :: params
character(len = 500) :: data_dir
! parameters of mskrtd
integer*2 :: buffer(BLOCK_SIZE)
real :: tsec
logical :: bshmsg = .false. ! enables shorthand messages
logical :: btrain = .false. ! turns on training in MSK144 mode
real*8 :: pcoeffs(5) = (/ 0.0, 0.0, 0.0, 0.0, 0.0 /); ! phase equalization
logical :: bswl = .false.
character(len = 80) :: line
character(len = CALL_LENGTH) :: mycall
character(len = CALL_LENGTH) :: hiscall
! local variables
integer :: sample_count
integer :: position
integer :: message_count = 0
! decode in 0.3s blocks
sample_count = params%ntr * SAMPLING_RATE
mycall = transfer(params%mycall, mycall) ! string to char[]
hiscall = transfer(params%hiscall, hiscall)
do position = 1, sample_count - BLOCK_SIZE + 1, STEP_SIZE
buffer = audio_samples(position : position + BLOCK_SIZE - 1)
tsec = position / REAL(SAMPLING_RATE)
call mskrtd(buffer, params%nutc, tsec, params%ntol, params%nfqso, params%ndepth, &
mycall, hiscall, bshmsg, btrain, pcoeffs, bswl, data_dir, line)
if (line(1:1) .ne. char(0)) then
line = line(1:index(line, char(0))-1)
write(*, 1001) line
1001 format(a80)
message_count = message_count + 1;
end if
end do
if (.not. params%ndiskdat) then
write(*, 1002) 0, message_count, 0
1002 format('<DecodeFinished>', 2i4, i9)
end if
end subroutine decode_msk144

View File

@ -44,9 +44,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
real ss(184,NSMAX)
logical baddata,newdat65,newdat9,single_decode,bVHF,bad0,newdat,ex
logical lprinthash22
integer*2 id2(NTMAX*12000)
integer nqf(20)
type(params_block) :: params
real*4 dd(NTMAX*12000)
character(len=20) :: datetime
@ -213,28 +211,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
params%nfa,params%nfb,logical(params%nclearave), &
single_decode,logical(params%nagain),params%max_drift, &
logical(params%newdat),params%emedelay,mycall,hiscall,hisgrid, &
params%nQSOProgress,ncontest,logical(params%lapcqonly),navg0,nqf)
params%nclearave=.false.
if(.not.params%nagain) then
! Go through identified candidates again, treating each as if it had been
! double-clicked on the waterfall.
do k=1,20
if(nqf(k).eq.0) exit
if(params%nagain .and. abs(nqf(k)-params%nfqso).gt.params%ntol) cycle
nqd=1
navg0=0
ntol=5
call my_q65%decode(q65_decoded,id2,nqd,params%nutc,params%ntr, &
params%nsubmode,nqf(k),ntol,params%ndepth, &
params%nfa,params%nfb,logical(params%nclearave), &
.true.,.true.,params%max_drift, &
.false.,params%emedelay,mycall,hiscall,hisgrid, &
params%nQSOProgress,ncontest,logical(params%lapcqonly), &
navg0,nqf)
enddo
endif
params%nQSOProgress,ncontest,logical(params%lapcqonly),navg0)
call timer('dec_q65 ',1)
close(17)
go to 800
@ -244,30 +221,27 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
! We're in FST4 mode
ndepth=iand(params%ndepth,3)
iwspr=0
lprinthash22=.false.
params%nsubmode=0
call timer('dec_fst4',0)
call my_fst4%decode(fst4_decoded,id2,params%nutc, &
params%nQSOProgress,params%nfa,params%nfb, &
params%nfqso,ndepth,params%ntr,params%nexp_decode, &
params%ntol,params%emedelay,logical(params%nagain), &
logical(params%lapcqonly),mycall,hiscall,iwspr,lprinthash22)
logical(params%lapcqonly),mycall,hiscall,iwspr)
call timer('dec_fst4',1)
go to 800
endif
if(params%nmode.eq.241 .or. params%nmode.eq.242) then
if(params%nmode.eq.241) then
! We're in FST4W mode
ndepth=iand(params%ndepth,3)
iwspr=1
lprinthash22=.false.
if(params%nmode.eq.242) lprinthash22=.true.
call timer('dec_fst4',0)
call my_fst4%decode(fst4_decoded,id2,params%nutc, &
params%nQSOProgress,params%nfa,params%nfb, &
params%nfqso,ndepth,params%ntr,params%nexp_decode, &
params%ntol,params%emedelay,logical(params%nagain), &
logical(params%lapcqonly),mycall,hiscall,iwspr,lprinthash22)
logical(params%lapcqonly),mycall,hiscall,iwspr)
call timer('dec_fst4',1)
go to 800
endif
@ -731,7 +705,7 @@ contains
end subroutine ft4_decoded
subroutine fst4_decoded (this,nutc,sync,nsnr,dt,freq,decoded,nap, &
qual,ntrperiod,fmid,w50)
qual,ntrperiod,lwspr,fmid,w50)
use fst4_decode
implicit none
@ -746,6 +720,7 @@ contains
integer, intent(in) :: nap
real, intent(in) :: qual
integer, intent(in) :: ntrperiod
logical, intent(in) :: lwspr
real, intent(in) :: fmid
real, intent(in) :: w50

View File

@ -20,7 +20,7 @@ subroutine four2a(a,nfft,ndim,isign,iform)
! actual computations.
use fftw3
parameter (NPMAX=2100) !Max number of stored plans
parameter (NPMAX=2100) !Max numberf of stored plans
parameter (NSMALL=16385) !Max half complex size of "small" FFTs
complex a(nfft) !Array to be transformed
complex aa(NSMALL) !Local copy of "small" a()

View File

@ -171,15 +171,15 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
if( ndeep.eq. 1) then
nord=1
xlambda=0.0
nsyndmax=np
nsyncmax=np
elseif(ndeep.eq.2) then
nord=2
xlambda=0.0
nsyndmax=np
nsyncmax=np
elseif(ndeep.eq.3) then
nord=3
xlambda=4.0
nsyndmax=11
nsyncmax=11
elseif(ndeep.eq.4) then
nord=4
xlambda=3.4
@ -190,6 +190,7 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
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
@ -215,6 +216,7 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,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
@ -222,6 +224,7 @@ subroutine fastosd240_74(llr,k,apmask,ndeep,message74,cw,nhardmin,dmin)
call nextpat74(mi,k,iorder,iflag)
enddo
enddo
998 continue
! Re-order the codeword to [message bits][parity bits] format.
cw(indices)=cw

View File

@ -93,10 +93,6 @@ program fst4sim
if(i3.eq.1) then
write(*,*) ' mycall hiscall hisgrid'
write(*,'(28i1,1x,i1,1x,28i1,1x,i1,1x,i1,1x,15i1,1x,3i1)') msgbits(1:77)
elseif(i3.eq.0 .and. n3.eq.6) then
write(*,'(a15,37x,a5)') '50-bit message','CRC24'
write(*,'(50i1,1x,24i1)') msgbits(1:50),msgbits(51:74)
write(*,'(a50)') '01234567890123456789012345678901234567890123456789'
else
write(*,'(a14)') 'Message bits: '
write(*,'(77i1,1x,24i1)') msgbits

View File

@ -4,47 +4,33 @@ program ldpcsim240_74
use packjt77
parameter(N=240, NN=120)
parameter(N=240, K=74, M=N-K)
character*8 arg
character*37 msg0,msgsent,msg
character*37 msg0
character*77 c77
character*24 c24
integer*1 msgbits(101)
integer*1 msgbits(74)
integer*1 apmask(240)
integer*1 cw(240)
integer*1 codeword(N),message74(74)
integer ncrc24
integer modtype, graymap(0:3)
integer*4 itone(120)
integer channeltype
integer lmax(1)
real rxdata(N)
real llr(240)
real bitmetrics(2*NN,4)
complex c1(4,8),c2(16,4),c4(256,2),cs(0:3,NN)
real s2(0:65535)
logical one(0:65535,0:15) ! 65536 8-symbol sequences, 16 bits
real rxdata(N),llr(N)
logical first
data first/.true./
data graymap/0,1,3,2/
nargs=iargc()
if(nargs.ne.7 .and. nargs.ne.8) then
print*,'Usage: ldpcsim maxosd norder #trials s Keff modtype channel '
print*,'e.g. ldpcsim240_74 2 4 1000 0.85 50 1 0'
if(nargs.ne.5 .and. nargs.ne.6) then
print*,'Usage: ldpcsim niter ndeep #trials s K [msg]'
print*,'e.g. ldpcsim240_74 20 5 1000 0.85 64 "K9AN K1JT FN20"'
print*,'s : if negative, then value is ignored and sigma is calculated from SNR.'
print*,'maxosd<0: do bp only'
print*,'maxosd=0: do bp and then call osd once with channel llrs.'
print*,'maxosd>0: do bp and then call osc maxosd times with saved bp outputs.'
print*,'norder : osd decoding depth'
print*,'Keff : # of message bits, Keff must be in the range 50:74'
print*,'modtype : 0 coherent BPSK, 1 4FSK'
print*,'channel : 0 AWGN, 1 Rayleigh (4FSK only)'
print*,'niter: is the number of BP iterations.'
print*,'ndeep: -1 is BP only, ndeep>=0 is OSD order'
print*,'K :is the number of message+CRC bits and must be in the range [50,74]'
print*,'WSPR-format message is optional'
return
endif
call getarg(1,arg)
read(arg,*) maxosd
read(arg,*) max_iterations
call getarg(2,arg)
read(arg,*) norder
call getarg(3,arg)
@ -53,26 +39,17 @@ program ldpcsim240_74
read(arg,*) s
call getarg(5,arg)
read(arg,*) Keff
call getarg(6,arg)
read(arg,*) modtype
call getarg(7,arg)
read(arg,*) channeltype
call getarg(8,arg)
msg0='K9AN EN50 20 '
msg0='K9AN K1JT FN20 '
if(nargs.eq.6) call getarg(6,msg0)
call pack77(msg0,i3,n3,c77)
rate=real(Keff)/real(N)
write(*,*) "code rate: ",rate
write(*,*) "maxosd : ",maxosd
write(*,*) "niter : ",max_iterations
write(*,*) "norder : ",norder
write(*,*) "s : ",s
write(*,*) "K : ",Keff
if(modtype.eq.0) write(*,*) "modtype : coherent BPSK"
if(modtype.eq.1) write(*,*) "modtype : noncoherent 4FSK"
if(channeltype.eq.0) write(*,*) "channel : AWGN"
if(channeltype.eq.1) write(*,*) "channel : Rayleigh"
msgbits=0
read(c77,'(50i1)') msgbits(1:50)
@ -82,170 +59,49 @@ program ldpcsim240_74
call get_crc24(msgbits,74,ncrc24)
write(c24,'(b24.24)') ncrc24
read(c24,'(24i1)') msgbits(51:74)
write(*,'(24i1)') msgbits(51:74)
write(*,'(24i1)') msgbits(51:74)
write(*,*) 'message with crc24'
write(*,'(74i1)') msgbits(1:74)
call encode240_74(msgbits(1:74),codeword)
do i=1,120
is=codeword(2*i)+2*codeword(2*i-1)
itone(i)=graymap(is)
enddo
call encode240_74(msgbits,codeword)
call init_random_seed()
call sgran()
write(*,*) 'codeword'
write(*,'(77i1,1x,24i1,1x,73i1)') codeword
! call init_random_seed()
! call sgran()
one=.false.
do i=0,65535
do j=0,15
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
write(*,*) "Eb/N0 Es/N0 ngood nundetected symbol error rate"
do idb = 24,-8,-1
write(*,*) "Eb/N0 Es/N0 ngood nundetected sigma symbol error rate"
do idb = 8,-3,-1
db=idb/2.0-1.0
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
sigma=1/sqrt( 2*rate*(10**(db/10.0)) ) ! to make db represent Eb/No
! sigma=1/sqrt( 2*(10**(db/10.0)) ) ! db represents Es/No
ngood=0
nue=0
nberr=0
nsymerr=0
do itrial=1, ntrials
! Create a realization of a noisy received word
if(modtype.eq.0) then
iq = 1 ! bits per symbol
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
nberr=nberr+nerr
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
nberr=nberr+nerr
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
! noncoherent MFSK
iq = 2 ! bits per symbol
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) ) ! to make db represent Eb/No
A=1
do i=1,120
do j=0,3
if(j.eq.itone(i)) then
if(channeltype.eq.0) then
A=1.0
elseif(channeltype.eq.1) then
xI=gran()**2+gran()**2
A=sqrt(xI/2)
endif
cs(j,i)= A + sigma*gran() + cmplx(0,1)*sigma*gran()
elseif(j.ne.itone(i)) then
cs(j,i)= sigma*gran() + cmplx(0,1)*sigma*gran()
endif
enddo
lmax=maxloc(abs(cs(:,i)))
if(lmax(1)-1.ne.itone(i) ) nsymerr=nsymerr+1
enddo
do k=1,NN,8
do m=1,8 ! do 4 1-symbol correlations for each of 8 symbs
s2=0
do is=1,4
c1(is,m)=cs(graymap(is-1),k+m-1)
s2(is-1)=abs(c1(is,m))
enddo
ipt=(k-1)*2+2*(m-1)+1
do ib=0,1
bm=maxval(s2(0:3),one(0:3,1-ib)) - &
maxval(s2(0:3),.not.one(0:3,1-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,1)=bm
enddo
enddo
do m=1,4 ! do 16 2-symbol correlations for each of 4 2-symbol groups
s2=0
do i=1,4
do j=1,4
is=(i-1)*4+j
c2(is,m)=c1(i,2*m-1)+c1(j,2*m)
s2(is-1)=abs(c2(is,m))**2
enddo
enddo
ipt=(k-1)*2+4*(m-1)+1
do ib=0,3
bm=maxval(s2(0:15),one(0:15,3-ib)) - &
maxval(s2(0:15),.not.one(0:15,3-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,2)=bm
enddo
enddo
do m=1,2 ! do 256 4-symbol corrs for each of 2 4-symbol groups
s2=0
do i=1,16
do j=1,16
is=(i-1)*16+j
c4(is,m)=c2(i,2*m-1)+c2(j,2*m)
s2(is-1)=abs(c4(is,m))
enddo
enddo
ipt=(k-1)*2+8*(m-1)+1
do ib=0,7
bm=maxval(s2(0:255),one(0:255,7-ib)) - &
maxval(s2(0:255),.not.one(0:255,7-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,3)=bm
enddo
enddo
s2=0 ! do 65536 8-symbol correlations for the entire group
do i=1,256
do j=1,256
is=(i-1)*256+j
s2(is-1)=abs(c4(i,1)+c4(j,2))
enddo
enddo
ipt=(k-1)*2+1
do ib=0,15
bm=maxval(s2(0:65535),one(0:65535,15-ib)) - &
maxval(s2(0:65535),.not.one(0:65535,15-ib))
if(ipt+ib.gt.2*NN) cycle
bitmetrics(ipt+ib,4)=bm
enddo
enddo
call normalizebmet(bitmetrics(:,1),2*NN)
call normalizebmet(bitmetrics(:,2),2*NN)
call normalizebmet(bitmetrics(:,3),2*NN)
call normalizebmet(bitmetrics(:,4),2*NN)
scalefac=2.83
bitmetrics=scalefac*bitmetrics
llr=bitmetrics(:,1)
ss=s
endif
llr=2.0*rxdata/(ss*ss)
apmask=0
dmin=0.0
maxosd=2
call decode240_74(llr, Keff, maxosd, norder, apmask, message74, cw, ntype, nharderror, dmin)
if(nharderror.ge.0) then
n2err=0
@ -260,10 +116,9 @@ program ldpcsim240_74
endif
enddo
! snr2500=db+10*log10(200.0/116.0/2500.0)
esn0=db+10*log10(rate*iq)
pberr=real(nberr)/real(ntrials*N)
pserr=real(nsymerr)/real(ntrials*120)
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,e10.3)") db,esn0,ngood,nue,pserr
esn0=db+10*log10(rate)
pberr=real(nberr)/(real(ntrials*N))
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,e10.3)") db,esn0,ngood,nue,pberr
enddo

View File

@ -8,7 +8,7 @@ module fst4_decode
abstract interface
subroutine fst4_decode_callback (this,nutc,sync,nsnr,dt,freq, &
decoded,nap,qual,ntrperiod,fmid,w50)
decoded,nap,qual,ntrperiod,lwspr,fmid,w50)
import fst4_decoder
implicit none
class(fst4_decoder), intent(inout) :: this
@ -21,6 +21,7 @@ module fst4_decode
integer, intent(in) :: nap
real, intent(in) :: qual
integer, intent(in) :: ntrperiod
logical, intent(in) :: lwspr
real, intent(in) :: fmid
real, intent(in) :: w50
end subroutine fst4_decode_callback
@ -30,7 +31,7 @@ contains
subroutine decode(this,callback,iwave,nutc,nQSOProgress,nfa,nfb,nfqso, &
ndepth,ntrperiod,nexp_decode,ntol,emedelay,lagain,lapcqonly,mycall, &
hiscall,iwspr,lprinthash22)
hiscall,iwspr)
use prog_args
use timer_module, only: timer
@ -66,10 +67,9 @@ contains
integer mcq(29),mrrr(19),m73(19),mrr73(19)
logical badsync,unpk77_success,single_decode
logical first,nohiscall
logical first,nohiscall,lwspr
logical new_callsign,plotspec_exists,wcalls_exists,do_k50_decode
logical decdata_exists
logical lprinthash22
integer*2 iwave(30*60*12000)
@ -88,8 +88,7 @@ contains
dxcall13=hiscall ! initialize for use in packjt77
mycall13=mycall
if(iwspr.ne.0 .and. iwspr.ne.1) return
if(iwspr.ne.0.and.iwspr.ne.1) return
if(lagain) continue ! use lagain to keep compiler happy
if(first) then
@ -504,13 +503,6 @@ contains
write(c77,'(50i1)') message74(1:50)
c77(51:77)='000000000000000000000110000'
call unpack77(c77,1,msg,unpk77_success)
if(lprinthash22 .and. unpk77_success .and. index(msg,'<...>').gt.0) then
read(c77,'(b22.22)') n22tmp
i1=index(msg,' ')
wpart=trim(msg(i1+1:))
write(msg,'(a1,i7.7,a1)') '<',n22tmp,'>'
msg=trim(msg)//' '//trim(wpart)
endif
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,' ')
@ -610,7 +602,6 @@ contains
case(1800)
snr_calfac=320.0
case default
snr_calfac=430.0
end select
arg=snr_calfac*xsig/base - 1.0
if(arg.gt.0.0) then
@ -635,7 +626,8 @@ contains
close(21)
endif
call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, &
iaptype,qual,ntrperiod,fmid,w50)
iaptype,qual,ntrperiod,lwspr,fmid,w50)
! if(iwspr.eq.0 .and. nb.lt.0) go to 900
goto 800
endif
enddo ! metrics
@ -996,7 +988,7 @@ contains
do i=-ia,ia !Find freq range that has 50% of signal power
sum2=sum2 + ss(i)-avg
if(sum2.ge.0.25*sum1 .and. xi1.eq.-999.0) then
xi1=i - 1 + (0.25*sum1-sum2)/(sum2-sum2z)
xi1=i - 1 + (sum2-0.25*sum1)/(sum2-sum2z)
endif
if(sum2.ge.0.50*sum1 .and. xi2.eq.-999.0) then
xi2=i - 1 + (sum2-0.50*sum1)/(sum2-sum2z)

View File

@ -15,7 +15,7 @@ subroutine foxgen()
! common block.
parameter (NN=79,ND=58,NSPS=4*1920)
parameter (NWAVE=(160+2)*134400*4) ! the biggest waveform we generate (FST4-1800 at 48kHz)
parameter (NWAVE=(160+2)*134400*4) !the biggest waveform we generate (FST4-1800 at 48kHz)
parameter (NFFT=614400,NH=NFFT/2)
character*40 cmsg
character*37 msg,msgsent

View File

@ -2,50 +2,38 @@ program ldpcsim174_91
! End to end test of the (174,91)/crc14 encoder and decoder.
use packjt77
integer, parameter:: N=174, K=91, M=N-K, NN=58
character*37 msg,msgsent
integer, parameter:: N=174, K=91, M=N-K
character*37 msg,msgsent,msgreceived
character*77 c77
character*8 arg
character*6 grid
character*96 tmpchar
integer*1, allocatable :: codeword(:), decoded(:), message(:)
integer*1 msgbits(77)
integer*1 message91(91)
integer*1 message77(77),message91(91)
integer*1 apmask(N), cw(N)
integer lmax(1)
integer modtype, itone(79), itonecw(58), graymap(0:7)
integer nerrtot(0:N),nerrdec(0:N)
integer channeltype
logical unpk77_success
logical one(0:511,0:8)
real*8, allocatable :: rxdata(:)
real llr(174),llra(174),llrb(174),llrc(174),llrd(174)
real bmeta(174),bmetb(174),bmetc(174),bmetd(174)
complex cs(0:7,NN)
real s2(0:511)
data graymap/0,1,3,2,5,6,4,7/
real, allocatable :: llr(:)
nerrtot=0
nerrdec=0
!
nargs=iargc()
if(nargs.ne.7) then
print*,'Usage: ldpcsim maxosd norder #trials s Keff modtype channel'
print*,'eg: ldpcsim 10 2 1000 0.84 91 1 0'
print*,' maxosd<0: do bp only'
print*,' maxosd=0: do bp and then call osd once with channel llrs'
print*,' maxosd>1: do bp and then call osd maxosd times with saved bp outputs'
print*,' norder : osd decoding depth'
print*,' s : BPSK only, noise sigma, if s<0 value is ignored and sigma is calculated from SNR.'
print*,' Keff : Keff must be in the range [77,91]; Keff-77 is the # of bits to use as CRC.'
print*,' modtype : 0, coherent BPSK; 1 noncoherent 8FSK'
print*,' channel : 0, AWGN; 1, block Rayleigh (Rayleigh only works with 8FSK!)'
if(nargs.ne.6) then
print*,'Usage: ldpcsim niter ndepth #trials s Keff nbposd'
print*,'eg: ldpcsim 10 2 1000 0.84 91 1'
print*,'niter: max BP iterations'
print*,'ndepth: OSD order'
print*,'s: noise sigma; if negative value is ignored and sigma is calculated from SNR.'
print*,'nbposd=0, no coupling. nbposd>0, maxsuper=nbposd; nbposd<0, no OSD'
return
endif
call getarg(1,arg)
read(arg,*) maxosd
read(arg,*) max_iterations
call getarg(2,arg)
read(arg,*) norder
read(arg,*) ndepth
call getarg(3,arg)
read(arg,*) ntrials
call getarg(4,arg)
@ -53,24 +41,16 @@ program ldpcsim174_91
call getarg(5,arg)
read(arg,*) Keff
call getarg(6,arg)
read(arg,*) modtype
call getarg(7,arg)
read(arg,*) channeltype
read(arg,*) nbposd
! scale Eb/No for a (174,91) code
rate=real(K)/real(N)
write(*,*) "rate: ",rate
write(*,*) "niter= ",max_iterations," s= ",s
allocate ( codeword(N), decoded(K), message(K) )
allocate ( rxdata(N) )
one=.false.
do i=0,511
do j=0,8
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
allocate ( rxdata(N), llr(N) )
msg="K9ABC K1ABC FN20"
i3=0
@ -85,144 +65,47 @@ program ldpcsim174_91
call init_random_seed()
iq=1
if(modtype.gt.0) then ! MFSK - get tones
i3=-1
n3=-1
call genft8(msg,i3,n3,msgsent,msgbits,itone)
write(*,*) 'message tones'
write(*,'(79(i1,1x))') itone
itonecw(1:29)=itone(8:36)
itonecw(30:58)=itone(44:72)
iq=3 ! bits per symbol
endif
call encode174_91(msgbits,codeword)
write(*,*) 'crc14'
write(*,'(14i1)') codeword(78:91)
write(*,*) 'codeword'
write(*,'(22(8i1,1x))') codeword
write(*,*) 'Eb/N0 Es/N0 SNR2500 ngood nundetected sigma psymerr pbiterr'
do idb = 20,-4,-1
nsymerr=0
nbiterr=0
write(*,*) "Eb/N0 Es/N0 ngood nundetected sigma psymerr"
do idb = 10,-4,-1
db=idb/2.0-1.0
sigma=1/sqrt( 2*rate*iq*(10**(db/10.0)) )
sigma=1/sqrt( 2*rate*(10**(db/10.0)) )
ngood=0
nue=0
nsumerr=0
do itrial=1, ntrials
! Create a realization of a noisy received word
if(modtype.eq.0) then
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1
do i=1,N
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
enddo
nerr=0
do i=1,N
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
enddo
if(nerr.ge.1) nerrtot(nerr)=nerrtot(nerr)+1
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
if( s .lt. 0 ) then
ss=sigma
else
! noncoherent MFSK
do i=1,58
do j=0,7
if(j.eq.itonecw(i)) then
if(channeltype.eq.0) then
A=1.0
elseif(channeltype.eq.1) then
xI=gran()**2 + gran()**2
A=sqrt(xI/2)
endif
cs(j,i)= A + sigma*gran() + cmplx(0,1)*sigma*gran()
elseif(j.ne.itonecw(i)) then
cs(j,i)= sigma*gran() + cmplx(0,1)*sigma*gran()
endif
enddo
lmax=maxloc(abs(cs(:,i)))
if(lmax(1)-1.ne.itonecw(i) ) nsymerr=nsymerr+1
enddo
do nsym=1,3
nt=2**(3*nsym)
do ks=1,58,nsym
amax=-1.0
do i=0,nt-1
i1=i/64
i2=iand(i,63)/8
i3=iand(i,7)
if(nsym.eq.1) then
s2(i)=abs(cs(graymap(i3),ks))
elseif(nsym.eq.2) then
s2(i)=abs(cs(graymap(i2),ks)+cs(graymap(i3),ks+1))
elseif(nsym.eq.3) then
if(ks.ne.58) then
s2(i)=abs(cs(graymap(i1),ks)+cs(graymap(i2),ks+1)+cs(graymap(i3),ks+2))
else
s2(i)=abs(cs(graymap(i1),ks))
endif
else
print*,"Error - nsym must be 1, 2, or 3."
endif
enddo
i32=1+(ks-1)*3
if(nsym.eq.1) ibmax=2
if(nsym.eq.2) ibmax=5
if(nsym.eq.3) ibmax=8
do ib=0,ibmax
bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
if(i32+ib .gt.174) cycle
if(nsym.eq.1) then
bmeta(i32+ib)=bm
den=max(maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)), &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib)))
if(den.gt.0.0) then
cm=bm/den
else ! erase it
cm=0.0
endif
bmetd(i32+ib)=cm
elseif(nsym.eq.2) then
bmetb(i32+ib)=bm
elseif(nsym.eq.3) then
bmetc(i32+ib)=bm
endif
enddo
enddo
enddo
call normalizebmet(bmeta,174)
call normalizebmet(bmetb,174)
call normalizebmet(bmetc,174)
call normalizebmet(bmetd,174)
scalefac=2.83
llra=scalefac*bmeta
llrb=scalefac*bmetb
llrc=scalefac*bmetc
llrd=scalefac*bmetd
llr=llrc
ss=s
endif
do i=1, 174
if(llr(i)*(codeword(i)-0.5).lt.0) nbiterr=nbiterr+1
enddo
llr=2.0*rxdata/(ss*ss)
nap=0 ! number of AP bits
llr(1:nap)=5*(2.0*msgbits(1:nap)-1.0)
apmask=0
apmask(1:nap)=1
call decode174_91(llr,Keff,maxosd,norder,apmask,message91,cw,ntype,nharderrors,dmin)
call decode174_91(llr,Keff,nbposd,ndepth,apmask,message91,cw,ntype,nharderrors,dmin)
! If the decoder finds a valid codeword, nharderrors will be .ge. 0.
if( nharderrors.ge.0 ) then
nhw=count(cw.ne.codeword)
@ -236,12 +119,9 @@ program ldpcsim174_91
nsumerr=nsumerr+nerr
enddo
esn0=db+10.0*log10(iq*rate) ! iq=3 bits per symbol for 8FSK
snr2500=esn0-10.0*log10(2500/6.25)
! pberr=real(nsumerr)/(real(ntrials*N))
psymerr=real(nsymerr)/(ntrials*174.0/iq)
pbiterr=real(nbiterr)/(ntrials*174.0)
write(*,"(f4.1,4x,f5.1,4x,f5.1,1x,i8,1x,i8,8x,f5.2,8x,e10.3,8x,e10.3)") db,esn0,snr2500,ngood,nue,ss,psymerr,pbiterr
esn0=db+10.0*log10(rate)
pberr=real(nsumerr)/(real(ntrials*N))
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,8x,f5.2,8x,e10.3)") db,esn0,ngood,nue,ss,pberr
enddo
@ -252,18 +132,3 @@ program ldpcsim174_91
close(23)
end program ldpcsim174_91
subroutine normalizebmet(bmet,n)
real bmet(n)
bmetav=sum(bmet)/real(n)
bmet2av=sum(bmet*bmet)/real(n)
var=bmet2av-bmetav*bmetav
if( var .gt. 0.0 ) then
bmetsig=sqrt(var)
else
bmetsig=sqrt(bmet2av)
endif
bmet=bmet/bmetsig
return
end subroutine normalizebmet

View File

@ -1,4 +1,5 @@
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,candidate,ncand,sbase)
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,nzhsym,candidate, &
ncand,sbase)
include 'ft8_params.f90'
parameter (MAXPRECAND=1000)

View File

@ -46,6 +46,7 @@ contains
procedure(ft8_decode_callback) :: callback
parameter (MAXCAND=600,MAX_EARLY=100)
real*8 tsec,tseq
real s(NH1,NHSYM)
real sbase(NH1)
real candidate(3,MAXCAND)
real dd(15*12000),dd1(15*12000)
@ -60,14 +61,14 @@ contains
character datetime*13,msg37*37
character*37 allmessages(200)
character*12 ctime
integer allsnrs(200)
integer allsnrs(100)
integer itone(NN)
integer itone_save(NN,MAX_EARLY)
real f1_save(MAX_EARLY)
real xdt_save(MAX_EARLY)
data nutc0/-1/
save dd,dd1,nutc0,ndec_early,itone_save,f1_save,xdt_save,lsubtracted, &
save s,dd,dd1,nutc0,ndec_early,itone_save,f1_save,xdt_save,lsubtracted,&
allmessages
this%callback => callback
@ -192,7 +193,8 @@ contains
endif
call timer('sync8 ',0)
maxc=MAXCAND
call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,candidate,ncand,sbase)
call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,nzhsym,candidate, &
ncand,sbase)
call timer('sync8 ',1)
do icand=1,ncand
sync=candidate(3,icand)

View File

@ -1,132 +0,0 @@
subroutine get_q3list(fname,bDiskData,nlist,list)
type q3list
character*6 call
character*4 grid
integer nsec
integer nfreq
integer moonel
end type q3list
parameter (MAX_CALLERS=40)
character*(*) fname
character*36 list(40)
character*8 grid6
logical*1 bDiskData
integer time
integer nt(8)
integer indx(MAX_CALLERS)
type(q3list) ctmp(MAX_CALLERS),callers(MAX_CALLERS)
character*256 jpleph_file_name,file24name
common/jplcom/jpleph_file_name
common/lu24com/file24name
nhist2=0
open(24,file=fname,status='unknown',form='unformatted')
read(24,end=1) nhist2
if(nhist2.ge.1 .and. nhist2.le.40) then
read(24,end=1) ctmp(1:nhist2)
else
nhist2=0
endif
1 rewind 24
if(nhist2.eq.0) go to 900
now=time()
call date_and_time(values=nt)
uth=nt(5) + (nt(6)-nt(4))/60.0 + nt(7)/3600.0
j=0
do i=1,nhist2
age=(now - ctmp(i)%nsec)/3600.0
if(age.gt.24.0) cycle
grid6=ctmp(i)%grid//'mm'
call grid2deg(grid6,xlon,xlat)
call sun(nt(1),nt(2),nt(3),uth,-xlon,xlat,RASun,DecSun,xLST, &
AzSun,ElSun,mjd,day)
call moondopjpl(nt(1),nt(2),nt(3),uth,-xlon,xlat,RAMoon,DecMoon, &
xLST,HA,AzMoon,ElMoon,vr,techo)
if(ElMoon.lt.-5.0 .and. (.not.bDiskData)) cycle
j=j+1 !Keep this one...
callers(j)=ctmp(i)
callers(j)%moonel=nint(ElMoon) !... and save its current moonel
enddo
nhist2=j
write(24) nhist2
write(24) callers(1:nhist2)
call indexx(callers(1:nhist2)%nfreq,nhist2,indx)
do i=1,nhist2
j=indx(i)
moon_el=nint(ElMoon)
age=(now - callers(j)%nsec)/3600.0
write(list(i),1000) i,callers(j)%nfreq,callers(j)%call, &
callers(j)%grid,callers(j)%moonel,age,char(0)
1000 format(i2,'.',i6,2x,a6,2x,a4,i5,f7.1,a1)
! h1=mod(now,86400)/3600.0
! h2=mod(callers(i)%nsec,86400)/3600.0
! hd=h1-h2
! if(hd.lt.0.0) hd=hd+24.0
! write(*,3301) i,callers(i)%call,now,callers(i)%nsec,h1,h2,hd
!3301 format(i3,2x,a6,2i12,3f10.6)
enddo
900 close(24)
nlist=nhist2
file24name=fname
return
end subroutine get_q3list
subroutine rm_q3list(dxcall0)
parameter (MAX_CALLERS=40)
type q3list
character*6 call
character*4 grid
integer nsec
integer nfreq
integer moonel
end type q3list
character*(*) dxcall0
character*6 dxcall
character*256 file24name
type(q3list) callers(MAX_CALLERS)
common/lu24com/file24name
dxcall=dxcall0
open(24,file=trim(file24name),status='unknown',form='unformatted')
read(24) nhist2
read(24) callers(1:nhist2)
if(nhist2.eq.MAX_CALLERS .and. dxcall.eq.callers(nhist2)%call) then
nhist2=MAX_CALLERS - 1
go to 10
endif
iz=nhist2
do i=1,iz
if(callers(i)%call .eq. dxcall) then
nhist2=nhist2-1
callers(i:nhist2)=callers(i+1:nhist2+1) !Remove dxcall from q3list
exit
endif
enddo
10 rewind 24
write(24) nhist2
write(24) callers(1:nhist2)
close(24)
return
end subroutine rm_q3list
subroutine jpl_setup(fname)
character*256 fname,jpleph_file_name
common/jplcom/jpleph_file_name
jpleph_file_name=fname
return
end subroutine jpl_setup

View File

@ -1 +1 @@
gfortran -o chkfft3 chkfft3.f90 four2a.f90 gran.c libfftw3f-3.dll
gfortran -o chkfft chkfft3.f90 four2a.f90 gran.c /jtsdk/fftw3f/libfftw3f-3.dll

View File

@ -27,7 +27,7 @@ program jt9
logical :: read_files = .true., tx9 = .false., display_help = .false., &
bLowSidelobes = .false., nexp_decode_set = .false., &
have_ntol = .false.
type (option) :: long_options(33) = [ &
type (option) :: long_options(31) = [ &
option ('help', .false., 'h', 'Display this help message', ''), &
option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), &
option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', &
@ -60,11 +60,9 @@ program jt9
option ('jt65', .false.,'6', 'JT65 mode', ''), &
option ('fst4', .false., '7', 'FST4 mode', ''), &
option ('fst4w', .false., 'W', 'FST4W mode', ''), &
option ('fst4w', .false., 'Y', 'FST4W mode, print hash22 values', ''), &
option ('ft8', .false., '8', 'FT8 mode', ''), &
option ('jt9', .false., '9', 'JT9 mode', ''), &
option ('qra64', .false., 'q', 'QRA64 mode', ''), &
option ('msk144', .false., 'k', 'MSK144 mode', ''), &
option ('QSOprog', .true., 'Q', 'QSO progress (0-5), default PROGRESS=1',&
'QSOprogress'), &
option ('sub-mode', .true., 'b', 'Sub mode, default SUBMODE=A', 'A'), &
@ -87,12 +85,13 @@ program jt9
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
data npatience/1/,nthreads/1/,wisfile/' '/
iwspr=0
nsubmode = 0
ntol = 20
TRperiod=60.d0
do
call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WYqkTL:S:H:c:G:x:g:X:Q:', &
call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:9876543WqTL:S:H:c:G:x:g:X:Q:', &
long_options,c,optarg,arglen,stat,offset,remain,.true.)
if (stat .ne. 0) then
exit
@ -130,9 +129,7 @@ program jt9
read (optarg(:arglen), *) fhigh
case ('q')
mode = 164
case ('k')
mode = 144
case ('Q')
case ('Q')
read (optarg(:arglen), *) nQSOProg
case ('3')
mode = 66
@ -144,6 +141,7 @@ program jt9
if (mode.lt.65) mode = mode + 65
case ('7')
mode = 240
iwspr=0
case ('8')
mode = 8
case ('9')
@ -154,8 +152,7 @@ program jt9
read (optarg(:arglen), *) npatience
case ('W')
mode = 241
case ('Y')
mode = 242
iwspr=1
case ('c')
read (optarg(:arglen), *) mycall
case ('G')
@ -215,7 +212,7 @@ program jt9
hisgrid=' '
endif
if (mode .eq. 241 .or. mode .eq. 242) then
if (mode .eq. 241) then
ntol = min (ntol, 100)
else if (mode .eq. 65 + 9 .and. .not. have_ntol) then
ntol = 20
@ -225,7 +222,7 @@ program jt9
ntol = min (ntol, 1000)
end if
if (.not. nexp_decode_set) then
if (mode .eq. 240 .or. mode .eq. 241 .or. mode .eq. 242) then
if (mode .eq. 240 .or. mode .eq. 241) then
nexp_decode = 3 * 256 ! single decode off and nb=0
end if
end if
@ -280,8 +277,7 @@ program jt9
call timer('symspec ',1)
endif
nhsym0=nhsym
if(nhsym.ge.181 .and. mode.ne.240 .and. mode.ne.241 .and. &
mode.ne.242 .and. mode.ne.66) exit
if(nhsym.ge.181 .and. mode.ne.240 .and. mode.ne.241 .and. mode.ne.66) exit
endif
enddo
close(unit=wav%lun)
@ -298,6 +294,7 @@ program jt9
shared_data%params%kin=64800
if(mode.eq.240) shared_data%params%kin=720000 !### 60 s periods ###
shared_data%params%nzhsym=nhsym
if(mode.eq.240 .and. iwspr.eq.1) ndepth=ior(ndepth,128)
shared_data%params%ndepth=ndepth
shared_data%params%lft8apon=.true.
shared_data%params%ljt65apon=.true.
@ -355,12 +352,7 @@ program jt9
call multimode_decoder(shared_data%ss,id2a, &
shared_data%params,nfsample)
cycle
! MSK144
else if (mode .eq. 144) then
call decode_msk144(shared_data%id2, shared_data%params, data_dir)
endif
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2, &
shared_data%params,nfsample)

View File

@ -70,15 +70,8 @@ subroutine jt9a()
call multimode_decoder(shared_data%ss,id2a,local_params,12000)
local_params%nzhsym=50
endif
if(local_params%nmode .eq. 144) then
! MSK144
call decode_msk144(shared_data%id2, shared_data%params, data_dir)
else
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
endif
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
call timer('decoder ',1)

View File

@ -1,5 +1,5 @@
subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
ntol,newdat,nagain,max_drift,ndepth,mycall,hiscall,hisgrid)
subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, &
nagain,max_drift,mycall,hiscall,hisgrid)
use prog_args
use timer_module, only: timer
@ -14,8 +14,8 @@ subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
logical single_decode,bVHF,lnewdat,lagain,lclearave,lapcqonly
integer*2 id2(300*12000)
integer nqf(20)
! type(params_block) :: params
character(len=20) :: datetime
character(len=12) :: mycall, hiscall
character(len=6) :: hisgrid
data ntr0/-1/
@ -28,7 +28,8 @@ subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
! hiscall=transfer(params%hiscall,hiscall)
! mygrid=transfer(params%mygrid,mygrid)
! hisgrid=transfer(params%hisgrid,hisgrid)
datetime=' '
my_q65%decoded = 0
ncontest=0
nQSOprogress=0
@ -39,12 +40,16 @@ subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
lagain=(nagain.ne.0)
bVHF=.true.
emedelay=2.5
! ntrperiod=60
ndepth=1
ntrperiod=60
open(17,file=trim(temp_dir)//'/red.dat',status='unknown')
open(14,file=trim(temp_dir)//'/avemsg.txt',status='unknown')
call timer('dec_q65 ',0)
call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, &
ntol,ndepth,nfa,nfb,lclearave,single_decode,lagain,max_drift,lnewdat, &
emedelay,mycall,hiscall,hisgrid,nQSOProgress,ncontest,lapcqonly,navg0,nqf)
emedelay,mycall,hiscall,hisgrid,nQSOProgress,ncontest,lapcqonly,navg0)
call timer('dec_q65 ',1)
return

View File

@ -3,10 +3,6 @@ subroutine pctile(x,npts,npct,xpct)
real x(npts)
real,allocatable :: tmp(:)
if(npts.lt.0 .or. npct.lt.0 .or. npct.gt.100) then
xpct=1.0
go to 900
endif
allocate(tmp(npts))
tmp=x
@ -15,7 +11,6 @@ subroutine pctile(x,npts,npct,xpct)
if(j.lt.1) j=1
if(j.gt.npts) j=npts
xpct=tmp(j)
deallocate(tmp)
900 return
return
end subroutine pctile

View File

@ -33,7 +33,7 @@ contains
subroutine decode(this,callback,iwave,nqd0,nutc,ntrperiod,nsubmode,nfqso, &
ntol,ndepth,nfa0,nfb0,lclearave,single_decode,lagain,max_drift0, &
lnewdat0,emedelay,mycall,hiscall,hisgrid,nQSOprogress,ncontest, &
lapcqonly,navg0,nqf)
lapcqonly,navg0)
! Top-level routine that organizes the decoding of Q65 signals
! Input: iwave Raw data, i*2
@ -55,13 +55,9 @@ contains
use, intrinsic :: iso_c_binding
use q65 !Shared variables
use prog_args
use types
parameter (NMAX=300*12000) !Max TRperiod is 300 s
parameter (MAX_CALLERS=40) !For multiple q3 decodes in NA VHf Contest mode
parameter (NMAX=300*12000) !Max TRperiod is 300 s
class(q65_decoder), intent(inout) :: this
procedure(q65_decode_callback) :: callback
character(len=12) :: mycall, hiscall !Used for AP decoding
character(len=6) :: hisgrid
@ -74,26 +70,19 @@ contains
character*80 fmt
integer*2 iwave(NMAX) !Raw data
real, allocatable :: dd(:) !Raw data
real xdtdecodes(100)
real f0decodes(100)
integer dat4(13) !Decoded message as 12 6-bit integers
integer dgen(13)
integer nqf(20)
integer stageno !Added by W3SZ
integer time
logical lclearave,lnewdat0,lapcqonly,unpk77_success
logical single_decode,lagain
complex, allocatable :: c00(:) !Analytic signal, 6000 Sa/s
complex, allocatable :: c0(:) !Analytic signal, 6000 Sa/s
type(q3list) callers(MAX_CALLERS)
integer stageno !Added by W3SZ
stageno=0
! Start by setting some parameters and allocating storage for large arrays
call sec0(0,tdecode)
stageno=0
ndecodes=0
decodes=' '
f0decodes=0.
xdtdecodes=0.
nfa=nfa0
nfb=nfb0
nqd=nqd0
@ -108,30 +97,9 @@ contains
nfft1=ntrperiod*12000
nfft2=ntrperiod*6000
npasses=1
nhist2=0
if(lagain) ndepth=ior(ndepth,3) !Use 'Deep' for manual Q65 decodes
dxcall13=hiscall ! initialize for use in packjt77
mycall13=mycall
if(ncontest.eq.1) then
! NA VHF, WW-Digi, or ARRL Digi Contest
open(24,file=trim(data_dir)//'/tsil.3q',status='unknown', &
form='unformatted')
read(24,end=2) nhist2
if(nhist2.ge.1 .and. nhist2.le.40) then
read(24,end=2) callers(1:nhist2)
now=time()
do i=1,nhist2
hours=(now - callers(i)%nsec)/3600.0
if(hours.gt.24.0) then
callers(i:nhist2-1)=callers(i+1:nhist2)
nhist2=nhist2-1
endif
enddo
else
nhist2=0
endif
2 close(24)
endif
! Determine the T/R sequence: iseq=0 (even), or iseq=1 (odd)
n=nutc
@ -164,37 +132,25 @@ contains
baud=12000.0/nsps
this%callback => callback
nFadingModel=1
! ibwa=max(1,int(1.8*log(baud*mode_q65)) + 5)
!### This needs work!
ibwa=1 !Q65-60A
if(mode_q65.eq.2) ibwa=3 !Q65-60B
if(mode_q65.eq.4) ibwa=8 !Q65-60C
if(mode_q65.eq.8) ibwa=8 !Q65-60D
if(mode_q65.eq.16) ibwa=8 !Q65-60E
!###
! ibwb=min(15,ibwa+4)
ibwb=min(15,ibwa+6)
maxiters=40
if(iand(ndepth,3).eq.2) maxiters=60
maxiters=33
ibwa=max(1,int(1.8*log(baud*mode_q65)) + 1)
ibwb=min(10,ibwa+2)
if(iand(ndepth,3).ge.2) then
ibwa=max(1,int(1.8*log(baud*mode_q65)) + 1)
ibwb=min(10,ibwa+5)
maxiters=67
endif
if(iand(ndepth,3).eq.3) then
ibwa=max(1,ibwa-2)
ibwb=min(15,ibwb+2)
ibwa=max(1,ibwa-1)
ibwb=min(10,ibwb+1)
maxiters=100
endif
! Generate codewords for full-AP list decoding
if(ichar(hiscall(1:1)).eq.0) hiscall=' '
if(ichar(hisgrid(1:1)).eq.0) hisgrid=' '
ncw=0
if(nqd.eq.1 .or. lagain .or. ncontest.eq.1) then
if(ncontest.eq.1) then
call q65_set_list2(mycall,hiscall,hisgrid,callers,nhist2, &
codewords,ncw)
else
call q65_set_list(mycall,hiscall,hisgrid,codewords,ncw)
endif
if(nqd.eq.1 .or. lagain) then
call q65_set_list(mycall,hiscall,hisgrid,codewords,ncw)
endif
dgen=0
call q65_enc(dgen,codewords) !Initialize the Q65 codec
@ -210,9 +166,11 @@ contains
call timer('q65_dec0',0)
! Call top-level routine in q65 module: establish sync and try for a
! q3 or q0 decode.
call q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('q65_dec0',1)
! write(*,3001) '=a',nfqso,ntol,ndepth,xdt,f0,idec
!3001 format(a2,3i5,f7.2,f7.1,i5)
if(idec.ge.0) then
dtdec=xdt !We have a q3 or q0 decode at nfqso
@ -220,9 +178,6 @@ contains
go to 100
endif
if(ncontest.eq.1 .and. lagain .and. iand(ndepth,16).eq.16) go to 50
if(ncontest.eq.1 .and. lagain .and. iand(ndepth,16).eq.0) go to 100
! Prepare for a single-period decode with iaptype = 0, 1, 2, or 4
jpk0=(xdt+1.0)*6000 !Index of nominal start of signal
if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000 !For shortest sequences
@ -245,10 +200,11 @@ contains
read(c78,1060) apsymbols
endif
call timer('q65loop1',0)
call timer('q65loops',0)
call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, &
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
call timer('q65loop1',1)
call timer('q65loops',1)
! write(*,3001) '=b',nfqso,ntol,ndepth,xdt,f0,idec
if(idec.ge.0) then
dtdec=xdt1
f0dec=f1
@ -259,11 +215,11 @@ contains
if(iand(ndepth,16).eq.0 .or. navg(iseq).lt.2) go to 100
! There was no single-transmission decode. Try for an average 'q3n' decode.
50 iavg=1
call timer('list_avg',0)
50 call timer('list_avg',0)
! Call top-level routine in q65 module: establish sync and try for a q3
! decode, this time using the cumulative 's1a' symbol spectra.
call q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
iavg=1
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('list_avg',1)
@ -280,7 +236,7 @@ contains
call timer('q65_avg ',0)
iavg=2
call q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('q65_avg ',1)
if(idec.ge.0) then
@ -294,7 +250,7 @@ contains
call timer('q65_dec0',0)
! Call top-level routine in q65 module: establish sync and try for a
! q3 or q0 decode.
call q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('q65_dec0',1)
if(idec.ge.0) then
@ -324,21 +280,15 @@ contains
if(idupe.eq.0) then
ndecodes=min(ndecodes+1,100)
decodes(ndecodes)=decoded
f0decodes(ndecodes)=f0dec
xdtdecodes(ndecodes)=dtdec
call q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
nsnr=nint(snr2)
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
idec,nused,ntrperiod)
if(ncontest.eq.1) then
call q65_hist2(nint(f0dec),decoded,callers,nhist2)
else
call q65_hist(nint(f0dec),msg0=decoded)
endif
call q65_hist(nint(f0dec),msg0=decoded)
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.txt',status='unknown', &
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios)
if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis.
@ -348,13 +298,13 @@ contains
if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,i5,4i2,8i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
fmt='(i6.4,1x,a4,i5,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ibwa,ibwb,ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt, &
f0,snr2,plog,tdecode,mycall(1:6),c6,c4,trim(decoded)
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22)
endif
endif
@ -367,26 +317,6 @@ contains
snr1=candidates(icand,1)
xdt= candidates(icand,2)
f0 = candidates(icand,3)
do i=1,ndecodes
fdiff=f0-f0decodes(i)
if(fdiff.gt.-baud*mode_q65 .and. fdiff.lt.65*baud*mode_q65) go to 800
enddo
!### TEST REGION
if(ncontest.eq.-1) then
call timer('q65_dec0',0)
! Call top-level routine in q65 module: establish sync and try for a
! q3 or q0 decode.
call q65_dec0(iavg,iwave,ntrperiod,nint(f0),ntol,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('q65_dec0',1)
if(idec.ge.0) then
dtdec=xdt !We have a q3 or q0 decode at f0
f0dec=f0
go to 200
endif
endif
!###
jpk0=(xdt+1.0)*6000 !Index of nominal start of signal
if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000 !For shortest sequences
if(jpk0.lt.0) jpk0=0
@ -399,8 +329,6 @@ contains
if(lapcqonly) npasses=1
iaptype=0
do ipass=0,npasses !Loop over AP passes
! write(*,3001) nutc,icand,ipass,f0,xdt,snr1
!3001 format('a',i5.4,2i3,3f7.1)
apmask=0 !Try first with no AP information
apsymbols=0
if(ipass.ge.1) then
@ -413,10 +341,10 @@ contains
read(c78,1060) apsymbols
endif
call timer('q65loop2',0)
call timer('q65loops',0)
call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, &
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
call timer('q65loop2',1)
call timer('q65loops',1)
! write(*,3001) '=e',nfqso,ntol,ndepth,xdt,f0,idec
if(idec.ge.0) then
dtdec=xdt1
@ -437,21 +365,15 @@ contains
if(idupe.eq.0) then
ndecodes=min(ndecodes+1,100)
decodes(ndecodes)=decoded
f0decodes(ndecodes)=f0dec
call q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
nsnr=nint(snr2)
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
idec,nused,ntrperiod)
if(ncontest.eq.1) then
call q65_hist2(nint(f0dec),decoded,callers,nhist2)
else
call q65_hist(nint(f0dec),msg0=decoded)
endif
call q65_hist(nint(f0dec),msg0=decoded)
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode)
ios=1
open(22,file=trim(data_dir)//'/q65_decodes.txt',status='unknown',&
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios)
if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis.
@ -461,45 +383,20 @@ contains
if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,i5,4i2,8i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
fmt='(i6.4,1x,a4,i5,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest, &
idtbest,ibwa,ibwb,ibw,ndistbest,nused,icand,ncand,nrc, &
ndepth,xdt,f0,snr2,plog,tdecode,mycall(1:6),c6,c4, &
trim(decoded)
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22)
endif
endif
endif
800 continue
enddo ! icand
if(iavg.eq.0 .and.navg(iseq).ge.2 .and. iand(ndepth,16).ne.0) go to 50
900 if(ncontest.ne.1 .or. lagain) go to 999
if(ntrperiod.ne.60 .or. nsubmode.ne.0) go to 999
! This is first time here, and we're running Q65-60A in NA VHF Contest mode.
! Return a list of potential sync frequencies at which to try q3 decoding.
k=0
nqf=0
bw=baud*mode_q65*65
do i=1,ncand
! snr1=candidates(i,1)
! xdt= candidates(i,2)
f0 = candidates(i,3)
do j=1,ndecodes ! Already decoded one at or near this frequency?
fj=f0decodes(j)
if(f0.gt.fj-5.0 .and. f0.lt.fj+bw+5.0) go to 990
enddo
k=k+1
nqf(k)=nint(f0)
990 continue
enddo
999 return
900 return
end subroutine decode
end module q65_decode

View File

@ -2,8 +2,8 @@ module q65
parameter (NSTEP=8) !Number of time bins per symbol in s1, s1a, s1b
parameter (PLOG_MIN=-242.0) !List decoding threshold
integer iz0,jz0
! integer listutc(10)
integer nsave,nlist,LL0,iz0,jz0
integer listutc(10)
integer apsym0(58),aph10(10)
integer apmask1(78),apsymbols1(78)
integer apmask(13),apsymbols(13)
@ -12,22 +12,23 @@ module q65
integer codewords(63,206)
integer ibwa,ibwb,ncw,nsps,mode_q65,nfa,nfb,nqd
integer idfbest,idtbest,ibw,ndistbest,maxiters,max_drift
integer istep,nsmo,lag1,lag2,npasses,iseq,ncand,nrc
integer istep,nsmo,lag1,lag2,npasses,nused,iseq,ncand,nrc
integer i0,j0
integer navg(0:1)
logical lnewdat
real candidates(20,3) !snr, xdt, and f0 of top candidates
real, allocatable :: s1raw(:,:) !Symbol spectra, 1/8-symbol steps
real, allocatable :: s1(:,:) !Symbol spectra w/suppressed peaks
real, allocatable :: s1w(:,:) !Symbol spectra w/suppressed peaks (W3SZ)
real, allocatable :: s1w(:,:) !Symbol spectra w/suppressed peaks !w3sz added
real, allocatable,save :: s1a(:,:,:) !Cumulative symbol spectra
real, allocatable,save :: ccf2(:) !Max CCF(freq) at any lag (orange curve)
real, allocatable,save :: ccf2_avg(:) !Like ccf2, but for avg (red curve)
real, allocatable,save :: ccf2(:) !Max CCF(freq) at any lag, single seq
real, allocatable,save :: ccf2_avg(:) !Like ccf2, but for accumulated average
real sync(85) !sync vector
real df,dtstep,dtdec,f0dec,ftol,plog,drift
contains
subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
! Top-level routine in q65 module
@ -40,6 +41,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
! ntrperiod T/R sequence length (s)
! nfqso Target frequency (Hz)
! ntol Search range around nfqso (Hz)
! ndepth Requested decoding depth
! lclearave Flag to clear the accumulating array
! emedelay Extra delay for EME signals
! Output: xdt Time offset from nominal (s)
@ -66,7 +68,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
real, allocatable :: s3(:,:) !Data-symbol energies s3(LL,63)
real, allocatable :: ccf1(:) !CCF(freq) at fixed lag (red)
data first/.true./
save first,LL0
save first
integer w3t
integer w3f
@ -74,6 +76,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
integer stageno
NN=63
if(nutc+ndepth.eq.-999) stop !Silence compiler warnings
! Set some parameters and allocate storage for large arrays
irc=-2
@ -92,8 +95,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
ftol=ntol
ia=ntol/df
ia2=max(ia,10*mode_q65,nint(100.0/df))
! nsmo=int(0.7*mode_q65*mode_q65)
nsmo=int(0.5*mode_q65*mode_q65)
nsmo=int(0.7*mode_q65*mode_q65)
if(nsmo.lt.1) nsmo=1
if(first) then !Generate the sync vector
sync=-22.0/63.0 !Sync tone OFF
@ -105,6 +107,8 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
allocate(s3(-64:LL-65,63))
allocate(ccf1(-ia2:ia2))
if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then
if(allocated(s1raw)) deallocate(s1raw)
allocate(s1raw(iz,jz))
if(allocated(s1)) deallocate(s1)
allocate(s1(iz,jz))
if(allocated(s1a)) deallocate(s1a)
@ -122,7 +126,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
lclearave=.false.
endif
ccf1=0.
if(iavg.eq.0) ccf2=0.
if(iavg.eq.0) ccf2_avg=0.
dtstep=nsps/(NSTEP*12000.0) !Step size in seconds
lag1=-1.0/dtstep
lag2=1.0/dtstep + 0.9999
@ -131,18 +135,29 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
if(nsps.ge.7200) j0=1.0/dtstep !Nominal start-signal index
s3=0.
! if(iavg.eq.0 .and. lnewdat) then
if(iavg.eq.0) then
call timer('q65_syms',0)
! Compute symbol spectra with NSTEP time bins per symbol
call q65_symspec(iwave,ntrperiod*12000,iz,jz,s1)
call timer('q65_syms',1)
! lnewdat=.false.
else
s1=s1a(:,:,iseq)
endif
i0=nint(nfqso/df) !Target QSO frequency
ii1=max(1,i0-64)
ii2=i0-65+LL
call pctile(s1(ii1:ii2,1:jz),ii2-ii1+1*jz,45,base)
s1=s1/base
s1raw=s1
! Apply fast AGC to the symbol spectra
s1max=20.0 !Empirical choice
do j=1,jz !### Maybe wrong way? ###
smax=maxval(s1(ii1:ii2,j))
if(smax.gt.s1max) s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax
enddo
dat4=0
if(ncw.gt.0 .and. iavg.le.1) then
! Try list decoding via "Deep Likelihood".
@ -163,7 +178,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
! Get 2d CCF and ccf2 using sync symbols only
if(iavg.eq.0) then
call timer('ccf_22a ',0)
call q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
call q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
f0a,xdta,ccf2)
call timer('ccf_22a ',1)
endif
@ -171,7 +186,7 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
! Get 2d CCF and ccf2_avg using sync symbols only
if(iavg.ge.1) then
call timer('ccf_22b ',0)
call q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
call q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
f0a,xdta,ccf2_avg)
call timer('ccf_22b ',1)
endif
@ -202,8 +217,10 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
if(i2.eq.-9999 .and. ccf1(-i).ge.0.5*smax) i2=-i
enddo
width=df*(i2-i1)
if(ncw.eq.0) ccf1=0.
call q65_write_red(iz,xdt,ccf2_avg,ccf2) !### Need this call for WSJT-X
call q65_write_red(iz,xdt,ccf2_avg,ccf2)
if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then
call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded)
@ -274,7 +291,7 @@ subroutine q65_symspec(iwave,nmax,iz,jz,s1)
allocate(c0(0:nsps-1))
nfft=nsps
fac=1/32767.0
do j=1,jz,2 !Compute symbol spectra at 2*step size
do j=1,jz !Compute symbol spectra at step size
i1=(j-1)*istep
i2=i1+nsps-1
k=-1
@ -294,8 +311,6 @@ subroutine q65_symspec(iwave,nmax,iz,jz,s1)
do i=1,nsmo
call smo121(s1(1:iz,j),iz)
enddo
! Interpolate to fill in the skipped-over spectra.
if(j.ge.3) s1(1:iz,j-1)=0.5*(s1(1:iz,j-2)+s1(1:iz,j))
enddo
if(lnewdat) then
navg(iseq)=navg(iseq) + 1
@ -466,7 +481,7 @@ subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best, &
return
end subroutine q65_ccf_85
subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
f0,xdt,ccf2)
! Attempt synchronization using only the 22 sync symbols. Return ccf2
@ -474,7 +489,6 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
real s1(iz,jz)
real ccf2(iz) !Orange sync curve
real tmp(20,3)
real, allocatable :: xdt2(:)
real, allocatable :: s1avg(:)
integer, allocatable :: indx(:)
@ -485,12 +499,11 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
ia=max(nfa,100)/df
ib=min(nfb,4900)/df
! if(nqd.ne.1 .or. iavg.ne.0) max_drift=0 !### Disabled March 22, 2023
if(nqd.ne.1 .or. iavg.ne.0) max_drift=0
if(max_drift.ne.0) then
ia=max(nint(100/df),nint((nfqso-ntol)/df))
ib=min(nint(4900/df),nint((nfqso+ntol)/df))
endif
if(ia.ge.ib) ia=ib-ntol/df !Protect against wacky settings
do i=ia,ib
s1avg(i)=sum(s1(i,1:jz))
@ -500,9 +513,7 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
ibest=0
lagpk=0
lagbest=0
idrift_max=0
idrift_best=0
do i=ia,ib
ccfmax=0.
do lag=lag1,lag2
@ -524,13 +535,10 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
endif
enddo ! idrift
enddo ! lag
ccf2(i)=ccfmax
xdt2(i)=lagpk*dtstep
if(ccfmax.gt.ccfbest .and. abs(i*df-nfqso).le.ftol) then
ccfbest=ccfmax
snrbest=snr
ibest=i
lagbest=lagpk
idrift_best=idrift_max
@ -548,39 +556,28 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
! Save parameters for best candidates
jzz=ib-ia+1
call pctile(ccf2(ia:ib),jzz,40,base)
ccf2=ccf2/base
call indexx(ccf2(ia:ib),jzz,indx)
call pctile(ccf2(ia:ib),jzz,50,ave)
call pctile(ccf2(ia:ib),jzz,84,base)
rms=base-ave
ncand=0
maxcand=20
do j=1,20
k=jzz-j+1
if(k.lt.1 .or. k.gt.iz) cycle
i=indx(k)+ia-1
if(ccf2(i).lt.3.3) exit !Candidate limit
f=i*df
i3=max(1, i-mode_q65)
i4=min(iz,i+mode_q65)
biggest=maxval(ccf2(i3:i4))
if(ccf2(i).ne.biggest) cycle
snr=(ccf2(i)-ave)/rms
if(snr.lt.6.0) exit
ncand=ncand+1
candidates(ncand,1)=snr
candidates(ncand,1)=ccf2(i)
candidates(ncand,2)=xdt2(i)
candidates(ncand,3)=f
if(ncand.ge.maxcand) exit
enddo
! Resort the candidates back into frequency order
tmp(1:ncand,1:3)=candidates(1:ncand,1:3)
candidates=0.
call indexx(tmp(1:ncand,3),ncand,indx)
do i=1,ncand
candidates(i,1:3)=tmp(indx(i),1:3)
enddo
return
end subroutine q65_ccf_22
@ -594,7 +591,7 @@ subroutine q65_dec1(s3,nsubmode,b90ts,esnodb,irc,dat4,decoded)
integer dat4(13)
character c77*77,decoded*37
logical unpk77_success
nFadingModel=1
decoded=' '
call q65_intrinsics_ff(s3,nsubmode,b90ts,nFadingModel,s3prob)
@ -608,7 +605,7 @@ subroutine q65_dec1(s3,nsubmode,b90ts,esnodb,irc,dat4,decoded)
irc=-1
endif
nrc=irc
return
end subroutine q65_dec1
@ -675,21 +672,16 @@ subroutine q65_write_red(iz,xdt,ccf2_avg,ccf2)
call q65_sync_curve(ccf2_avg,1,iz,rms1)
call q65_sync_curve(ccf2,1,iz,rms2)
i1=max(1,nint(nfa/df))
i2=min(iz,int(nfb/df))
y0=minval(ccf2(i1:i2))
y0_avg=minval(ccf2_avg(i1:i2))
g=0.4
g_avg=0.
if(navg(iseq).ge.2) g_avg=g
rewind 17
write(17,1000) xdt,g_avg*minval(ccf2_avg),g_avg*maxval(ccf2_avg)
do i=i1,i2
write(17,1000) xdt,minval(ccf2_avg),maxval(ccf2_avg)
do i=max(1,nint(nfa/df)),min(iz,int(nfb/df))
freq=i*df
y1=g_avg*(ccf2_avg(i)-y0_avg)
y2=g*(ccf2(i)-y0)
y1=ccf2_avg(i)
if(y1.gt.10.0) y1=10.0 + 2.0*log10(y1/10.0)
y2=ccf2(i)
if(y2.gt.10.0) y2=10.0 + 2.0*log10(y2/10.0)
write(17,1000) freq,y1,y2
1000 format(f10.3,2f15.6)
1000 format(3f10.3)
enddo
flush(17)
@ -741,7 +733,7 @@ subroutine q65_bzap(s3,LL)
return
end subroutine q65_bzap
subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
! Estimate SNR of a decoded transmission by aligning the spectra of
! all 85 symbols.
@ -772,7 +764,7 @@ subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
if(j.ge.1 .and. j.le.jz0) then
do i=1,iz0
ii=i+mode_q65*itone(k)
if(ii.ge.1 .and. ii.le.iz0) spec(i)=spec(i) + s1(ii,j)
if(ii.ge.1 .and. ii.le.iz0) spec(i)=spec(i) + s1raw(ii,j)
enddo
endif
enddo
@ -789,6 +781,8 @@ subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,snr2)
sig_area=sum(spec(ia+nsum:ib-nsum)-1.0)
w_equiv=sig_area/(smax-1.0)
snr2=db(max(1.0,sig_area)) - db(2500.0/df)
! NB: No adjustment to SNR is now made for nused>1, because that process did
! not seem to work as expected.
return
end subroutine q65_snr
@ -847,66 +841,4 @@ subroutine q65_hist(if0,msg0,dxcall,dxgrid)
900 return
end subroutine q65_hist
subroutine q65_hist2(nfreq,msg0,callers,nhist2)
use types
use prog_args
parameter (MAX_CALLERS=40) !For multiple q3 decodes in NA VHf Contest mode
character*37 msg0,msg
type(q3list) callers(MAX_CALLERS)
character*6 c6
character*4 g4
logical newcall,isgrid
isgrid(g4)=g4(1:1).ge.'A' .and. g4(1:1).le.'R' .and. g4(2:2).ge.'A' .and. &
g4(2:2).le.'R' .and. g4(3:3).ge.'0' .and. g4(3:3).le.'9' .and. &
g4(4:4).ge.'0' .and. g4(4:4).le.'9' .and. g4(1:4).ne.'RR73'
msg=msg0
if(index(msg,'/').gt.0) goto 900 !Ignore messages with compound calls
i0=index(msg,' R ')
if(i0.ge.7) msg=msg(1:i0)//msg(i0+3:)
i1=index(msg,' ')
c6=' '
g4=' '
if(i1.ge.4 .and. i1.le.13) then
i2=index(msg(i1+1:),' ') + i1
c6=msg(i1+1:i2-1) !Extract DX call
g4=msg(i2+1:i2+4) !Extract DX grid
endif
newcall=.true.
do i=1,nhist2
if(callers(i)%call .eq. c6) then
newcall=.false.
callers(i)%nsec=time()
callers(i)%nfreq=nfreq
exit
endif
enddo
if(newcall .and. isgrid(g4)) then
if(nhist2.eq.MAX_CALLERS) then
! Purge the oldest caller
callers(1:MAX_CALLERS-1)=callers(2:MAX_CALLERS)
nhist2=nhist2-1
endif
nhist2=nhist2+1
callers(nhist2)%call=c6
callers(nhist2)%grid=g4
callers(nhist2)%nsec=time()
callers(nhist2)%nfreq=nfreq
endif
if(nhist2.ge.1 .and. nhist2.le.40) then
open(24,file=trim(data_dir)//'/tsil.3q',status='unknown', &
form='unformatted')
write(24) nhist2
write(24) callers(1:nhist2)
close(24)
endif
900 return
end subroutine q65_hist2
end module q65

View File

@ -135,9 +135,10 @@ end
subroutine get_q65crc12(mc2,ncrc1,ncrc2)
!
character c6*6
character c12*12,c6*6
integer*1 mc(90),mc2(90),tmp(6)
integer*1 r(13),p(13)
integer ncrc
! polynomial for 12-bit CRC 0xF01
data p/1,1,0,0,0,0,0,0,0,1,1,1,1/
@ -169,6 +170,7 @@ subroutine get_q65_tones(msg37,codeword,itone)
implicit none
character*37 msg37
character*77 c77
character*12 c12
character*6 c6
integer codeword(65)
integer sync(22)

View File

@ -37,7 +37,7 @@ subroutine q65_loops(c00,npts2,nsps2,nsubmode,ndepth,jpk0, &
if(iand(ndepth,3).eq.3) then
idfmax=5
idtmax=5
maxdist=5
maxdist=15
endif
napmin=99

View File

@ -3,7 +3,7 @@ subroutine q65_set_list(mycall,hiscall,hisgrid,codewords,ncw)
parameter (MAX_NCW=206)
character*12 mycall,hiscall
character*6 hisgrid
character*37 msg,msgsent
character*37 msg0,msg,msgsent
logical my_std,his_std
integer codewords(63,MAX_NCW)
integer itone(85)
@ -45,7 +45,7 @@ subroutine q65_set_list(mycall,hiscall,hisgrid,codewords,ncw)
endif
endif
call genq65(msg,0,msgsent,itone,i3,n3)
10 call genq65(msg,0,msgsent,itone,i3,n3)
i0=1
j=0
do k=1,85

View File

@ -1,70 +0,0 @@
subroutine q65_set_list2(mycall,hiscall,hisgrid,callers,nhist2,codewords,ncw)
use types
parameter (MAX_NCW=206)
parameter (MAX_CALLERS=40) !For multiple q3 decodes in NA VHf Contest mode
character*12 mycall,hiscall
character*6 hisgrid,c6
character*4 g4
character*37 msg,msgsent
logical std,isgrid
integer codewords(63,MAX_NCW)
integer itone(85)
integer isync(22)
type(q3list) callers(MAX_CALLERS)
data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
isgrid(g4)=g4(1:1).ge.'A' .and. g4(1:1).le.'R' .and. g4(2:2).ge.'A' .and. &
g4(2:2).le.'R' .and. g4(3:3).ge.'0' .and. g4(3:3).le.'9' .and. &
g4(4:4).ge.'0' .and. g4(4:4).le.'9' .and. g4(1:4).ne.'RR73'
call stdcall(hiscall,std)
jmax=nhist2
if(std .and. isgrid(hisgrid(1:4))) then
jmax=min(MAX_CALLERS,nhist2+1)
do j=1,nhist2
if(callers(j)%call .eq. hiscall(1:6)) then
jmax=nhist2
exit
endif
enddo
endif
codewords(:,1)=0
i=1
do j=1,jmax
c6=callers(j)%call
g4=callers(j)%grid
if(j.eq.nhist2+1) then
c6=hiscall(1:6)
g4=hisgrid(1:4)
endif
do k=1,5
i=i+1
msg=trim(mycall)//' '//trim(c6)
j0=len(trim(msg))+1
if(k.eq.1) msg=msg(1:j0)//g4
if(k.eq.2) msg=msg(1:j0)//'R '//g4
if(k.eq.3) msg(j0:j0+3)=' RRR'
if(k.eq.4) msg(j0:j0+4)=' RR73'
if(k.eq.5) msg(j0:j0+2)=' 73'
call genq65(msg,0,msgsent,itone,i3,n3)
i0=1
jj=0
do kk=1,85
if(kk.eq.isync(i0)) then
i0=i0+1
cycle
endif
jj=jj+1
codewords(jj,i)=itone(kk) - 1
enddo
! write(71,3001) i,j,k,codewords(1:13,i),trim(msg)
!3001 format(3i3,2x,13i3,2x,a)
enddo
enddo
ncw=i
return
end subroutine q65_set_list2

View File

@ -8,7 +8,6 @@ program q65sim
type(hdr) h !Header for .wav file
integer*2 iwave(NMAX) !Generated waveform
integer itone(85) !Channel symbols (values 0-65)
integer ntone(85,10) !Channel symbols for up to 10 messages
integer y(63) !Codeword
integer istart !averaging compatible start seconds
integer imins !minutes for 15s period timestamp
@ -18,20 +17,19 @@ program q65sim
complex cdat(NMAX) !Generated complex waveform
complex cspread(0:NMAX-1) !Complex amplitude for Rayleigh fading
complex z
real*8 f00,f0,dt,twopi,phi,dphi,baud,fsample,freq
character fname*17,csubmode*1,arg*12,c2*2
character*37 msg,msgsent,imsg(10)
real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq
character msg*37,fname*17,csubmode*1,arg*12
character msgsent*37
nargs=iargc()
if(nargs.ne.11) then
print*,'Usage: q65sim "msg" A-E freq fDop DT f1 Stp TRp Nsig Nfile SNR'
print*,'Example: q65sim "K1ABC W9XYZ EN37" A 1500 0.0 0.0 0.0 1 60 1 1 -26'
if(nargs.ne.10) then
print*,'Usage: q65sim "msg" A-E freq fDop DT f1 Stp TRp Nfile SNR'
print*,'Example: q65sim "K1ABC W9XYZ EN37" A 1500 0.0 0.0 0.0 1 60 1 -26'
print*,'Example: q65sim "ST" A 1500 0.0 0.0 0.0 1 60 1 -26'
print*,' fDop = Doppler spread'
print*,' f1 = Drift or Doppler rate (Hz/min)'
print*,' Stp = Step size (Hz)'
print*,' Stp = 0 implies no Doppler tracking'
print*,' Nsig = number of generated signals, 1 - 10'
print*,' Creates filenames which increment to permit averaging in first period'
print*,' If msg = ST program produces a single tone at freq'
go to 999
@ -40,7 +38,7 @@ program q65sim
call getarg(2,csubmode)
mode65=2**(ichar(csubmode)-ichar('A'))
call getarg(3,arg)
read(arg,*) f00
read(arg,*) f0
call getarg(4,arg)
read(arg,*) fspread
call getarg(5,arg)
@ -52,10 +50,8 @@ program q65sim
call getarg(8,arg)
read(arg,*) ntrperiod
call getarg(9,arg)
read(arg,*) nsig
call getarg(10,arg)
read(arg,*) nfiles
call getarg(11,arg)
call getarg(10,arg)
read(arg,*) snrdb
if(ntrperiod.eq.15) then
@ -83,39 +79,22 @@ program q65sim
nsym=85 !Number of channel symbols
mode65=2**(ichar(csubmode) - ichar('A'))
imsg(1)=msg
if(nsig.ge.2) then
i0=index(msg,' ')
i0=i0 + index(msg(i0+1:),' ')-2
do i=1,nsig
c2=char(ichar('A')+i-1)//char(ichar('A')+i-1)
imsg(i)=msg(1:i0-1)//c2//msg(i0+2:)
enddo
endif
ichk=0
do i=1,nsig
msg=imsg(i)
call genq65(msg,ichk,msgsent,itone,i3,n3)
ntone(:,i)=itone
enddo
call genq65(msg,ichk,msgsent,itone,i3,n3)
if(nsig.eq.1) then
j=0
do i=1,85
if(itone(i).gt.0) then
j=j+1
y(j)=itone(i)-1
endif
enddo
write(*,1001) y(1:13),y(1:13)
j=0
do i=1,85
if(itone(i).gt.0) then
j=j+1
y(j)=itone(i)-1
endif
enddo
write(*,1001) y(1:13),y(1:13)
1001 format('Generated message'/'6-bit: ',13i3/'binary: ',13b6.6)
write(*,1002) y
write(*,1002) y
1002 format(/'Codeword:'/(20i3))
write(*,1003) itone
write(*,1003) itone
1003 format(/'Channel symbols:'/(20i3))
endif
baud=12000.d0/nsps !Keying rate (6.67 baud fot 15-s sequences)
h=default_header(12000,npts)
@ -137,54 +116,43 @@ program q65sim
open(10,file=trim(fname),access='stream',status='unknown')
xnoise=0.
cdat=0.
if(snrdb.lt.90) then
do i=1,npts
xnoise(i)=gran() !Generate gaussian noise
enddo
endif
cdat=0.
bandwidth_ratio=2500.0/6000.0
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snrdb)
if(snrdb.gt.90.0) sig=1.0
write(*,1020) ifile,ntrperiod,f00,csubmode,snrdb,fspread,xdt,f1,nstp,trim(msgsent)
1020 format(i4,i6,f7.1,2x,a1,2x,f5.1,1x,f6.2,2f6.1,i4,2x,a)
n=65.0*baud*mode65/100.0 + 0.9999
nfstep=100*n
nf1=1500 - nfstep*(nsig-1)/2
do n=1,nsig
f0=f00
if(nsig.ge.2) then
f0=nf1 + (n-1)*nfstep
itone=ntone(:,n)
write(*,1020) ifile,ntrperiod,f0,csubmode,snrdb,fspread,xdt,f1,nstp,trim(msgsent)
1020 format(i4,i6,f7.1,2x,a1,2x,f5.1,1x,f6.2,2f6.1,i4,2x,a)
phi=0.d0
dphi=0.d0
k=(xdt+0.5)*12000 !Start audio at t=xdt+0.5 s (TR=15 and 30 s)
if(ntrperiod.ge.60) k=(xdt+1.0)*12000 !TR 60+ at t = xdt + 1.0 s
isym0=-99
do i=1,npts !Add this signal into cdat()
isym=i/nsps + 1
if(isym.gt.nsym) exit
if(isym.ne.isym0) then
freq_drift=f1*i*dt/60.0
if(nstp.ne.0) freq_drift=freq_drift - nstp*nint(freq_drift/nstp)
if (msg(1:2).eq.'ST') then
freq = f0 + freq_drift
else
freq = f0 + freq_drift + itone(isym)*baud*mode65
endif
dphi=twopi*freq*dt
isym0=isym
endif
phi=0.d0
dphi=0.d0
k=(xdt+0.5)*12000 !Start audio at t=xdt+0.5 s (TR=15 and 30 s)
if(ntrperiod.ge.60) k=(xdt+1.0)*12000 !TR 60+ at t = xdt + 1.0 s
isym0=-99
do i=1,npts !Add this signal into cdat()
isym=i/nsps + 1
if(isym.gt.nsym) exit
if(isym.ne.isym0) then
freq_drift=f1*i*dt/60.0
if(nstp.ne.0) freq_drift=freq_drift - nstp*nint(freq_drift/nstp)
if (msg(1:2).eq.'ST') then
freq = f0 + freq_drift
else
freq = f0 + freq_drift + itone(isym)*baud*mode65
endif
dphi=twopi*freq*dt
isym0=isym
endif
phi=phi + dphi
if(phi.gt.twopi) phi=phi-twopi
xphi=phi
z=cmplx(cos(xphi),sin(xphi))
k=k+1
if(k.ge.1) cdat(k)=cdat(k) + sig*z
enddo
phi=phi + dphi
if(phi.gt.twopi) phi=phi-twopi
xphi=phi
z=cmplx(cos(xphi),sin(xphi))
k=k+1
if(k.ge.1) cdat(k)=cdat(k) + sig*z
enddo
if(fspread.ne.0) then !Apply specified Doppler spread

View File

@ -35,7 +35,7 @@ program sumsim
fac=1.0/nargs
iwave(1:npts)=nint(fac*wave(1:npts))
open(12,file='000001_0000.wav',access='stream',status='unknown')
open(12,file='000000_0000.wav',access='stream',status='unknown')
write(12) h,iwave(1:npts)
close(12)

View File

@ -50,7 +50,7 @@ subroutine sun(y,m,DD,UT,lon,lat,RA,Dec,LST,Az,El,mjd,day)
MM = mod(356.0470d0 + 0.9856002585d0 * d + 360000.d0,360.d0)
Ls = mod(w+MM+720.0,360.0)
EE = MM + e*rad*sin(MM/rad) * (1.0 + e*cos(MM/rad))
EE = MM + e*rad*sin(MM/rad) * (1.0 + e*cos(M/rad))
EE = EE - (EE - e*rad*sin(EE/rad)-MM) / (1.0 - e*cos(EE/rad))
xv = cos(EE/rad) - e

129
lib/test_qra64.f90 Normal file
View File

@ -0,0 +1,129 @@
program test_qra64
character*71 cmd1,cmd2,line
character*22 msg
character*8 arg
character*1 csubmode
integer nretcode(0:11)
logical decok
nargs=iargc()
if(nargs.ne.9) then
print*,'Usage: test_qra64 "msg" A-D depth freq DT fDop TRp nfiles SNR'
print*,'Example: test_qra64 "K1ABC W9XYZ EN37" A 3 1000 0.0 5.0 60 100 -20'
print*,' SNR = 0 to loop over all relevant SNRs'
go to 999
endif
call getarg(1,msg)
call getarg(2,csubmode)
call getarg(3,arg)
read(arg,*) ndepth
call getarg(4,arg)
read(arg,*) nf0
call getarg(5,arg)
read(arg,*) dt
call getarg(6,arg)
read(arg,*) fDop
call getarg(7,arg)
read(arg,*) ntrperiod
call getarg(8,arg)
read(arg,*) nfiles
call getarg(9,arg)
read(arg,*) nsnr
nsps=6192
i50=-28
ia=-20
ib=-33
if(nsnr.ne.0) then
ia=nsnr
ib=nsnr
endif
baud=12000.0/nsps
tsym=1.0/baud
! 1 2 3 4 5 6 7
! 12345678901234567890123456789012345678901234567890123456789012345678901'
cmd1='qra64sim "K1ABC W9XYZ EN37 " A 1 0.2 0.00 100 F -20 > junk0'
cmd2='jt9 -q -L 300 -H 3000 -f 1000 -d 3 -b A *.wav > junk'
write(cmd1(10:33),'(a)') '"'//msg//'"'
cmd1(35:35)=csubmode
write(cmd1(40:43),'(f4.1)') fDop
write(cmd1(44:48),'(f5.2)') dt
write(cmd1(49:53),'(i5)') nfiles
write(cmd2(26:29),'(i4)') nf0
write(cmd2(34:34),'(i1)') ndepth
cmd2(39:39)=csubmode
call system('rm -f *.wav')
write(*,1000) (j,j=0,11)
write(12,1000) (j,j=0,11)
1000 format(/'SNR d Dop Sync Dec Bad',i6,11i4,' tdec'/80('-'))
dterr=tsym/4.0
nferr=max(1,nint(0.5*baud),nint(fdop/3.0))
ndecodes0=nfiles
do nsnr=ia,ib,-1
nsync=0
ndecodes=0
nfalse=0
nretcode=0
write(cmd1(57:59),'(i3)') nsnr
call system(cmd1)
call sec0(0,tdec)
call system(cmd2)
call sec0(1,tdec)
open(10,file='junk',status='unknown')
n=0
do iline=1,9999
read(10,'(a71)',end=10) line
if(index(line,'<Decode').eq.1) cycle
read(line(11:20),*) xdt,nf
irc=-1
if(line(23:23).ne.' ') read(line(45:46),*) irc
decok=index(line,'W9XYZ').gt.0
if((abs(xdt-dt).le.dterr .and. abs(nf-nf0).le.nferr) .or. decok) then
nsync=nsync+1
endif
if(irc.lt.0) cycle
if(decok) then
i=irc
if(i.le.11) then
ndecodes=ndecodes + 1
else
i=mod(i,10)
endif
nretcode(i)=nretcode(i) + 1
else
nfalse=nfalse + 1
print*,'False: ',line
endif
enddo ! iline
10 close(10)
write(*,1100) nsnr,ndepth,fDop,nsync,ndecodes,nfalse,nretcode, &
tdec/nfiles
write(12,1100) nsnr,ndepth,fDop,nsync,ndecodes,nfalse,nretcode, &
tdec/nfiles
1100 format(i3,i2,f5.1,2i5,i4,i6,11i4,f6.2)
if(ndecodes.lt.nfiles/2 .and. ndecodes0.ge.nfiles/2) then
snr_thresh=nsnr + float(nfiles/2 - ndecodes)/(ndecodes0-ndecodes)
write(13,1200) ndepth,fdop,csubmode,snr_thresh
1200 format(i1,f6.1,2x,a1,f7.1)
flush(13)
endif
flush(6)
flush(12)
if(ndecodes.eq.0) exit !Bail out if no decodes at this SNR
ndecodes0=ndecodes
enddo ! nsnr
999 end program test_qra64
include 'sec0.f90'

View File

@ -7,12 +7,4 @@ module types
integer, parameter :: dp = REAL64
integer, parameter :: qp = REAL128
type q3list
character*6 call
character*4 grid
integer nsec
integer nfreq
integer moonel
end type q3list
end module types

View File

@ -146,7 +146,6 @@ unsigned long readwavfile(char *ptr_to_infile, int ntrmin, float *idat, float *q
nr=fread(buf2,2,npoints,fp); //Read raw data
fclose(fp);
if( nr == 0 ) {
free(buf2);
fprintf(stderr, "No data in file '%s'\n", ptr_to_infile);
return 1;
}
@ -1166,7 +1165,7 @@ int main(int argc, char *argv[])
for (k=0; k<162; k++) { //Sum over symbols
ifd=ifr+((float)k-81.0)/81.0*( (float)idrift )/(2.0*df);
kindex=k0+2*k;
if( kindex >= 0 && kindex < nffts ) {
if( kindex < nffts ) {
p0=ps[ifd-3][kindex];
p1=ps[ifd-1][kindex];
p2=ps[ifd+1][kindex];

View File

@ -16,11 +16,9 @@
#include <QTextStream>
#include <QDebug>
#include <QDebugStateSaver>
#include <QRegularExpression>
#include "Configuration.hpp"
#include "Radio.hpp"
#include "pimpl_impl.hpp"
#include "Logger.hpp"
#include "moc_AD1CCty.cpp"
@ -165,9 +163,6 @@ public:
{
}
QString get_cty_path(const Configuration *configuration);
void load_cty(QFile &file);
entity_by_id::iterator lookup_entity (QString call, prefix const& p) const
{
call = call.toUpper ();
@ -233,9 +228,6 @@ public:
Configuration const * configuration_;
QString path_;
QString cty_version_;
QString cty_version_date_;
entities_type entities_;
prefixes_type prefixes_;
};
@ -322,80 +314,6 @@ char const * AD1CCty::continent (Continent c)
}
}
QString AD1CCty::impl::get_cty_path(Configuration const * configuration)
{
QDir dataPath {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
auto path = dataPath.exists (file_name)
? dataPath.absoluteFilePath (file_name) // user override
: configuration->data_dir ().absoluteFilePath (file_name); // or original
return path;
}
void AD1CCty::impl::load_cty(QFile &file)
{
QRegularExpression version_pattern{R"(VER\d{8})"};
int entity_id = 0;
int line_number{0};
entities_.clear();
prefixes_.clear();
cty_version_ = QString{};
cty_version_date_ = QString{};
QTextStream in{&file};
while (!in.atEnd())
{
auto const &entity_line = in.readLine();
++line_number;
if (!in.atEnd())
{
auto const &entity_parts = entity_line.split(':');
if (entity_parts.size() >= 8)
{
auto primary_prefix = entity_parts[7].trimmed();
bool WAE_only{false};
if (primary_prefix.startsWith('*'))
{
primary_prefix = primary_prefix.mid(1);
WAE_only = true;
}
bool ok1, ok2, ok3, ok4, ok5;
entities_.emplace(++entity_id, entity_parts[0].trimmed(), WAE_only, entity_parts[1].trimmed().toInt(&ok1),
entity_parts[2].trimmed().toInt(&ok2), continent(entity_parts[3].trimmed()),
entity_parts[4].trimmed().toFloat(&ok3), entity_parts[5].trimmed().toFloat(&ok4),
static_cast<int> (entity_parts[6].trimmed().toFloat(&ok5) * 60 * 60), primary_prefix);
if (!(ok1 && ok2 && ok3 && ok4 && ok5))
{
throw std::domain_error{"Invalid number in cty.dat line " + boost::lexical_cast<std::string>(line_number)};
}
QString line;
QString detail;
do
{
in.readLineInto(&line);
++line_number;
} while (detail += line, !detail.endsWith(';'));
for (auto prefix: detail.left(detail.size() - 1).split(','))
{
prefix = prefix.trimmed();
bool exact{false};
if (prefix.startsWith('='))
{
prefix = prefix.mid(1);
exact = true;
// match version pattern to prefix
if (version_pattern.match(prefix).hasMatch())
{
cty_version_date_ = prefix;
}
}
prefixes_.emplace(prefix, exact, entity_id);
}
}
}
}
}
AD1CCty::AD1CCty (Configuration const * configuration)
: m_ {configuration}
{
@ -403,23 +321,69 @@ AD1CCty::AD1CCty (Configuration const * configuration)
// TODO: G4WJS - consider doing the following asynchronously to
// speed up startup. Not urgent as it takes less than 0.5s on a Core
// i7 reading BIG CTY.DAT.
AD1CCty::reload (configuration);
}
void AD1CCty::reload(Configuration const * configuration)
{
m_->path_ = m_->impl::get_cty_path(configuration);
QDir dataPath {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
m_->path_ = dataPath.exists (file_name)
? dataPath.absoluteFilePath (file_name) // user override
: configuration->data_dir ().absoluteFilePath (file_name); // or original
QFile file {m_->path_};
LOG_INFO(QString{"Loading CTY.DAT from %1"}.arg (m_->path_));
if (file.open (QFile::ReadOnly))
{
m_->impl::load_cty(file);
m_->cty_version_ = AD1CCty::lookup("VERSION").entity_name;
Q_EMIT cty_loaded(m_->cty_version_);
LOG_INFO(QString{"Loaded CTY.DAT version %1, %2"}.arg (m_->cty_version_date_).arg (m_->cty_version_));
}
{
int entity_id = 0;
int line_number {0};
QTextStream in {&file};
while (!in.atEnd ())
{
auto const& entity_line = in.readLine ();
++line_number;
if (!in.atEnd ())
{
auto const& entity_parts = entity_line.split (':');
if (entity_parts.size () >= 8)
{
auto primary_prefix = entity_parts[7].trimmed ();
bool WAE_only {false};
if (primary_prefix.startsWith ('*'))
{
primary_prefix = primary_prefix.mid (1);
WAE_only = true;
}
bool ok1, ok2, ok3, ok4, ok5;
m_->entities_.emplace (++entity_id
, entity_parts[0].trimmed ()
, WAE_only
, entity_parts[1].trimmed ().toInt (&ok1)
, entity_parts[2].trimmed ().toInt (&ok2)
, continent (entity_parts[3].trimmed ())
, entity_parts[4].trimmed ().toFloat (&ok3)
, entity_parts[5].trimmed ().toFloat (&ok4)
, static_cast<int> (entity_parts[6].trimmed ().toFloat (&ok5) * 60 * 60)
, primary_prefix);
if (!(ok1 && ok2 && ok3 && ok4 && ok5))
{
throw std::domain_error {"Invalid number in cty.dat line " + boost::lexical_cast<std::string> (line_number)};
}
QString line;
QString detail;
do
{
in.readLineInto (&line);
++line_number;
} while (detail += line, !detail.endsWith (';'));
for (auto prefix : detail.left (detail.size () - 1).split (','))
{
prefix = prefix.trimmed ();
bool exact {false};
if (prefix.startsWith ('='))
{
prefix = prefix.mid (1);
exact = true;
}
m_->prefixes_.emplace (prefix, exact, entity_id);
}
}
}
}
}
}
AD1CCty::~AD1CCty ()
@ -446,8 +410,8 @@ auto AD1CCty::lookup (QString const& call) const -> Record
if (p != m_->prefixes_.end ())
{
impl::entity_by_id::iterator e = m_->lookup_entity (call, *p);
// always lookup WAE entities, we substitute them later in displaytext.cpp if "Include extra WAE entites" is not selected
if (!p->exact_ || call.size () == search_prefix.size ())
if ((m_->configuration_->include_WAE_entities () || !e->WAE_only_)
&& (!p->exact_ || call.size () == search_prefix.size ()))
{
return m_->fixup (*p, *e);
}
@ -457,7 +421,3 @@ auto AD1CCty::lookup (QString const& call) const -> Record
}
return Record {};
}
auto AD1CCty::version () const -> QString
{
return m_->cty_version_date_;
}

View File

@ -42,11 +42,8 @@ public:
};
explicit AD1CCty (Configuration const *);
void reload(Configuration const * configuration);
~AD1CCty ();
Record lookup (QString const& call) const;
QString version () const;
Q_SIGNAL void cty_loaded (QString const& version) const;
private:
class impl;

View File

@ -23,7 +23,6 @@
#include <QDateTime>
#include "Configuration.hpp"
#include "revision_utils.hpp"
#include "Logger.hpp"
#include "qt_helpers.hpp"
#include "pimpl_impl.hpp"
@ -226,7 +225,7 @@ namespace
{
auto const logFileName = "wsjtx_log.adi";
// Exception class suitable for using with QtConcurrent across
// Expception class suitable for using with QtConcurrent across
// thread boundaries
class LoaderException final
: public QException
@ -375,7 +374,6 @@ public:
void reload ()
{
prefixes_.reload (configuration_);
async_loader_ = QtConcurrent::run (loader, path_, &prefixes_);
loader_watcher_.setFuture (async_loader_);
}
@ -404,18 +402,11 @@ WorkedBefore::WorkedBefore (Configuration const * configuration)
{
error = e.error ();
}
QString cty_ver = m_->prefixes_.version();
LOG_DEBUG(QString{"WorkedBefore::reload: CTY.DAT version %1"}.arg (cty_ver));
Q_EMIT finished_loading (n, cty_ver, error);
Q_EMIT finished_loading (n, error);
});
reload ();
}
QString WorkedBefore::cty_version () const
{
return m_->prefixes_.version ();
}
void WorkedBefore::reload ()
{
m_->reload ();
@ -677,7 +668,6 @@ bool WorkedBefore::CQ_zone_worked (int CQ_zone, QString const& mode, QString con
}
}
bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString const& band) const
{
if (mode.size ())
@ -709,5 +699,3 @@ bool WorkedBefore::ITU_zone_worked (int ITU_zone, QString const& mode, QString c
}
}
}

View File

@ -36,9 +36,8 @@ public:
bool continent_worked (Continent continent, QString const& mode, QString const& band) const;
bool CQ_zone_worked (int CQ_zone, QString const& mode, QString const& band) const;
bool ITU_zone_worked (int ITU_zone, QString const& mode, QString const& band) const;
QString cty_version () const;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const, QString const& error) const;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
private:
class impl;

View File

@ -69,11 +69,6 @@ void LogBook::rescan ()
worked_before_.reload ();
}
QString const LogBook::cty_version() const
{
return worked_before_.cty_version();
}
QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, QString const& mode,
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
QDateTime const& dateTimeOff, QString const& band, QString const& comments,
@ -101,7 +96,7 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
t += " <band:" + QString::number(band.size()) + ">" + band;
t += " <freq:" + QString::number(strDialFreq.size()) + ">" + strDialFreq;
t += " <station_callsign:" + QString::number(myCall.size()) + ">" + myCall;
if(myGrid!="") t += " <my_gridsquare:" + QString::number(myGrid.size()) + ">" + myGrid;
t += " <my_gridsquare:" + QString::number(myGrid.size()) + ">" + myGrid;
if(txPower!="") t += " <tx_pwr:" + QString::number(txPower.size()) + ">" + txPower;
if(comments!="") t += " <comment:" + QString::number(comments.size()) + ">" + comments;
if(name!="") t += " <name:" + QString::number(name.size()) + ">" + name;

View File

@ -46,9 +46,7 @@ public:
QString const& m_myGrid, QString const& m_txPower, QString const& operator_call,
QString const& xSent, QString const& xRcvd, QString const& propmode);
QString const cty_version() const;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const cty_version, QString const& error) const;
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
CabrilloLog * contest_log ();
Multiplier const * multiplier () const;

View File

@ -63,14 +63,13 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int isec=sec;
double uth=nhr + nmin/60.0 + sec/3600.0;
int nfreq=(int)datcom_.fcenter;
// if(nfreq<10 or nfreq > 50000) nfreq=144;
if(nfreq<10 or nfreq > 50000) nfreq=144;
astrosub_(&nyear, &month, &nday, &uth, &nfreq, mygrid.toLatin1(),
hisgrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
&azmoondx, &elmoondx, &ntsky, &ndop, &ndop00,&ramoon, &decmoon,
&dgrd, &poloffset, &xnr, 6, 6);
datcom_.nfast=ndop00; //Send self Doppler to decoder, via datcom
sprintf(cc,
"Az: %6.1f\n"
"El: %6.1f\n"

View File

@ -7,177 +7,242 @@
<x>0</x>
<y>0</y>
<width>441</width>
<height>503</height>
<height>483</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="astroTextBrowser">
<property name="font">
<font>
<family>Courier New</family>
<pointsize>20</pointsize>
<bold>true</bold>
</font>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="cbPointingTests">
<property name="text">
<string>Pointing Tests</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="gbPointing">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QRadioButton" name="rb6">
<widget class="QGroupBox" name="gbPointing">
<property name="geometry">
<rect>
<x>269</x>
<y>19</y>
<width>151</width>
<height>431</height>
</rect>
</property>
<property name="title">
<string/>
</property>
<widget class="QRadioButton" name="rb1">
<property name="geometry">
<rect>
<x>10</x>
<y>100</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
<widget class="QRadioButton" name="rb2">
<property name="geometry">
<rect>
<x>60</x>
<y>100</y>
<width>40</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>2, 5</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QRadioButton" name="rb3">
<property name="geometry">
<rect>
<x>110</x>
<y>100</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
<widget class="QRadioButton" name="rb4">
<property name="geometry">
<rect>
<x>60</x>
<y>150</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
<widget class="QRadioButton" name="rb6">
<property name="geometry">
<rect>
<x>60</x>
<y>50</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>6</string>
</property>
</widget>
<widget class="QDoubleSpinBox" name="sbOffset">
<property name="geometry">
<rect>
<x>10</x>
<y>230</y>
<width>130</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Offset </string>
</property>
<property name="suffix">
<string> deg</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>20.000000000000000</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>2.500000000000000</double>
</property>
</widget>
<widget class="QCheckBox" name="cbAutoCycle">
<property name="geometry">
<rect>
<x>30</x>
<y>330</y>
<width>91</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Auto Cycle</string>
</property>
</widget>
<widget class="QCheckBox" name="cbOnOff">
<property name="geometry">
<rect>
<x>30</x>
<y>380</y>
<width>70</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>On Off</string>
</property>
</widget>
<widget class="QSpinBox" name="sbDwell">
<property name="geometry">
<rect>
<x>10</x>
<y>280</y>
<width>130</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="prefix">
<string>Dwell </string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
</widget>
</widget>
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>258</width>
<height>471</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="astroTextBrowser">
<property name="font">
<font>
<family>Courier New</family>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="cbPointingTests">
<property name="text">
<string>6</string>
<string>Pointing Tests</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="rb1">
<property name="text">
<string>1</string>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="rb2">
<property name="text">
<string>2, 5</string>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QRadioButton" name="rb3">
<property name="text">
<string>3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="rb4">
<property name="text">
<string>4</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QDoubleSpinBox" name="sbOffset">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Offset </string>
</property>
<property name="suffix">
<string> deg</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>20.000000000000000</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>2.500000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QSpinBox" name="sbDwell">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="prefix">
<string>Dwell </string>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="cbAutoCycle">
<property name="text">
<string>Auto Cycle</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="cbOnOff">
<property name="text">
<string>On Off</string>
</property>
</widget>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>

File diff suppressed because it is too large Load Diff

View File

@ -12,15 +12,3 @@ subroutine astrosub(nyear,month,nday,uth8,nfreq,mygrid,hisgrid, &
return
end subroutine astrosub
subroutine astrosub00(nyear,month,nday,uth8,nfreq,mygrid,ndop00)
implicit real*8 (a-h,o-z)
character*6 mygrid
call astrosub(nyear,month,nday,uth8,nfreq,mygrid,mygrid, &
AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8,ntsky,ndop,ndop00, &
RAMoon8,DecMoon8,Dgrd8,poloffset8,xnr8)
return
end subroutine astrosub00

View File

@ -12,7 +12,7 @@ subroutine decode0(dd,ss,savg,nstandalone)
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
common/early/nhsym1,nhsym2,ldecoded(32768)
common/decodes/ndecodes
data neme0/-99/,mcall3b/1/
@ -56,7 +56,7 @@ subroutine decode0(dd,ss,savg,nstandalone)
mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, &
nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, &
neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample, &
ndiskdat,nxpol,nmode,ndop00)
ndiskdat,nxpol,nmode)
call timer('map65a ',1)
call timer('decode0 ',1)

View File

@ -10,7 +10,6 @@ subroutine ftninit(appd)
addpfx=' '
call pfxdump(appd//'/prefixes.txt')
open(12,file=appd//'/wb_q65.txt',status='unknown')
open(13,file=appd//'/map65.log',status='unknown')
open(19,file=appd//'/livecq.txt',status='unknown')
open(21,file=appd//'/map65_rx.log',status='unknown',access='append',err=950)

View File

@ -7,9 +7,9 @@ program m65
!
! 10 binary input data, *.tf2 files
! 11 prefixes.txt
! 12 wb_w65.txt
! 12
! 13 map65.log
! 14
! 14
! 15
! 16 tquick log
! 17 saved *.tf2 files
@ -41,7 +41,7 @@ program m65
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
common/early/nhsym1,nhsym2,ldecoded(32768)
nargs=iargc()

View File

@ -82,7 +82,7 @@ subroutine m65c(dd,ss,savg,nparams0)
common/npar/fcenter,nutc,idphi,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,neme,newdat,nfa,nfb,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid, &
nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2
common/early/nhsym1,nhsym2,ldecoded(32768)
equivalence (nparams,fcenter)

View File

@ -2,7 +2,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
mousedf,mousefqso,nagain,ndecdone,nfshift,ndphi,max_drift, &
nfcal,nkeep,mcall3b,nsum,nsave,nxant,mycall,mygrid, &
neme,ndepth,nstandalone,hiscall,hisgrid,nhsym,nfsample, &
ndiskdat,nxpol,nmode,ndop00)
ndiskdat,nxpol,nmode)
! Processes timf2 data from Linrad to find and decode JT65 signals.
@ -41,7 +41,6 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/
save
rewind 12
ndecodes=0
! Clean start for Q65 at early decode
@ -69,11 +68,11 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
endif
!###
! do k=1,ncand
! freq=cand(k)%f+nkhz_center-48.0
! freq=cand(k)%f+nkhz_center-48.0-1.27046
! ipk=cand(k)%indx
! write(71,3071) k,db(cand(k)%snr),freq,cand(k)%xdt, &
! write(*,3010) nutc,k,db(cand(k)%snr),freq,cand(k)%xdt, &
! cand(k)%ipol,cand(k)%iflip,ipk,ldecoded(ipk)
!3071 format(i3,f8.2,f10.3,f8.2,2i3,i6,L4)
!3010 format('=a',i5.4,i5,f8.2,f10.3,f8.2,2i3,i6,L4)
! enddo
!###
@ -366,7 +365,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid, hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,nhsym,ndop00,idec)
newdat,nagain,max_drift,nhsym,idec)
call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true.
enddo
@ -377,7 +376,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,nhsym,ndop00,idec)
newdat,nagain,max_drift,nhsym,idec)
call timer('q65b ',1)
endif
endif
@ -421,7 +420,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
call timer('q65b ',0)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
nagain,max_drift,nhsym,ndop00,idec)
nagain,max_drift,nhsym,idec)
call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true.
enddo ! icand
@ -521,7 +520,6 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
ndecdone=2
900 close(23)
call flush(12)
ndphi=0
mcall3b=mcall3a

View File

@ -1,6 +1,6 @@
subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
mycall0,mygrid,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain, &
max_drift,nhsym,ndop00,idec)
max_drift,nhsym,idec)
! This routine provides an interface between MAP65 and the Q65 decoder
! in WSJT-X. All arguments are input data obtained from the MAP65 GUI.
@ -137,11 +137,10 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
nfb=min(2500,1000+ntol)
endif
nsnr0=-99 !Default snr for no decode
ndpth=3
! NB: Frequency of ipk is now shifted to 1000 Hz.
call map65_mmdec(nutc,iwave,nqd,60,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,ndepth,mycall,hiscall0,hisgrid)
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,mycall,hiscall,hisgrid)
MHz=fcenter
freq0=MHz + 0.001d0*ikhz
@ -182,16 +181,11 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then
! Write to file map65_rx.log:
ndecodes=ndecodes+1
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28), &
cmode(2:2),cq0
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': ',a1,2x,a3)
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3)
nutc00=nutc
msg00=msg0(1:28)
freq1_00=freq1
frx=0.001*k0*df+nkhz_center-48.0+1.0 - 0.001*nfcal
fsked=frx - 0.001*ndop00/2.0 - 1.5
write(12,1120) nutc,fsked,xdt0,nsnr0,trim(msg0)
1120 format(i4.4,f9.3,f7.2,i5,2x,a,i6)
endif
endif

View File

@ -41,7 +41,7 @@ subroutine get_candidates(ss,savg,xpol,jz,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
type(candidate) :: cand(MAX_CANDIDATES)
common/early/nhsym1,nhsym2,ldecoded(32768)
call wb_sync(ss,savg,xpol,jz,nfa,nfb) !Output to sync() array
call wb_sync(ss,savg,xpol,jz,nfa,nfb)
tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65
df3=96000.0/NFFT
@ -89,6 +89,8 @@ subroutine get_candidates(ss,savg,xpol,jz,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
if(diffhz.gt.-0.03*bw .and. diffhz.lt.1.03*bw) skip=.true.
enddo
if(skip) cycle
! write(*,3301) i,k,m,f0,diffhz,bw,db(snr1)
!3301 format('=A',3i5,f8.3,2f8.0,f8.2)
k=k+1
cand(k)%snr=snr1
cand(k)%f=f0
@ -97,8 +99,6 @@ subroutine get_candidates(ss,savg,xpol,jz,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
cand(k)%ipol=sync(n)%ipol
cand(k)%iflip=nint(flip)
cand(k)%indx=n
! write(50,3050) i,k,m,f0+32.0,diffhz,bw,snr1,db(snr1)
!3050 format(3i5,f8.3,2f8.0,2f8.2)
if(k.ge.MAX_CANDIDATES) exit
enddo
ncand=k
@ -251,29 +251,14 @@ subroutine wb_sync(ss,savg,xpol,jz,nfa,nfb)
enddo ! i (frequency bin)
call pctile(sync(ia:ib)%ccfmax,ib-ia+1,50,base)
sync(ia:ib)%ccfmax=sync(ia:ib)%ccfmax/base
bw=65*4*1.66666667 !Q65-60C bandwidth
nbw=bw/df3 + 1 !Number of bins to blank
syncmin=2.0
nguard=10
do i=ia,ib
if(sync(i)%ccfmax.lt.syncmin) cycle
spk=maxval(sync(i:i+nbw)%ccfmax)
ip =maxloc(sync(i:i+nbw)%ccfmax)
i0=ip(1)+i-1
ja=min(i,i0-nguard)
jb=i0+nbw+nguard
sync(ja:jb)%ccfmax=0.
sync(i0)%ccfmax=spk
enddo
! do i=ia,ib
! write(15,3015) 0.001*(i-1)*df3+32.0,sync(i)%ccfmax,sync(i)%xdt, &
! sync(i)%ipol,sync(i)%iflip,sync(i)%birdie
! write(15,3015) 0.001*(i-1)*df3,sync(i)%ccfmax,sync(i)%xdt,sync(i)%ipol, &
! sync(i)%iflip,sync(i)%birdie
!3015 format(3f10.3,2i6,L5)
! enddo
call pctile(sync(ia:ib)%ccfmax,ib-ia+1,50,base)
sync(ia:ib)%ccfmax=sync(ia:ib)%ccfmax/base
return
end subroutine wb_sync

View File

@ -1293,25 +1293,7 @@ void MainWindow::decode() //decode()
datcom_.mousefqso=m_wide_graph_window->QSOfreq();
datcom_.ndepth=m_ndepth;
datcom_.ndiskdat=0;
if(m_diskData) {
datcom_.ndiskdat=1;
int i0=m_path.indexOf(".tf2");
if(i0<0) i0=m_path.indexOf(".iq");
if(i0>0) {
// Compute self Doppler using the filename for Date and Time
int nyear=m_path.mid(i0-11,2).toInt()+2000;
int month=m_path.mid(i0-9,2).toInt();
int nday=m_path.mid(i0-7,2).toInt();
int nhr=m_path.mid(i0-4,2).toInt();
int nmin=m_path.mid(i0-2,2).toInt();
double uth=nhr + nmin/60.0;
int nfreq=(int)datcom_.fcenter;
int ndop00;
astrosub00_(&nyear, &month, &nday, &uth, &nfreq, m_myGrid.toLatin1(),&ndop00,6);
datcom_.nfast=ndop00; //Send self Doppler to decoder, via datcom
}
}
if(m_diskData) datcom_.ndiskdat=1;
datcom_.neme=0;
if(ui->actionOnly_EME_calls->isChecked()) datcom_.neme=1;
@ -1340,7 +1322,7 @@ void MainWindow::decode() //decode()
datcom_.nxpol=0;
if(m_xpol) datcom_.nxpol=1;
datcom_.nmode=10*m_modeQ65 + m_modeJT65;
// datcom_.nfast=1; //No longer used
datcom_.nfast=1; //No longer used
datcom_.nsave=m_nsave;
datcom_.max_drift=ui->sbMaxDrift->value();

View File

@ -322,9 +322,6 @@ extern "C" {
int len1, int len2);
int ptt_(int* nport, int* itx, int* iptt);
void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
const char* mygrid, int* ndop00, int len1);
}
#endif // MAINWINDOW_H

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>902</width>
<height>560</height>
<width>635</width>
<height>523</height>
</rect>
</property>
<property name="sizePolicy">
@ -54,7 +54,7 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>620</width>
<height>16777215</height>
</size>
</property>
@ -65,7 +65,7 @@
<item>
<widget class="DisplayText" name="decodedTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -78,8 +78,8 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
<width>610</width>
<height>400</height>
</size>
</property>
<property name="font">
@ -229,27 +229,9 @@ p, li { white-space: pre-wrap; }
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5" stretch="0,0,1,0,0,1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QFrame" name="xMeterFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>65</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -260,18 +242,6 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<widget class="QFrame" name="yMeterFrame">
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
@ -292,13 +262,13 @@ p, li { white-space: pre-wrap; }
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
<width>164</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>290</width>
<height>16777215</height>
</size>
</property>
@ -306,252 +276,181 @@ p, li { white-space: pre-wrap; }
<string notr="true"/>
</property>
<property name="title">
<string/>
<string> DX Call DX Grid </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>6</number>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>231</x>
<y>13</y>
<width>50</width>
<height>23</height>
</rect>
</property>
<property name="topMargin">
<number>0</number>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="rightMargin">
<number>6</number>
<property name="text">
<string>SetMsgs</string>
</property>
<property name="bottomMargin">
<number>6</number>
</widget>
<widget class="QWidget" name="layoutWidget_2">
<property name="geometry">
<rect>
<x>7</x>
<y>13</y>
<width>150</width>
<height>64</height>
</rect>
</property>
<property name="spacing">
<number>6</number>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="dxCallEntry">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="dxGridEntry">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="lookupButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Lookup</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addButton">
<property name="minimumSize">
<size>
<width>70</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QPushButton" name="genStdMsgsPushButton">
<property name="geometry">
<rect>
<x>40</x>
<y>80</y>
<width>90</width>
<height>23</height>
</rect>
</property>
<item row="2" column="0" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="dxCallEntry">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="dxGridEntry">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>23</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QPushButton" name="lookupButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Lookup</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="addButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="genStdMsgsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;GenStdMsgs</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QLabel" name="DX_Grid_label">
<property name="styleSheet">
<string notr="true">border-width: 0;</string>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;DX Grid&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="DX_Call_label">
<property name="styleSheet">
<string notr="true">border-width: 0;</string>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="text">
<string>DX Call</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;GenStdMsgs</string>
</property>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="labUTC">
<property name="minimumSize">
<size>
@ -836,20 +735,20 @@ p, li { white-space: pre-wrap; }
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9" stretch="1,0,0">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLineEdit" name="tx1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -866,14 +765,14 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QLineEdit" name="tx2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -882,14 +781,14 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QLineEdit" name="tx3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -898,14 +797,14 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QLineEdit" name="tx4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -914,14 +813,14 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QLineEdit" name="tx5">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -930,14 +829,14 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QLineEdit" name="tx6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>160</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<width>180</width>
<height>24</height>
</size>
</property>
@ -950,7 +849,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -963,7 +862,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -981,7 +880,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -994,7 +893,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -1009,7 +908,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb3">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1022,7 +921,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -1037,7 +936,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb4">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1050,7 +949,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -1065,7 +964,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb5">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1078,7 +977,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -1093,7 +992,7 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QRadioButton" name="txrb6">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>16</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -1106,7 +1005,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>30</width>
<width>20</width>
<height>16777215</height>
</size>
</property>
@ -1138,7 +1037,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1157,7 +1056,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1176,7 +1075,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1195,7 +1094,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1214,7 +1113,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1233,7 +1132,7 @@ p, li { white-space: pre-wrap; }
</property>
<property name="maximumSize">
<size>
<width>35</width>
<width>29</width>
<height>20</height>
</size>
</property>
@ -1257,8 +1156,8 @@ p, li { white-space: pre-wrap; }
<rect>
<x>0</x>
<y>0</y>
<width>902</width>
<height>23</height>
<width>635</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -1392,7 +1291,7 @@ p, li { white-space: pre-wrap; }
</action>
<action name="actionAbout">
<property name="text">
<string>About MAP65</string>
<string> About MAP65</string>
</property>
<property name="shortcut">
<string>Ctrl+F1</string>

View File

@ -776,7 +776,7 @@ void CPlotter::mouseMoveEvent (QMouseEvent * event)
if(lower) {
QToolTip::showText(event->globalPos(),QString::number(ndf));
} else {
QToolTip::showText(event->globalPos(),QString::number(freq,'f',3));
QToolTip::showText(event->globalPos(),QString::number(freq));
}
QWidget::mouseMoveEvent(event);
}

View File

@ -11,7 +11,6 @@
#include <QSqlQuery>
#include <QTextStream>
#include <QDebug>
#include "Logger.hpp"
#include "Configuration.hpp"
#include "qt_db_helpers.hpp"
#include "pimpl_impl.hpp"
@ -38,10 +37,6 @@ public:
Configuration const * configuration_;
QSqlQuery mutable dupe_query_;
QSqlQuery mutable export_query_;
// queries for rates
QSqlQuery mutable rate_n_query_;
QSqlQuery mutable rate60m_query_;
QString rate();
};
#include "FoxLog.moc"
@ -123,25 +118,6 @@ FoxLog::impl::impl (Configuration const * configuration)
" ORDER BY "
" \"when\"");
SQL_error_check (rate_n_query_, &QSqlQuery::prepare,
"SELECT "
" \"when\""
" FROM "
" fox_log "
" ORDER BY "
" \"when\" DESC"
" LIMIT :limitn"
);
SQL_error_check (rate60m_query_, &QSqlQuery::prepare,
"SELECT "
" COUNT() "
" FROM "
" fox_log "
" where \"when\" > :one_hour_ago"
" ORDER BY "
" \"when\" DESC"
);
setEditStrategy (QSqlTableModel::OnFieldChange);
setTable ("fox_log");
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
@ -159,13 +135,6 @@ FoxLog::impl::impl (Configuration const * configuration)
SQL_error_check (*this, &QSqlTableModel::select);
}
QString FoxLog::rate()
{
return QString("Last 10: %1, Last 100: %2, Last 60m: %3").arg(QString::number(this->rate_last_n(10),'f',0),
QString::number(this->rate_last_n(100),'f',0),
QString::number(this->rate_60m()));
}
FoxLog::FoxLog (Configuration const * configuration)
: m_ {configuration}
{
@ -252,47 +221,6 @@ void FoxLog::reset ()
}
}
int FoxLog::rate_60m()
{
int rate60m = 0;
qlonglong const& one_hour_ago = QDateTime::currentDateTime().addSecs(-3600).toMSecsSinceEpoch () / 1000;
// query the 60m rate
m_->rate60m_query_.bindValue (":one_hour_ago", one_hour_ago);
SQL_error_check (m_->rate60m_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
m_->rate60m_query_.next ();
rate60m = m_->rate60m_query_.value (0).toLongLong();
return rate60m;
//
}
double FoxLog::rate_last_n(int n)
{
double rate_interval = 0;
qlonglong const& secs_now = QDateTime::currentDateTime().toMSecsSinceEpoch () / 1000;
// get last n or up to n
m_->rate_n_query_.bindValue (":limitn", n);
SQL_error_check (m_->rate_n_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
m_->rate_n_query_.next();
if (!m_->rate_n_query_.isValid()) {
LOG_ERROR(QString("rate_n result is not valid. Last error %1").arg(m_->rate_n_query_.lastError().text()));
return 0.0;
}
// size / (time_now - time_of_first)
m_->rate_n_query_.last();
rate_interval = secs_now - m_->rate_n_query_.value (0).toLongLong ();
if (rate_interval == 0) return 0.0;
m_->rate_n_query_.first(); // count the records
int size = 1;
while (m_->rate_n_query_.next() && m_->rate_n_query_.isValid()) size++;
return (size/rate_interval) * 3600;
}
namespace
{
struct ADIF_field

View File

@ -26,9 +26,6 @@ public:
QSqlTableModel * model ();
void reset ();
void export_qsos (QTextStream&) const;
QString rate();
double rate_last_n(int n); // get the rate for the last n
int rate_60m();
private:
class impl;

View File

@ -659,7 +659,7 @@ QModelIndex FrequencyList_v2_101::impl::add (Item f)
endInsertRows ();
// if we added one that had a preferred frequency, unprefer everything else
if (f.preferred_) unprefer_all_but(f, row, {Qt::DisplayRole, Qt::CheckStateRole});
unprefer_all_but(f, row, {Qt::DisplayRole, Qt::CheckStateRole});
return index (row, 0);
}
@ -1335,10 +1335,8 @@ FrequencyList_v2_101::FrequencyItems FrequencyList_v2_101::from_json_file(QFile
{
throw ReadFileException{tr ("No Frequencies were found")};
}
#ifdef DUMP_ENTRY_COUNTS
int valid_entry_count = 0;
int skipped_entry_count = 0;
#endif
for (auto const &item: arr)
{
QString mode_s, region_s;
@ -1361,21 +1359,13 @@ FrequencyList_v2_101::FrequencyItems FrequencyList_v2_101::from_json_file(QFile
freq.isSane())
{
list.push_back(freq);
#ifdef DUMP_ENTRY_COUNTS
valid_entry_count++;
#endif
} else {
#ifdef DUMP_ENTRY_COUNTS
} else
skipped_entry_count++;
#endif
}
}
#ifdef DUMP_ENTRY_COUNTS
MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
QString::number(skipped_entry_count)));
#endif
//MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
// tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
// QString::number(skipped_entry_count)));
return list;
}
// write JSON format to a file

1
qmap/.gitignore vendored
View File

@ -1 +0,0 @@
~*

View File

@ -1,65 +0,0 @@
set (qmap_CXXSRCS
about.cpp
astro.cpp
devsetup.cpp
displaytext.cpp
getfile.cpp
main.cpp
mainwindow.cpp
meterwidget.cpp
plotter.cpp
signalmeter.cpp
soundin.cpp
widegraph.cpp
)
if (WIN32)
set (qmap_CXXSRCS ${qmap_CXXSRCS})
endif (WIN32)
set (qmap_UISRCS
about.ui
astro.ui
devsetup.ui
mainwindow.ui
widegraph.ui
)
set (qmap_C_and_CXXSRCS
${qmap_CSRCS}
${qmap_CXXSRCS}
)
set_property (SOURCE ${qmap_C_and_CXXSRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -include wsjtx_config.h")
set_property (SOURCE ${qmap_C_and_CXXSRCS} APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/wsjtx_config.h)
# build the subdirectories
add_subdirectory (libqmap)
# UI generation
qt5_wrap_ui (qmap_GENUISRCS ${qmap_UISRCS})
add_executable (qmap ${qmap_CXXSRCS} ${qmap_CSRCS} ${qmap_GENUISRCS} qmap.rc)
target_include_directories (qmap PRIVATE ${CMAKE_SOURCE_DIR} ${FFTW3_INCLUDE_DIRS})
target_link_libraries (qmap wsjt_qt qmap_impl ${FFTW3_LIBRARIES} Qt5::Widgets Qt5::Network Usb::Usb)
if (WSJT_CREATE_WINMAIN)
set_target_properties (qmap PROPERTIES WIN32_EXECUTABLE ON)
endif (WSJT_CREATE_WINMAIN)
if (WIN32)
install (
CODE "get_filename_component (_path \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/wsjtx_dir.txt\" REALPATH)
if (WIN32)
set (_separator \"\\\\\")
else ()
set (_separator \"/\")
endif ()
file (WRITE \"\${_path}\" \".\${_separator}\\n\")"
)
install (
TARGETS qmap
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION . COMPONENT runtime
)
endif ()

View File

@ -1,30 +0,0 @@
+ + + This Software is released under the "Simplified BSD License" + + +
Copyright 2010 Moe Wheatley. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY Moe Wheatley ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL Moe Wheatley OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation
are those of the authors and should not be interpreted as representing
official policies, either expressed or implied, of Moe Wheatley.

Binary file not shown.

View File

@ -1,23 +0,0 @@
#include "about.h"
#include "revision_utils.hpp"
#include "ui_about.h"
CAboutDlg::CAboutDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::CAboutDlg)
{
ui->setupUi(this);
ui->labelTxt->setText("<html><h2>" + QString {"QMAP v"
+ QCoreApplication::applicationVersion ()
+ " " + revision ()}.simplified () + "</h2><br />"
"QMAP is a wideband receiver for the Q65 protocol, intnded<br />"
"primarily for amateur radio EME communication. It works <br />"
"in close cooperation with WSJT-X, versions 2.7 and later. <br /><br />"
"Copyright 2001-2024 by Joe Taylor, K1JT. Additional <br />"
"acknowledgments are contained in the source code.");
}
CAboutDlg::~CAboutDlg()
{
delete ui;
}

View File

@ -1,23 +0,0 @@
#ifndef ABOUTDLG_H
#define ABOUTDLG_H
#include <QDialog>
namespace Ui {
class CAboutDlg;
}
class CAboutDlg : public QDialog
{
Q_OBJECT
public:
explicit CAboutDlg(QWidget *parent = nullptr);
~CAboutDlg();
private:
Ui::CAboutDlg *ui;
QString m_Str;
};
#endif // ABOUTDLG_H

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CAboutDlg</class>
<widget class="QDialog" name="CAboutDlg">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>374</width>
<height>164</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>About QMAP</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelTxt">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,257 +0,0 @@
0 0.0000 0.0000 0.0000
1 0.0000 0.0000 0.0000
2 0.0078 0.0000 0.0000
3 0.0157 0.0000 0.0000
4 0.0235 0.0000 0.0000
5 0.0314 0.0000 0.0000
6 0.0392 0.0000 0.0000
7 0.0471 0.0000 0.0000
8 0.0549 0.0000 0.0000
9 0.0627 0.0000 0.0000
10 0.0706 0.0000 0.0000
11 0.0784 0.0000 0.0000
12 0.0863 0.0000 0.0000
13 0.0941 0.0000 0.0000
14 0.1020 0.0000 0.0000
15 0.1098 0.0000 0.0000
16 0.1176 0.0000 0.0000
17 0.1255 0.0000 0.0000
18 0.1333 0.0000 0.0000
19 0.1412 0.0000 0.0000
20 0.1490 0.0000 0.0000
21 0.1569 0.0000 0.0000
22 0.1647 0.0000 0.0000
23 0.1725 0.0000 0.0000
24 0.1804 0.0000 0.0000
25 0.1882 0.0000 0.0000
26 0.1961 0.0000 0.0000
27 0.2039 0.0000 0.0000
28 0.2118 0.0000 0.0000
29 0.2196 0.0000 0.0000
30 0.2275 0.0000 0.0000
31 0.2353 0.0000 0.0000
32 0.2431 0.0000 0.0000
33 0.2510 0.0000 0.0000
34 0.2588 0.0000 0.0000
35 0.2667 0.0000 0.0000
36 0.2745 0.0000 0.0000
37 0.2824 0.0000 0.0000
38 0.2902 0.0000 0.0000
39 0.2980 0.0000 0.0000
40 0.3059 0.0000 0.0000
41 0.3137 0.0000 0.0000
42 0.3216 0.0000 0.0000
43 0.3294 0.0000 0.0000
44 0.3373 0.0000 0.0000
45 0.3451 0.0000 0.0000
46 0.3529 0.0000 0.0000
47 0.3608 0.0000 0.0000
48 0.3686 0.0000 0.0000
49 0.3765 0.0000 0.0000
50 0.3843 0.0000 0.0000
51 0.3922 0.0000 0.0000
52 0.4000 0.0000 0.0000
53 0.4078 0.0000 0.0000
54 0.4157 0.0000 0.0000
55 0.4235 0.0000 0.0000
56 0.4314 0.0000 0.0000
57 0.4392 0.0000 0.0000
58 0.4471 0.0000 0.0000
59 0.4549 0.0000 0.0000
60 0.4627 0.0000 0.0000
61 0.4706 0.0000 0.0000
62 0.4784 0.0000 0.0000
63 0.4863 0.0000 0.0000
64 0.4941 0.0000 0.0000
65 0.5020 0.0000 0.0000
66 0.5098 0.0098 0.0000
67 0.5176 0.0176 0.0000
68 0.5255 0.0255 0.0000
69 0.5333 0.0333 0.0000
70 0.5412 0.0412 0.0000
71 0.5490 0.0490 0.0000
72 0.5569 0.0569 0.0000
73 0.5647 0.0647 0.0000
74 0.5725 0.0725 0.0000
75 0.5804 0.0804 0.0000
76 0.5882 0.0882 0.0000
77 0.5961 0.0961 0.0000
78 0.6039 0.1039 0.0000
79 0.6118 0.1118 0.0000
80 0.6196 0.1196 0.0000
81 0.6275 0.1275 0.0000
82 0.6353 0.1353 0.0000
83 0.6431 0.1431 0.0000
84 0.6510 0.1510 0.0000
85 0.6588 0.1588 0.0000
86 0.6667 0.1667 0.0000
87 0.6745 0.1745 0.0000
88 0.6824 0.1824 0.0000
89 0.6902 0.1902 0.0000
90 0.6980 0.1980 0.0000
91 0.7059 0.2059 0.0000
92 0.7137 0.2137 0.0000
93 0.7216 0.2216 0.0000
94 0.7294 0.2294 0.0000
95 0.7373 0.2373 0.0000
96 0.7451 0.2451 0.0000
97 0.7529 0.2529 0.0000
98 0.7608 0.2608 0.0000
99 0.7686 0.2686 0.0000
100 0.7765 0.2765 0.0000
101 0.7843 0.2843 0.0000
102 0.7922 0.2922 0.0000
103 0.8000 0.3000 0.0000
104 0.8078 0.3078 0.0000
105 0.8157 0.3157 0.0000
106 0.8235 0.3235 0.0000
107 0.8314 0.3314 0.0000
108 0.8392 0.3392 0.0000
109 0.8471 0.3471 0.0000
110 0.8549 0.3549 0.0000
111 0.8627 0.3627 0.0000
112 0.8706 0.3706 0.0000
113 0.8784 0.3784 0.0000
114 0.8863 0.3863 0.0000
115 0.8941 0.3941 0.0000
116 0.9020 0.4020 0.0000
117 0.9098 0.4098 0.0000
118 0.9176 0.4176 0.0000
119 0.9255 0.4255 0.0000
120 0.9333 0.4333 0.0000
121 0.9412 0.4412 0.0000
122 0.9490 0.4490 0.0000
123 0.9569 0.4569 0.0000
124 0.9647 0.4647 0.0000
125 0.9725 0.4725 0.0000
126 0.9804 0.4804 0.0000
127 0.9882 0.4882 0.0000
128 0.9961 0.4961 0.0000
129 1.0000 0.5039 0.0000
130 1.0000 0.5118 0.0118
131 1.0000 0.5196 0.0196
132 1.0000 0.5275 0.0275
133 1.0000 0.5353 0.0353
134 1.0000 0.5431 0.0431
135 1.0000 0.5510 0.0510
136 1.0000 0.5588 0.0588
137 1.0000 0.5667 0.0667
138 1.0000 0.5745 0.0745
139 1.0000 0.5824 0.0824
140 1.0000 0.5902 0.0902
141 1.0000 0.5980 0.0980
142 1.0000 0.6059 0.1059
143 1.0000 0.6137 0.1137
144 1.0000 0.6216 0.1216
145 1.0000 0.6294 0.1294
146 1.0000 0.6373 0.1373
147 1.0000 0.6451 0.1451
148 1.0000 0.6529 0.1529
149 1.0000 0.6608 0.1608
150 1.0000 0.6686 0.1686
151 1.0000 0.6765 0.1765
152 1.0000 0.6843 0.1843
153 1.0000 0.6922 0.1922
154 1.0000 0.7000 0.2000
155 1.0000 0.7078 0.2078
156 1.0000 0.7157 0.2157
157 1.0000 0.7235 0.2235
158 1.0000 0.7314 0.2314
159 1.0000 0.7392 0.2392
160 1.0000 0.7471 0.2471
161 1.0000 0.7549 0.2549
162 1.0000 0.7627 0.2627
163 1.0000 0.7706 0.2706
164 1.0000 0.7784 0.2784
165 1.0000 0.7863 0.2863
166 1.0000 0.7941 0.2941
167 1.0000 0.8020 0.3020
168 1.0000 0.8098 0.3098
169 1.0000 0.8176 0.3176
170 1.0000 0.8255 0.3255
171 1.0000 0.8333 0.3333
172 1.0000 0.8412 0.3412
173 1.0000 0.8490 0.3490
174 1.0000 0.8569 0.3569
175 1.0000 0.8647 0.3647
176 1.0000 0.8725 0.3725
177 1.0000 0.8804 0.3804
178 1.0000 0.8882 0.3882
179 1.0000 0.8961 0.3961
180 1.0000 0.9039 0.4039
181 1.0000 0.9118 0.4118
182 1.0000 0.9196 0.4196
183 1.0000 0.9275 0.4275
184 1.0000 0.9353 0.4353
185 1.0000 0.9431 0.4431
186 1.0000 0.9510 0.4510
187 1.0000 0.9588 0.4588
188 1.0000 0.9667 0.4667
189 1.0000 0.9745 0.4745
190 1.0000 0.9824 0.4824
191 1.0000 0.9902 0.4902
192 1.0000 0.9980 0.4980
193 1.0000 1.0000 0.5059
194 1.0000 1.0000 0.5137
195 1.0000 1.0000 0.5216
196 1.0000 1.0000 0.5294
197 1.0000 1.0000 0.5373
198 1.0000 1.0000 0.5451
199 1.0000 1.0000 0.5529
200 1.0000 1.0000 0.5608
201 1.0000 1.0000 0.5686
202 1.0000 1.0000 0.5765
203 1.0000 1.0000 0.5843
204 1.0000 1.0000 0.5922
205 1.0000 1.0000 0.6000
206 1.0000 1.0000 0.6078
207 1.0000 1.0000 0.6157
208 1.0000 1.0000 0.6235
209 1.0000 1.0000 0.6314
210 1.0000 1.0000 0.6392
211 1.0000 1.0000 0.6471
212 1.0000 1.0000 0.6549
213 1.0000 1.0000 0.6627
214 1.0000 1.0000 0.6706
215 1.0000 1.0000 0.6784
216 1.0000 1.0000 0.6863
217 1.0000 1.0000 0.6941
218 1.0000 1.0000 0.7020
219 1.0000 1.0000 0.7098
220 1.0000 1.0000 0.7176
221 1.0000 1.0000 0.7255
222 1.0000 1.0000 0.7333
223 1.0000 1.0000 0.7412
224 1.0000 1.0000 0.7490
225 1.0000 1.0000 0.7569
226 1.0000 1.0000 0.7647
227 1.0000 1.0000 0.7725
228 1.0000 1.0000 0.7804
229 1.0000 1.0000 0.7882
230 1.0000 1.0000 0.7961
231 1.0000 1.0000 0.8039
232 1.0000 1.0000 0.8118
233 1.0000 1.0000 0.8196
234 1.0000 1.0000 0.8275
235 1.0000 1.0000 0.8353
236 1.0000 1.0000 0.8431
237 1.0000 1.0000 0.8510
238 1.0000 1.0000 0.8588
239 1.0000 1.0000 0.8667
240 1.0000 1.0000 0.8745
241 1.0000 1.0000 0.8824
242 1.0000 1.0000 0.8902
243 1.0000 1.0000 0.8980
244 1.0000 1.0000 0.9059
245 1.0000 1.0000 0.9137
246 1.0000 1.0000 0.9216
247 1.0000 1.0000 0.9294
248 1.0000 1.0000 0.9373
249 1.0000 1.0000 0.9451
250 1.0000 1.0000 0.9529
251 1.0000 1.0000 0.9608
252 1.0000 1.0000 0.9686
253 1.0000 1.0000 0.9765
254 1.0 0.0 0.0
255 1.0 1.0 0.0
256 0.0 1.000 0.0

View File

@ -1,195 +0,0 @@
#include "astro.h"
#include <QSettings>
#include "ui_astro.h"
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <stdio.h>
#include "SettingsGroup.hpp"
#include "commons.h"
#include <math.h>
extern "C" {
void astrosub_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
const char* mygrid, const char* hisgrid, double* azsun,
double* elsun, double* azmoon, double* elmoon, double* azmoondx,
double* elmoondx, int* ntsky, int* ndop, int* ndop00,
double* ramoon, double* decmoon, double* dgrd, double* poloffset,
double* xnr, int len1, int len2);
}
Astro::Astro (QString const& settings_filename, QWidget *parent) :
QWidget(parent),
ui(new Ui::Astro),
m_settings_filename {settings_filename}
{
ui->setupUi (this);
setWindowTitle ("Astronomical Data");
setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint);
QSettings settings {m_settings_filename, QSettings::IniFormat};
SettingsGroup g {&settings, "MainWindow"}; // MainWindow group for
// historical reasons
setGeometry (settings.value ("AstroGeom", QRect {71, 390, 227, 403}).toRect ());
ui->astroTextBrowser->setStyleSheet(
"QTextBrowser { background-color : cyan; color : black; }");
ui->astroTextBrowser->clear();
m_AzElDir0="";
}
Astro::~Astro()
{
QSettings settings {m_settings_filename, QSettings::IniFormat};
SettingsGroup g {&settings, "MainWindow"};
settings.setValue ("AstroGeom", geometry ());
delete ui;
}
void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg)
{
char cc[300];
double azsun,elsun,azmoon,elmoon,azmoondx,elmoondx;
double ramoon,decmoon,dgrd,poloffset,xnr;
int ntsky,ndop,ndop00;
QString date = t.date().toString("yyyy MMM dd");
QString utc = t.time().toString();
int nyear=t.date().year();
int month=t.date().month();
int nday=t.date().day();
int nhr=t.time().hour();
int nmin=t.time().minute();
double sec=t.time().second() + 0.001*t.time().msec();
int isec=sec;
double uth=nhr + nmin/60.0 + sec/3600.0;
int nfreq=(int)datcom_.fcenter;
astrosub_(&nyear, &month, &nday, &uth, &nfreq, mygrid.toLatin1(),
mygrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
&azmoondx, &elmoondx, &ntsky, &ndop, &ndop00,&ramoon, &decmoon,
&dgrd, &poloffset, &xnr, 6, 6);
datcom_.ndop00=ndop00; //Send self Doppler to decoder, via datcom
m_ndop00=ndop00;
snprintf(cc, sizeof(cc),
"Az: %6.1f\n"
"El: %6.1f\n"
"SelfDop:%6d\n"
"MoonDec:%6.1f\n"
"SunAz: %6.1f\n"
"SunEl: %6.1f\n"
"Freq: %6d\n"
"Tsky: %6d\n"
"MNR: %6.1f\n"
"Dgrd: %6.1f",
azmoon,elmoon,ndop00,decmoon,azsun,elsun,
nfreq,ntsky,xnr,dgrd);
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
double azOffset=0.0;
double elOffset=0.0;
double rad=57.2957795131;
int iCycle=2;
// Are we doing pointing tests?
bool bPointing=ui->cbPointingTests->isChecked();
ui->gbPointing->setVisible(bPointing);
if(bPointing) {
int nDwell=int(ui->sbDwell->value());
if(ui->cbAutoCycle->isChecked()) {
iCycle=(t.currentSecsSinceEpoch()%(6*nDwell))/nDwell + 1;
if(iCycle==1) {
azOffset = -ui->sbOffset->value()/cos(elsun/rad);
ui->rb1->setChecked(true);
}
if(iCycle==2 or iCycle==5) {
ui->rb2->setChecked(true);
}
if(iCycle==3) {
azOffset = +ui->sbOffset->value()/cos(elsun/rad);
ui->rb3->setChecked(true);
}
if(iCycle==4) {
elOffset = -ui->sbOffset->value();
ui->rb4->setChecked(true);
}
if(iCycle==6) {
elOffset = +ui->sbOffset->value();
ui->rb6->setChecked(true);
}
} else if(ui->cbOnOff->isChecked()) {
iCycle=(t.currentSecsSinceEpoch()%(2*nDwell))/nDwell + 1;
if(iCycle==1) {
azOffset = -ui->sbOffset->value()/cos(elsun/rad);
ui->rb1->setChecked(true);
}
if(iCycle==2) {
ui->rb2->setChecked(true);
}
} else {
if(ui->rb1->isChecked()) azOffset = -ui->sbOffset->value()/cos(elsun/rad);
if(ui->rb3->isChecked()) azOffset = ui->sbOffset->value()/cos(elsun/rad);
if(ui->rb4->isChecked()) elOffset = -ui->sbOffset->value();
if(ui->rb6->isChecked()) elOffset = ui->sbOffset->value();
}
if(ui->cbAutoCycle->isChecked() or ui->cbOnOff->isChecked()) {
QFile f("pointing.out");
if(f.open(QIODevice::WriteOnly | QIODevice::Append)) {
QTextStream out(&f);
out << t.toString("yyyy-MMM-dd hh:mm:ss");
snprintf(cc,sizeof(cc),"%7.1f %7.1f %d %7.1f %7.1f %10.1f %7.2f\n",
azsun,elsun,iCycle,azOffset,elOffset,xavg,10.0*log10(xavg));
out << cc;
f.close();
}
}
} else {
ui->rb2->setChecked(true);
ui->cbAutoCycle->setChecked(false);
ui->cbOnOff->setChecked(false);
}
// Write pointing data to azel.dat
QString fname=azelDir+"/azel.dat";
QFile f(fname);
if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
if(azelDir==m_AzElDir0) return;
m_AzElDir0=azelDir;
QMessageBox mb;
mb.setText("Cannot open " + fname + "\nCorrect the setting of AzEl Directory in Setup?");
mb.exec();
return;
}
QTextStream out(&f);
snprintf(cc,sizeof(cc),"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Moon\n"
"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Sun\n"
"%2.2d:%2.2d:%2.2d,%5.1f,%5.1f,Source\n"
"%4d,%6d,%6d,Doppler\n"
"%3d,%1d,fQSO\n",
nhr,nmin,isec,azmoon,elmoon,
nhr,nmin,isec,azsun+azOffset,elsun+elOffset,
nhr,nmin,isec,0.0,0.0,
nfreq,ndop,ndop00,
datcom_.mousefqso,0);
out << cc;
f.close();
}
void Astro::setFontSize(int n)
{
ui->astroTextBrowser->setFontPointSize(n);
}
void Astro::on_cbAutoCycle_clicked(bool checked)
{
if(checked) ui->cbOnOff->setChecked(false);
}
void Astro::on_cbOnOff_clicked(bool checked)
{
if(checked) ui->cbAutoCycle->setChecked(false);
}
int Astro::getSelfDop()
{
return m_ndop00;
}

View File

@ -1,35 +0,0 @@
#ifndef ASTRO_H
#define ASTRO_H
#include <QWidget>
#include <QDateTime>
namespace Ui {
class Astro;
}
class Astro : public QWidget
{
Q_OBJECT
public:
explicit Astro (QString const& settings_filename, QWidget *parent = 0);
void astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg);
void setFontSize(int n);
int getSelfDop();
~Astro ();
private slots:
void on_cbOnOff_clicked(bool checked);
void on_cbAutoCycle_clicked(bool checked);
private:
Ui::Astro *ui;
QString m_settings_filename;
QString m_AzElDir0;
qint32 m_ndop00=0;
};
#endif

View File

@ -1,283 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Astro</class>
<widget class="QWidget" name="Astro">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>393</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QGroupBox" name="gbPointing">
<property name="geometry">
<rect>
<x>269</x>
<y>19</y>
<width>151</width>
<height>361</height>
</rect>
</property>
<property name="title">
<string/>
</property>
<widget class="QRadioButton" name="rb1">
<property name="geometry">
<rect>
<x>10</x>
<y>70</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
<widget class="QRadioButton" name="rb2">
<property name="geometry">
<rect>
<x>60</x>
<y>70</y>
<width>40</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>2, 5</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QRadioButton" name="rb3">
<property name="geometry">
<rect>
<x>110</x>
<y>70</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>3</string>
</property>
</widget>
<widget class="QRadioButton" name="rb4">
<property name="geometry">
<rect>
<x>60</x>
<y>120</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>4</string>
</property>
</widget>
<widget class="QRadioButton" name="rb6">
<property name="geometry">
<rect>
<x>60</x>
<y>20</y>
<width>30</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>6</string>
</property>
</widget>
<widget class="QDoubleSpinBox" name="sbOffset">
<property name="geometry">
<rect>
<x>10</x>
<y>180</y>
<width>130</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Offset </string>
</property>
<property name="suffix">
<string> deg</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>0.500000000000000</double>
</property>
<property name="maximum">
<double>20.000000000000000</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>2.500000000000000</double>
</property>
</widget>
<widget class="QCheckBox" name="cbAutoCycle">
<property name="geometry">
<rect>
<x>30</x>
<y>260</y>
<width>91</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Auto Cycle</string>
</property>
</widget>
<widget class="QCheckBox" name="cbOnOff">
<property name="geometry">
<rect>
<x>30</x>
<y>300</y>
<width>70</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>On Off</string>
</property>
</widget>
<widget class="QSpinBox" name="sbDwell">
<property name="geometry">
<rect>
<x>10</x>
<y>220</y>
<width>130</width>
<height>22</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="prefix">
<string>Dwell </string>
</property>
<property name="minimum">
<number>15</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>258</width>
<height>371</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="astroTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>325</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Courier New</family>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="cbPointingTests">
<property name="text">
<string>Pointing Tests</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,256 +0,0 @@
0 0.0000 0.0000 0.0000
1 0.0902 0.0902 0.2558
2 0.1176 0.1176 0.2694
3 0.1412 0.1412 0.2820
4 0.1569 0.1569 0.2938
5 0.1725 0.1725 0.3049
6 0.1843 0.1843 0.3154
7 0.1961 0.1961 0.3254
8 0.2039 0.2039 0.3349
9 0.2157 0.2157 0.3440
10 0.2235 0.2235 0.3528
11 0.2314 0.2314 0.3612
12 0.2392 0.2392 0.3693
13 0.2471 0.2471 0.3772
14 0.2549 0.2549 0.3848
15 0.2588 0.2588 0.3921
16 0.2667 0.2667 0.3992
17 0.2706 0.2706 0.4061
18 0.2784 0.2784 0.4129
19 0.2824 0.2824 0.4194
20 0.2902 0.2902 0.4258
21 0.2941 0.2941 0.4319
22 0.2980 0.2980 0.4380
23 0.3059 0.3059 0.4439
24 0.3098 0.3098 0.4496
25 0.3137 0.3137 0.4553
26 0.3176 0.3176 0.4608
27 0.3216 0.3216 0.4661
28 0.3294 0.3294 0.4714
29 0.3333 0.3333 0.4765
30 0.3373 0.3373 0.4815
31 0.3412 0.3412 0.4865
32 0.3451 0.3451 0.4913
33 0.3490 0.3490 0.4960
34 0.3529 0.3529 0.5006
35 0.3569 0.3569 0.5052
36 0.3608 0.3608 0.5096
37 0.3647 0.3647 0.5140
38 0.3686 0.3686 0.5183
39 0.3725 0.3725 0.5225
40 0.3765 0.3765 0.5266
41 0.3804 0.3804 0.5306
42 0.3843 0.3843 0.5346
43 0.3843 0.3843 0.5385
44 0.3882 0.3882 0.5423
45 0.3922 0.3922 0.5460
46 0.3961 0.3961 0.5497
47 0.4000 0.4000 0.5533
48 0.4039 0.4039 0.5569
49 0.4078 0.4078 0.5603
50 0.4118 0.4118 0.5638
51 0.4118 0.4118 0.5671
52 0.4157 0.4157 0.5704
53 0.4196 0.4196 0.5736
54 0.4235 0.4235 0.5768
55 0.4275 0.4275 0.5799
56 0.4314 0.4314 0.5829
57 0.4314 0.4314 0.5859
58 0.4353 0.4353 0.5889
59 0.4392 0.4392 0.5917
60 0.4431 0.4431 0.5946
61 0.4471 0.4471 0.5973
62 0.4471 0.4471 0.6001
63 0.4510 0.4510 0.6027
64 0.4549 0.4549 0.6053
65 0.4588 0.4588 0.6079
66 0.4627 0.4627 0.6104
67 0.4627 0.4627 0.6129
68 0.4667 0.4667 0.6153
69 0.4706 0.4706 0.6176
70 0.4745 0.4745 0.6199
71 0.4745 0.4745 0.6222
72 0.4784 0.4784 0.6244
73 0.4824 0.4824 0.6266
74 0.4863 0.4863 0.6287
75 0.4863 0.4863 0.6308
76 0.4902 0.4902 0.6328
77 0.4941 0.4941 0.6348
78 0.4980 0.4980 0.6367
79 0.5020 0.5020 0.6386
80 0.5020 0.5020 0.6404
81 0.5059 0.5059 0.6422
82 0.5098 0.5098 0.6440
83 0.5098 0.5098 0.6457
84 0.5137 0.5137 0.6474
85 0.5176 0.5176 0.6490
86 0.5216 0.5216 0.6506
87 0.5216 0.5216 0.6521
88 0.5255 0.5255 0.6536
89 0.5294 0.5294 0.6551
90 0.5333 0.5333 0.6565
91 0.5333 0.5333 0.6578
92 0.5373 0.5373 0.6591
93 0.5412 0.5412 0.6604
94 0.5451 0.5451 0.6617
95 0.5451 0.5451 0.6629
96 0.5490 0.5490 0.6640
97 0.5529 0.5529 0.6651
98 0.5569 0.5569 0.6662
99 0.5569 0.5569 0.6672
100 0.5608 0.5608 0.6682
101 0.5647 0.5647 0.6692
102 0.5647 0.5647 0.6701
103 0.5686 0.5686 0.6710
104 0.5725 0.5725 0.6718
105 0.5765 0.5765 0.6726
106 0.5765 0.5765 0.6733
107 0.5804 0.5804 0.6740
108 0.5843 0.5843 0.6747
109 0.5843 0.5843 0.6753
110 0.5882 0.5882 0.6759
111 0.5922 0.5922 0.6765
112 0.5961 0.5961 0.6770
113 0.5961 0.5961 0.6774
114 0.6000 0.6000 0.6779
115 0.6039 0.6039 0.6783
116 0.6039 0.6039 0.6786
117 0.6078 0.6078 0.6789
118 0.6118 0.6118 0.6792
119 0.6157 0.6157 0.6794
120 0.6157 0.6157 0.6796
121 0.6196 0.6196 0.6798
122 0.6235 0.6235 0.6799
123 0.6235 0.6235 0.6800
124 0.6275 0.6275 0.6800
125 0.6314 0.6314 0.6800
126 0.6353 0.6353 0.6799
127 0.6353 0.6353 0.6799
128 0.6392 0.6392 0.6797
129 0.6431 0.6431 0.6796
130 0.6431 0.6431 0.6794
131 0.6471 0.6471 0.6791
132 0.6510 0.6510 0.6789
133 0.6549 0.6549 0.6785
134 0.6549 0.6549 0.6782
135 0.6588 0.6588 0.6778
136 0.6627 0.6627 0.6773
137 0.6627 0.6627 0.6769
138 0.6667 0.6667 0.6763
139 0.6706 0.6706 0.6758
140 0.6745 0.6745 0.6752
141 0.6745 0.6745 0.6746
142 0.6784 0.6784 0.6739
143 0.6824 0.6824 0.6732
144 0.6824 0.6824 0.6724
145 0.6863 0.6863 0.6716
146 0.6902 0.6902 0.6708
147 0.6941 0.6941 0.6699
148 0.6941 0.6941 0.6690
149 0.6980 0.6980 0.6680
150 0.7020 0.7020 0.6670
151 0.7020 0.7020 0.6660
152 0.7059 0.7059 0.6649
153 0.7098 0.7098 0.6638
154 0.7098 0.7098 0.6626
155 0.7137 0.7137 0.6614
156 0.7176 0.7176 0.6601
157 0.7216 0.7216 0.6589
158 0.7216 0.7216 0.6575
159 0.7255 0.7255 0.6561
160 0.7294 0.7294 0.6547
161 0.7294 0.7294 0.6533
162 0.7333 0.7333 0.6518
163 0.7373 0.7373 0.6502
164 0.7412 0.7412 0.6486
165 0.7412 0.7412 0.6470
166 0.7451 0.7451 0.6453
167 0.7490 0.7490 0.6436
168 0.7490 0.7490 0.6418
169 0.7529 0.7529 0.6400
170 0.7569 0.7569 0.6382
171 0.7608 0.7608 0.6363
172 0.7608 0.7608 0.6343
173 0.7647 0.7647 0.6324
174 0.7686 0.7686 0.6303
175 0.7686 0.7686 0.6282
176 0.7725 0.7725 0.6261
177 0.7765 0.7765 0.6239
178 0.7804 0.7804 0.6217
179 0.7804 0.7804 0.6194
180 0.7843 0.7843 0.6171
181 0.7882 0.7882 0.6147
182 0.7882 0.7882 0.6123
183 0.7922 0.7922 0.6098
184 0.7961 0.7961 0.6073
185 0.8000 0.8000 0.6047
186 0.8000 0.8000 0.6021
187 0.8039 0.8039 0.5994
188 0.8078 0.8078 0.5967
189 0.8078 0.8078 0.5939
190 0.8118 0.8118 0.5911
191 0.8157 0.8157 0.5882
192 0.8196 0.8196 0.5853
193 0.8196 0.8196 0.5823
194 0.8235 0.8235 0.5792
195 0.8275 0.8275 0.5761
196 0.8275 0.8275 0.5729
197 0.8314 0.8314 0.5697
198 0.8353 0.8353 0.5664
199 0.8392 0.8392 0.5630
200 0.8392 0.8392 0.5596
201 0.8431 0.8431 0.5561
202 0.8471 0.8471 0.5525
203 0.8471 0.8471 0.5489
204 0.8510 0.8510 0.5452
205 0.8549 0.8549 0.5414
206 0.8588 0.8588 0.5376
207 0.8588 0.8588 0.5337
208 0.8627 0.8627 0.5297
209 0.8667 0.8667 0.5257
210 0.8667 0.8667 0.5215
211 0.8706 0.8706 0.5173
212 0.8745 0.8745 0.5130
213 0.8784 0.8784 0.5086
214 0.8784 0.8784 0.5042
215 0.8824 0.8824 0.4996
216 0.8863 0.8863 0.4950
217 0.8863 0.8863 0.4902
218 0.8902 0.8902 0.4854
219 0.8941 0.8941 0.4804
220 0.8980 0.8980 0.4754
221 0.8980 0.8980 0.4702
222 0.9020 0.9020 0.4649
223 0.9059 0.9059 0.4595
224 0.9098 0.9098 0.4540
225 0.9098 0.9098 0.4484
226 0.9137 0.9137 0.4426
227 0.9176 0.9176 0.4366
228 0.9176 0.9176 0.4306
229 0.9216 0.9216 0.4243
230 0.9255 0.9255 0.4179
231 0.9294 0.9294 0.4114
232 0.9294 0.9294 0.4046
233 0.9333 0.9333 0.3977
234 0.9373 0.9373 0.3905
235 0.9373 0.9373 0.3831
236 0.9412 0.9412 0.3754
237 0.9451 0.9451 0.3675
238 0.9490 0.9490 0.3594
239 0.9490 0.9490 0.3509
240 0.9529 0.9529 0.3420
241 0.9569 0.9569 0.3328
242 0.9608 0.9608 0.3232
243 0.9608 0.9608 0.3131
244 0.9647 0.9647 0.3024
245 0.9686 0.9686 0.2912
246 0.9686 0.9686 0.2792
247 0.9725 0.9725 0.2664
248 0.9765 0.9765 0.2526
249 0.9804 0.9804 0.2375
250 0.9804 0.9804 0.2208
251 0.9843 0.9843 0.2020
252 0.9882 0.9882 0.1800
253 1.0 0.0 0.0
254 1.0 1.0 0.0
255 0.0 1.000 0.0

View File

@ -1,107 +0,0 @@
#ifndef COMMONS_H
#define COMMONS_H
#define NFFT 32768
extern "C" {
extern struct { //This is "common/datcom/..." in Fortran
float d4[2*5760000]; //Raw I/Q data from Linrad
float ss[400*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
float fselected; //Selected frequency for nagain decodes
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.iq file
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int n60; //nsecs%60
int junk4; //
int nfsample; //Input sample rate
int ndop58; //EME Self Doppler at t=58
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler at t=0
int nsave; //0=None, 1=SaveDecoded, 2=SaveAll
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom_;
extern struct { //This is "common/datcom/..." in Fortran
float d4[2*5760000]; //Raw I/Q data from Linrad
float ss[400*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol
float savg[NFFT]; //Avg spectra at 0,45,90,135 deg pol
double fcenter; //Center freq from Linrad (MHz)
int nutc; //UTC as integer, HHMM
float fselected; //Selected frequency for nagain decodes
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.iq file
int ntx60; //Number of seconds transmitted in Q65-60x
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int ntx30a; //Number of seconds transmitted in first half minute , Q65-30x
int ntx30b; //Number of seconds transmitted in second half minute, Q65-30x
int ntol; //+/- decoding range around fQSO (Hz)
int n60; //nsecs%60
int junk4; //
int nfsample; //Input sample rate
int ndop58; //EME Self Doppler at t=58
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler at t=0
int nsave; //0=None, 1=SaveDecoded, 2=SaveAll
int max_drift; //Maximum Q65 drift: units symbol_rate/TxT
int offset; //Offset in Hz
int nhsym; //Number of available JT65 half-symbols
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
int junk1; //Used to test extent of copy to shared memory
int junk2;
bool bAlso30; //Process for 30-second submode as well as 60-second
} datcom2_;
extern struct {
int ndecodes; //These are flags for inter-process communication
int ncand; //between QMAP and WSJT-X
int nQDecoderDone; //1 for real-time decodes, 2 for data from disk
int nWDecoderBusy; //Set to 1 when WSJT-X decoder is busy
int nWTransmitting; //Set to TRperiod when WSJT-X is transmitting
int kHzRequested; //Integer kHz dial frequency request to WSJT-X
char result[50][64]; //Staging area for QMAP decodes
} decodes_;
extern struct {
char revision[22];
char saveFileName[120];
} savecom_;
}
#endif // COMMONS_H

View File

@ -1,51 +0,0 @@
#include "devsetup.h"
#include "mainwindow.h"
#include <QTextStream>
#include <QDebug>
#include <cstdio>
//----------------------------------------------------------- DevSetup()
DevSetup::DevSetup(QWidget *parent) : QDialog(parent)
{
ui.setupUi(this); //setup the dialog form
m_restartSoundIn=false;
}
DevSetup::~DevSetup()
{
}
void DevSetup::initDlg()
{
ui.myCallEntry->setText(m_myCall);
ui.myGridEntry->setText(m_myGrid);
ui.astroFont->setValue(m_astroFont);
ui.myCallColor->addItems({"","red","green","cyan"});
ui.myCallColor->setCurrentIndex(m_myCallColor);
ui.saveDirEntry->setText(m_saveDir);
ui.azelDirEntry->setText(m_azelDir);
ui.fCalSpinBox->setValue(m_fCal);
ui.faddEntry->setText(QString::number(m_fAdd,'f',3));
ui.sbPort->setValue(m_udpPort);
ui.sb_dB->setValue(m_dB);
}
//------------------------------------------------------- accept()
void DevSetup::accept()
{
// Called when OK button is clicked.
// Check to see whether SoundInThread must be restarted,
// and save user parameters.
m_myCall=ui.myCallEntry->text();
m_myGrid=ui.myGridEntry->text();
m_astroFont=ui.astroFont->value();
m_myCallColor=ui.myCallColor->currentIndex();
m_saveDir=ui.saveDirEntry->text();
m_azelDir=ui.azelDirEntry->text();
m_fCal=ui.fCalSpinBox->value();
m_fAdd=ui.faddEntry->text().toDouble();
m_udpPort=ui.sbPort->value();
m_dB=ui.sb_dB->value();
QDialog::accept();
}

View File

@ -1,41 +0,0 @@
#ifndef DEVSETUP_H
#define DEVSETUP_H
#include <QDialog>
#include "ui_devsetup.h"
class DevSetup : public QDialog
{
Q_OBJECT
public:
DevSetup(QWidget *parent=0);
~DevSetup();
void initDlg();
qint32 m_fCal;
qint32 m_udpPort;
qint32 m_astroFont;
qint32 m_dB;
double m_fAdd;
double m_TxOffset;
bool m_network;
bool m_restartSoundIn;
int m_myCallColor;
QString m_myCall;
QString m_myGrid;
QString m_saveDir;
QString m_azelDir;
public slots:
void accept();
private:
int r,g,b,r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3;
Ui::DialogSndCard ui;
};
#endif // DEVSETUP_H

View File

@ -1,448 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogSndCard</class>
<widget class="QDialog" name="DialogSndCard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTabWidget" name="ioTabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Station</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>My Call:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>My Grid:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Astro Font Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Highlight My Call:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLineEdit" name="myCallEntry">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>K1JT</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="myGridEntry">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>FN20qi</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="astroFont">
<property name="minimum">
<number>12</number>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="myCallColor"/>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_9">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Fcal (Hz):</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Fadd (MHz)</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QSpinBox" name="fCalSpinBox">
<property name="minimum">
<number>-50000</number>
</property>
<property name="maximum">
<number>50000</number>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="faddEntry">
<property name="text">
<string>0.0</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_10">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Save Directory:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="saveDirEntry">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_6">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>AzEl Directory:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="azelDirEntry">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>I/O Devices</string>
</attribute>
<widget class="QWidget" name="layoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>255</width>
<height>64</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Input from Linrad or SDR Console</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QSpinBox" name="sb_dB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Adjust to scale digital I/Q data.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> dB</string>
</property>
<property name="prefix">
<string>Gain </string>
</property>
<property name="minimum">
<number>-50</number>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="sbPort">
<property name="minimumSize">
<size>
<width>57</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>20000</number>
</property>
<property name="maximum">
<number>51000</number>
</property>
<property name="value">
<number>50004</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Port">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>26</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogSndCard</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>380</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogSndCard</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>380</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,15 +0,0 @@
#include "displaytext.h"
#include <QDebug>
#include <QMouseEvent>
DisplayText::DisplayText(QWidget *parent) :
QTextBrowser(parent)
{
}
void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
{
bool ctrl = (e->modifiers() & 0x4000000);
emit(selectCallsign(ctrl));
QTextBrowser::mouseDoubleClickEvent(e);
}

View File

@ -1,22 +0,0 @@
#ifndef DISPLAYTEXT_H
#define DISPLAYTEXT_H
#include <QTextBrowser>
class DisplayText : public QTextBrowser
{
Q_OBJECT
public:
explicit DisplayText(QWidget *parent = 0);
signals:
void selectCallsign(bool ctrl);
public slots:
protected:
void mouseDoubleClickEvent(QMouseEvent *e);
};
#endif // DISPLAYTEXT_H

Some files were not shown because too many files have changed in this diff Show More