Compare commits

..

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

82 changed files with 3392 additions and 5139 deletions

View File

@ -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 (RC 2)
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
#
@ -362,7 +363,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 +492,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
@ -1144,9 +1143,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)
@ -1603,7 +1599,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 hash22calc
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)

View File

@ -173,6 +173,7 @@
#include <QJsonDocument>
#include <QJsonArray>
#include "pimpl_impl.hpp"
#include "Logger.hpp"
#include "qt_helpers.hpp"
@ -244,9 +245,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 +277,7 @@ namespace
constexpr quint32 qrg_version_100 {100};
}
//
// Dialog to get a new Frequency item
//
@ -331,9 +330,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 +385,7 @@ private:
QDateTimeEdit *start_date_time_edit_;
};
//
// Dialog to get a new Station item
//
@ -458,6 +458,9 @@ public:
}
};
// Internal implementation of the Configuration class.
class Configuration::impl final
: public QDialog
@ -577,11 +580,6 @@ private:
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);
@ -686,7 +684,6 @@ private:
QString FD_exchange_;
QString RTTY_exchange_;
QString Contest_Name_;
QString hamlib_backed_up_;
qint32 id_interval_;
qint32 ntrials_;
@ -761,6 +758,7 @@ private:
#include "Configuration.moc"
// delegate to implementation class
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, LogBook * logbook, QWidget * parent)
@ -1572,7 +1570,6 @@ void Configuration::impl::read_settings ()
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 +1746,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 ()
@ -2499,113 +2484,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

@ -225,7 +225,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

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>684</width>
<height>662</height>
</rect>
</property>
<property name="windowTitle">
@ -529,280 +529,6 @@ quiet period when decoding is done.</string>
<string>Radio interface configuration settings.</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="5" column="2">
<widget class="QGroupBox" name="mode_group_box">
<property name="toolTip">
<string>Modulation mode selected on radio.</string>
</property>
<property name="title">
<string>Mode</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="1">
<widget class="QRadioButton" name="mode_USB_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;USB is usually the correct modulation mode,&lt;/p&gt;&lt;p&gt;unless the radio has a special data or packet mode setting&lt;/p&gt;&lt;p&gt;for AFSK operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>US&amp;B</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mode_none_radio_button">
<property name="toolTip">
<string>Don't allow the program to set the radio mode
(not recommended but use if the wrong mode
or bandwidth is selected).</string>
</property>
<property name="text">
<string>None</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="2">
<widget class="QRadioButton" name="mode_data_radio_button">
<property name="toolTip">
<string>If this is available then it is usually the correct mode for this program.</string>
</property>
<property name="text">
<string>Data/P&amp;kt</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="2">
<widget class="QGroupBox" name="TX_audio_source_group_box">
<property name="toolTip">
<string>Some radios can select the audio input using a CAT command,
this setting allows you to select which audio input will be used
(if it is available then generally the Rear/Data option is best).</string>
</property>
<property name="title">
<string>Transmit Audio Source</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QRadioButton" name="TX_source_data_radio_button">
<property name="text">
<string>Rear&amp;/Data</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="TX_source_mic_radio_button">
<property name="text">
<string>&amp;Front/Mic</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="PTT_method_group_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>How this program activates the PTT on your radio?</string>
</property>
<property name="title">
<string>PTT Method</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="PTT_VOX_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;No PTT activation, instead the radio's automatic VOX is used to key the transmitter.&lt;/p&gt;&lt;p&gt;Use this if you have no radio interface hardware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VO&amp;X</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="PTT_DTR_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 DTR control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The DTR control line of the CAT serial port may be used for this or a DTR control line on a different serial port may be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;DTR</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="PTT_CAT_radio_button">
<property name="toolTip">
<string>Some radios support PTT via CAT commands,
use this option if your radio supports it and you have no
other hardware interface for PTT.</string>
</property>
<property name="text">
<string>C&amp;AT</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="PTT_RTS_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 RTS control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The RTS control line of the CAT serial port may be used for this or a RTS control line on a different serial port may be used. Note that this option is not available on the CAT serial port when hardware flow control is used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>R&amp;TS</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0" rowspan="2" colspan="2">
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="PTT_port_label">
<property name="text">
<string>Port:</string>
</property>
<property name="buddy">
<cstring>PTT_port_combo_box</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="PTT_port_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select the RS-232 serial port utilised for PTT control, this option is available when DTR or RTS is selected above as a transmit method.&lt;/p&gt;&lt;p&gt;This port can be the same one as the one used for CAT control.&lt;/p&gt;&lt;p&gt;For some interface types the special value CAT may be chosen, this is used for non-serial CAT interfaces that can control serial port control lines remotely (OmniRig for example).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string/>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="8" column="2">
<widget class="QGroupBox" name="split_operation_group_box">
<property name="title">
<string>Split Operation</string>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="2">
<widget class="QRadioButton" name="split_emulate_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use only VFO A for split operation (the program temporarily changes the QRG of your rig during transmission).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fake It</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="split_rig_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use VFO A+B for split operation (works with many rigs, but requires the use of both VFOs).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rig</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="split_none_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't use split (not recommended).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="11" column="2">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="11">
<widget class="QGroupBox" name="CAT_control_group_box">
<property name="sizePolicy">
@ -1209,13 +935,6 @@ a few, particularly some Kenwood rigs, require it).</string>
</layout>
</widget>
</item>
<item row="4" column="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="Line" name="line_6">
<property name="orientation">
@ -1223,22 +942,225 @@ a few, particularly some Kenwood rigs, require it).</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="13">
<item row="1" column="1" rowspan="12">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<spacer name="verticalSpacer_5">
<item row="1" column="2">
<widget class="QGroupBox" name="PTT_method_group_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>How this program activates the PTT on your radio?</string>
</property>
<property name="title">
<string>PTT Method</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="PTT_VOX_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;No PTT activation, instead the radio's automatic VOX is used to key the transmitter.&lt;/p&gt;&lt;p&gt;Use this if you have no radio interface hardware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VO&amp;X</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="PTT_DTR_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 DTR control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The DTR control line of the CAT serial port may be used for this or a DTR control line on a different serial port may be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;DTR</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="PTT_CAT_radio_button">
<property name="toolTip">
<string>Some radios support PTT via CAT commands,
use this option if your radio supports it and you have no
other hardware interface for PTT.</string>
</property>
<property name="text">
<string>C&amp;AT</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="PTT_RTS_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the RS-232 RTS control line to toggle your radio's PTT, requires hardware to interface the line.&lt;/p&gt;&lt;p&gt;Some commercial interface units also use this method.&lt;/p&gt;&lt;p&gt;The RTS control line of the CAT serial port may be used for this or a RTS control line on a different serial port may be used. Note that this option is not available on the CAT serial port when hardware flow control is used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>R&amp;TS</string>
</property>
<attribute name="buttonGroup">
<string notr="true">PTT_method_button_group</string>
</attribute>
</widget>
</item>
<item row="2" column="0" rowspan="2" colspan="2">
<layout class="QFormLayout" name="formLayout_4">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="PTT_port_label">
<property name="text">
<string>Port:</string>
</property>
<property name="buddy">
<cstring>PTT_port_combo_box</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="PTT_port_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select the RS-232 serial port utilised for PTT control, this option is available when DTR or RTS is selected above as a transmit method.&lt;/p&gt;&lt;p&gt;This port can be the same one as the one used for CAT control.&lt;/p&gt;&lt;p&gt;For some interface types the special value CAT may be chosen, this is used for non-serial CAT interfaces that can control serial port control lines remotely (OmniRig for example).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string/>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="5" column="2">
<widget class="QGroupBox" name="mode_group_box">
<property name="toolTip">
<string>Modulation mode selected on radio.</string>
</property>
<property name="title">
<string>Mode</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="1">
<widget class="QRadioButton" name="mode_USB_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;USB is usually the correct modulation mode,&lt;/p&gt;&lt;p&gt;unless the radio has a special data or packet mode setting&lt;/p&gt;&lt;p&gt;for AFSK operation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>US&amp;B</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mode_none_radio_button">
<property name="toolTip">
<string>Don't allow the program to set the radio mode
(not recommended but use if the wrong mode
or bandwidth is selected).</string>
</property>
<property name="text">
<string>None</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="2">
<widget class="QRadioButton" name="mode_data_radio_button">
<property name="toolTip">
<string>If this is available then it is usually the correct mode for this program.</string>
</property>
<property name="text">
<string>Data/P&amp;kt</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="2">
<widget class="QGroupBox" name="TX_audio_source_group_box">
<property name="toolTip">
<string>Some radios can select the audio input using a CAT command,
this setting allows you to select which audio input will be used
(if it is available then generally the Rear/Data option is best).</string>
</property>
<property name="title">
<string>Transmit Audio Source</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QRadioButton" name="TX_source_data_radio_button">
<property name="text">
<string>Rear&amp;/Data</string>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="TX_source_mic_radio_button">
<property name="text">
<string>&amp;Front/Mic</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">TX_audio_source_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="9" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1250,8 +1172,82 @@ a few, particularly some Kenwood rigs, require it).</string>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="11" column="2">
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="rig_label">
<property name="text">
<string>Rig:</string>
</property>
<property name="buddy">
<cstring>rig_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="rig_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="CAT_poll_interval_label">
<property name="text">
<string>Poll Interval:</string>
</property>
<property name="buddy">
<cstring>CAT_poll_interval_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="CAT_poll_interval_spin_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Interval to poll rig for status. Longer intervals will mean that changes to the rig will take longer to be detected.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="2">
<layout class="QHBoxLayout" name="testCATPTT_Layout">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QPushButton" name="test_CAT_push_button">
<property name="toolTip">
@ -1308,55 +1304,59 @@ radio interface behave as expected.</string>
</item>
</layout>
</item>
<item row="0" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="rig_label">
<property name="text">
<string>Rig:</string>
<item row="8" column="2">
<widget class="QGroupBox" name="split_operation_group_box">
<property name="title">
<string>Split Operation</string>
</property>
<property name="buddy">
<cstring>rig_combo_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="rig_combo_box">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="CAT_poll_interval_label">
<property name="text">
<string>Poll Interval:</string>
</property>
<property name="buddy">
<cstring>CAT_poll_interval_spin_box</cstring>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="CAT_poll_interval_spin_box">
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="2">
<widget class="QRadioButton" name="split_emulate_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Interval to poll rig for status. Longer intervals will mean that changes to the rig will take longer to be detected.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use only VFO A for split operation (the program temporarily changes the QRG of your rig during transmission).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="suffix">
<string> s</string>
<property name="text">
<string>Fake It</string>
</property>
<property name="minimum">
<number>1</number>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="split_rig_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use VFO A+B for split operation (works with many rigs, but requires the use of both VFOs).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rig</string>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="split_none_radio_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Don't use split (not recommended).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>None</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<attribute name="buttonGroup">
<string notr="true">split_mode_button_group</string>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
<item row="9" column="2">
<spacer name="verticalSpacer_2">
<item row="12" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
@ -1368,84 +1368,6 @@ radio interface behave as expected.</string>
</property>
</spacer>
</item>
<item row="12" column="0">
<widget class="QGroupBox" name="hamlib_groupBox">
<property name="title">
<string>Update Hamlib</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<item row="0" column="0">
<widget class="QRadioButton" name="rbHamlib64">
<property name="text">
<string>64-bit</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="rbHamlib32">
<property name="text">
<string>32-bit</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="revert_update_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Revert the last Hamlib update. &lt;/p&gt;&lt;p&gt;Note: This function is only available on Windows.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Revert Update</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="hamlib_download_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Download the latest libhamlib-4.dll file from https://n0nb.users.sourceforge.net/. &lt;/p&gt;&lt;p&gt;Note: This function is only available on Windows.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Update Hamlib</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<layout class="QGridLayout" name="hamlib_version_gridLayout" columnstretch="0,1">
<item row="0" column="0">
<widget class="QLabel" name="in_use_text">
<property name="text">
<string>In use:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="backed_up_text">
<property name="text">
<string>Backed up:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="in_use">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="backed_up">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="audio_tab">
@ -2513,7 +2435,7 @@ Right click for insert and delete options.</string>
<string>URL</string>
</property>
<property name="text">
<string>http://lotw.arrl.org/lotw-user-activity.csv</string>
<string>https://lotw.arrl.org/lotw-user-activity.csv</string>
</property>
</widget>
</item>
@ -3498,13 +3420,13 @@ Right click for insert and delete options.</string>
</connection>
</connections>
<buttongroups>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
</buttongroups>
</ui>

33
INSTALL
View File

@ -27,7 +27,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 +50,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 +113,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 +143,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 +178,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 +228,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 +352,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

101
NEWS
View File

@ -9,106 +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.
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc2
July 7, 2023

View File

@ -9,106 +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.
Copyright 2001 - 2023 by Joe Taylor, K1JT, and the WSJT Development Team
Release: WSJT-X 2.7.0-rc2
July 7, 2023

View File

@ -206,18 +206,15 @@ void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m, bool /*n
{
CAT_TRACE (f << ' ' << state ());
auto f_string = frequency_to_string (f);
if (UNK != m && m != get_mode ())
auto params = ("<xcvrfreq:%1>" + f_string).arg (f_string.size ());
simple_command (("<command:10>CmdSetFreq<parameters:%1>" + params).arg (params.size ()));
if (UNK != m)
{
auto m_string = map_mode (m);
auto params = ("<xcvrfreq:%1>" + f_string + "<xcvrmode:%2>" + m_string + "<preservesplitanddual:1>Y").arg (f_string.size ()).arg (m_string.size ());
simple_command (("<command:14>CmdSetFreqMode<parameters:%1>" + params).arg (params.size ()));
update_mode (m);
}
else
{
auto params = ("<xcvrfreq:%1>" + f_string).arg (f_string.size ());
simple_command (("<command:10>CmdSetFreq<parameters:%1>" + params).arg (params.size ()));
}
update_rx_frequency (f);
}

View File

@ -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");
}
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

3474
cty.dat

File diff suppressed because it is too large Load Diff

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

@ -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

@ -480,11 +480,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
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 +560,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 +1540,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

@ -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

@ -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,44 +59,26 @@ 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
@ -140,112 +99,9 @@ program ldpcsim240_74
endif
llr=2.0*rxdata/(ss*ss)
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)
endif
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

@ -996,7 +996,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,34 +65,22 @@ 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
@ -131,98 +99,13 @@ program ldpcsim174_91
else
ss=s
endif
llr=2.0*rxdata/(ss*ss)
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
endif
do i=1, 174
if(llr(i)*(codeword(i)-0.5).lt.0) nbiterr=nbiterr+1
enddo
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

@ -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(32) = [ &
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', &
@ -64,7 +64,6 @@ program jt9
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'), &
@ -92,7 +91,7 @@ program jt9
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:9876543WYqTL:S:H:c:G:x:g:X:Q:', &
long_options,c,optarg,arglen,stat,offset,remain,.true.)
if (stat .ne. 0) then
exit
@ -130,8 +129,6 @@ program jt9
read (optarg(:arglen), *) fhigh
case ('q')
mode = 164
case ('k')
mode = 144
case ('Q')
read (optarg(:arglen), *) nQSOProg
case ('3')
@ -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
! Normal decoding pass
call multimode_decoder(shared_data%ss,shared_data%id2,local_params,12000)
endif
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,ndepth,mycall,hiscall,hisgrid)
use prog_args
use timer_module, only: timer
@ -39,7 +39,7 @@ subroutine map65_mmdec(nutc,id2,nqd,ntrperiod, nsubmode,nfa,nfb,nfqso, &
lagain=(nagain.ne.0)
bVHF=.true.
emedelay=2.5
! ntrperiod=60
ntrperiod=60
call timer('dec_q65 ',0)
call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, &

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

@ -17,6 +17,7 @@ module q65
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,save :: s1a(:,:,:) !Cumulative symbol spectra
@ -105,6 +106,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)
@ -143,6 +146,19 @@ subroutine q65_dec0(iavg,iwave,ntrperiod,nfqso,ntol,lclearave, &
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".
@ -490,12 +506,12 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,iavg,ipk,jpk, &
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))
enddo
call pctile(s1avg(ia:ib),ib-ia+1,40,base0)
ccfbest=0.
ibest=0
lagpk=0
@ -772,7 +788,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

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

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;
}

View File

@ -446,8 +446,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);
}

View File

@ -101,7 +101,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

@ -140,7 +140,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
ndpth=3
! NB: Frequency of ipk is now shifted to 1000 Hz.
call map65_mmdec(nutc,iwave,nqd,60,nsubmode,nfa,nfb,1000,ntol, &
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,ndepth,mycall,hiscall0,hisgrid)
MHz=fcenter

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
int valid_entry_count [[maybe_unused]] = 0;
int skipped_entry_count [[maybe_unused]] = 0;
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

View File

@ -13,7 +13,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"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 />"
"Copyright 2001-2023 by Joe Taylor, K1JT. Additional <br />"
"acknowledgments are contained in the source code.");
}

View File

@ -20,7 +20,7 @@
</sizepolicy>
</property>
<property name="windowTitle">
<string>About QMAP</string>
<string>About MAP65</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>

View File

@ -44,8 +44,10 @@ Astro::~Astro()
delete ui;
}
void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg)
void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg)
{
static int ntxFreq0=-99;
char cc[300];
double azsun,elsun,azmoon,elmoon,azmoondx,elmoondx;
double ramoon,decmoon,dgrd,poloffset,xnr;
@ -61,27 +63,30 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xav
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;
astrosub_(&nyear, &month, &nday, &uth, &nfreq, mygrid.toLatin1(),
mygrid.toLatin1(), &azsun, &elsun, &azmoon, &elmoon,
hisgrid.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;
// qDebug() << "aa" << isec << datcom_.fcenter << nfreq << ndop00;
snprintf(cc, sizeof(cc),
"Az: %6.1f\n"
"El: %6.1f\n"
"SelfDop:%6d\n"
"MoonDec:%6.1f\n"
"MyDop: %6d\n"
"DxAz: %6.1f\n"
"DxEl: %6.1f\n"
"DxDop: %6d\n"
"Dec: %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,
azmoon,elmoon,ndop00,azmoondx,elmoondx,ndop,decmoon,azsun,elsun,
nfreq,ntsky,xnr,dgrd);
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
@ -149,6 +154,7 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xav
// Write pointing data to azel.dat
QString fname=azelDir+"/azel.dat";
// qDebug() << "aa" << fname << isec << bPointing << azOffset << elOffset;
QFile f(fname);
if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
if(azelDir==m_AzElDir0) return;
@ -158,18 +164,22 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xav
mb.exec();
return;
}
int ndiff=0;
if(ntxFreq != ntxFreq0) ndiff=1;
ntxFreq0=ntxFreq;
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",
"%3d,%1d,fQSO\n"
"%3d,%1d,fQSO2\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);
fQSO,nsetftx,
ntxFreq,ndiff);
out << cc;
f.close();
}
@ -189,7 +199,3 @@ void Astro::on_cbOnOff_clicked(bool checked)
if(checked) ui->cbAutoCycle->setChecked(false);
}
int Astro::getSelfDop()
{
return m_ndop00;
}

View File

@ -14,10 +14,9 @@ class Astro : public QWidget
public:
explicit Astro (QString const& settings_filename, QWidget *parent = 0);
void astroUpdate(QDateTime t, QString mygrid, QString azelDir, double xavg);
void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg);
void setFontSize(int n);
int getSelfDop();
~Astro ();
private slots:
@ -28,8 +27,6 @@ private:
Ui::Astro *ui;
QString m_settings_filename;
QString m_AzElDir0;
qint32 m_ndop00=0;
};
#endif

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>431</width>
<height>393</height>
<width>441</width>
<height>483</height>
</rect>
</property>
<property name="windowTitle">
@ -19,7 +19,7 @@
<x>269</x>
<y>19</y>
<width>151</width>
<height>361</height>
<height>431</height>
</rect>
</property>
<property name="title">
@ -29,7 +29,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>70</y>
<y>100</y>
<width>30</width>
<height>17</height>
</rect>
@ -42,7 +42,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>70</y>
<y>100</y>
<width>40</width>
<height>17</height>
</rect>
@ -58,7 +58,7 @@
<property name="geometry">
<rect>
<x>110</x>
<y>70</y>
<y>100</y>
<width>30</width>
<height>17</height>
</rect>
@ -71,7 +71,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>120</y>
<y>150</y>
<width>30</width>
<height>17</height>
</rect>
@ -84,7 +84,7 @@
<property name="geometry">
<rect>
<x>60</x>
<y>20</y>
<y>50</y>
<width>30</width>
<height>17</height>
</rect>
@ -97,7 +97,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>180</y>
<y>230</y>
<width>130</width>
<height>22</height>
</rect>
@ -131,7 +131,7 @@
<property name="geometry">
<rect>
<x>30</x>
<y>260</y>
<y>330</y>
<width>91</width>
<height>17</height>
</rect>
@ -144,7 +144,7 @@
<property name="geometry">
<rect>
<x>30</x>
<y>300</y>
<y>380</y>
<width>70</width>
<height>17</height>
</rect>
@ -157,7 +157,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>220</y>
<y>280</y>
<width>130</width>
<height>22</height>
</rect>
@ -172,46 +172,28 @@
<string>Dwell </string>
</property>
<property name="minimum">
<number>15</number>
<number>10</number>
</property>
<property name="maximum">
<number>300</number>
</property>
<property name="singleStep">
<number>5</number>
<number>10</number>
</property>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget">
<widget class="QWidget" name="">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>258</width>
<height>371</height>
<height>471</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>
@ -225,7 +207,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -245,7 +227,7 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -259,22 +241,6 @@
</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>

View File

@ -7,7 +7,7 @@ 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 ss[322*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
@ -17,24 +17,23 @@ extern struct { //This is "common/datcom/..." in Fortran
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 neme; //Hinted decoding tries only for EME calls
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 mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntol; //+/- decoding range around fQSO (Hz)
int n60; //nsecs%60
int junk4; //
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1;
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 nxpol; //1 if using xpol antennas, 0 otherwise
int nmode; //nmode = 10*m_modeQ65 + m_modeJT65
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
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];
@ -43,12 +42,11 @@ extern struct { //This is "common/datcom/..." in Fortran
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 ss[322*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
@ -58,24 +56,23 @@ extern struct { //This is "common/datcom/..." in Fortran
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 neme; //Hinted decoding tries only for EME calls
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 mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntol; //+/- decoding range around fQSO (Hz)
int n60; //nsecs%60
int junk4; //
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1;
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 nxpol; //1 if using xpol antennas, 0 otherwise
int nmode; //nmode = 10*m_modeQ65 + m_modeJT65
int ndop00; //EME Self Doppler
int nsave; //Number of s3(64,63) spectra saved
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];
@ -84,7 +81,6 @@ extern struct { //This is "common/datcom/..." in Fortran
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 {
@ -92,16 +88,10 @@ extern struct {
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
int nWTransmitting; //Set to 1 when WSJT-X is transmitting
char result[50][60]; //Staging area for QMAP decodes
} decodes_;
extern struct {
char revision[22];
char saveFileName[120];
} savecom_;
}
#endif // COMMONS_H

View File

@ -20,8 +20,6 @@ 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);
@ -40,7 +38,6 @@ void DevSetup::accept()
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();

View File

@ -12,6 +12,10 @@ public:
~DevSetup();
void initDlg();
qint32 m_idInt;
qint32 m_pttPort;
qint32 m_timeout;
qint32 m_dPhi;
qint32 m_fCal;
qint32 m_udpPort;
qint32 m_astroFont;
@ -21,14 +25,14 @@ public:
double m_TxOffset;
bool m_network;
bool m_fs96000;
bool m_restartSoundIn;
int m_myCallColor;
QString m_myCall;
QString m_myGrid;
QString m_saveDir;
QString m_azelDir;
QString m_editorCommand;
public slots:
void accept();

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>268</height>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
@ -63,13 +63,6 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Highlight My Call:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -113,9 +106,6 @@
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="myCallColor"/>
</item>
</layout>
</item>
<item>
@ -185,10 +175,10 @@
<item>
<widget class="QSpinBox" name="fCalSpinBox">
<property name="minimum">
<number>-50000</number>
<number>-20000</number>
</property>
<property name="maximum">
<number>50000</number>
<number>20000</number>
</property>
</widget>
</item>
@ -297,7 +287,7 @@
</sizepolicy>
</property>
<property name="title">
<string>Input from Linrad or SDR Console</string>
<string>Input from Linrad</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
@ -322,7 +312,7 @@
<number>-50</number>
</property>
<property name="maximum">
<number>50</number>
<number>10</number>
</property>
<property name="singleStep">
<number>1</number>

View File

@ -6,10 +6,10 @@
extern qint16 id[2*60*96000];
void getfile(QString fname, int dbDgrd)
void getfile(QString fname, bool xpol, int dbDgrd)
{
// int npts=2*56*96000;
int npts=2*60*96000;
int npts=2*56*96000;
if(xpol) npts=2*npts;
// Degrade S/N by dbDgrd dB -- for tests only!!
float dgrd=0.0;
@ -23,32 +23,31 @@ void getfile(QString fname, int dbDgrd)
if(fp != NULL) {
auto n = fread(&datcom_.fcenter,sizeof(datcom_.fcenter),1,fp);
n=fread(id,2,npts,fp);
n=fread(&datcom_.ntx30a,4,1,fp);
n=fread(&datcom_.ntx30b,4,1,fp);
if(n==0) {
datcom_.ntx30a=0;
datcom_.ntx30b=0;
}
// qDebug() << "aa0" << sizeof(datcom_.fcenter) << n << datcom_.fcenter;
n = fread(id,2,npts,fp);
Q_UNUSED (n);
int j=0;
if(dbDgrd<0) {
for(int i=0; i<npts; i+=2) {
datcom_.d4[j++]=fac*((float)id[i] + dgrd*gran());
datcom_.d4[j++]=fac*((float)id[i+1] + dgrd*gran());
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
}
} else {
for(int i=0; i<npts; i+=2) {
datcom_.d4[j++]=(float)id[i];
datcom_.d4[j++]=(float)id[i+1];
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
}
}
fclose(fp);
datcom_.ndiskdat=1;
int nfreq=(int)datcom_.fcenter;
if(nfreq!=144 and nfreq != 432 and nfreq != 1296) datcom_.fcenter=1296.090;
int i0=fname.indexOf(".iq");
if(nfreq!=144 and nfreq != 432 and nfreq != 1296) datcom_.fcenter=1296.080;
int i0=fname.indexOf(".tf2");
if(i0<0) i0=fname.indexOf(".iq");
datcom_.nutc=0;
if(i0>0) {
datcom_.nutc=100*fname.mid(i0-4,2).toInt() + fname.mid(i0-2,2).toInt();
@ -56,9 +55,11 @@ void getfile(QString fname, int dbDgrd)
}
}
void save_iq(QString fname)
void savetf2(QString fname, bool xpol)
{
int npts=2*60*96000;
int npts=2*56*96000;
if(xpol) npts=2*npts;
qint16* buf=(qint16*)malloc(2*npts);
char name[80];
strcpy(name,fname.toLocal8Bit());
@ -68,11 +69,11 @@ void save_iq(QString fname)
fwrite(&datcom_.fcenter,sizeof(datcom_.fcenter),1,fp);
int j=0;
for(int i=0; i<npts; i+=2) {
buf[i]=(qint16)qRound(datcom_.d4[j++]);
buf[i+1]=(qint16)qRound(datcom_.d4[j++]);
buf[i]=(qint16)datcom_.d4[j++];
buf[i+1]=(qint16)datcom_.d4[j++];
// if(!xpol) j+=2; //Skip over d4(3,x) and d4(4,x)
}
fwrite(buf,2,npts,fp);
fwrite(&datcom_.ntx30a,4,2,fp); //Write ntx30a and ntx30b to disk
fclose(fp);
}
free(buf);

View File

@ -5,8 +5,8 @@
#include <QDebug>
#include "commons.h"
void getfile(QString fname, int dbDgrd);
void save_iq(QString fname);
void getfile(QString fname, bool xpol, int dbDgrd);
void savetf2(QString fname, bool xpol);
float gran();
#endif // GETFILE_H

View File

@ -5,14 +5,14 @@ set (libq65_FSRCS
astro.f90
astro0.f90
astrosub.f90
chkstat.f90
dcoord.f90
decode0.f90
dot.f90
fchisq0.f90
fftbig.f90
filbig.f90
four2a.f90
ftninit.f90
# ftnquit.f90
ftnquit.f90
geocentric.f90
getcand2.f90
grid2deg.f90
@ -24,15 +24,12 @@ set (libq65_FSRCS
q65c.f90
q65_sync.f90
qmapa.f90
read_qm.f90
recvpkt.f90
save_qm.f90
sun.f90
symspec.f90
timf2.f90
tm2.f90
toxyz.f90
zaptx.f90
f77_wisdom.f
)

View File

@ -1,40 +0,0 @@
subroutine cfom(dd,k0,k,ndop0)
parameter(NMAX=60*96000)
real dd(2,NMAX)
complex*16 w,wstep
complex*8 c
real*8 twopi,dphi
logical first
data first/.true./
save twopi,w,first
if(first) then
twopi=8.d0*atan(1.d0)
w=1.d0
first=.false.
endif
dop0=0.5*ndop0
dphi=dop0*twopi/96000.0
wstep=cmplx(cos(dphi),sin(dphi))
do j=k0+1,k
c=w*cmplx(dd(1,j),dd(2,j))
dd(1,j)=real(c)
dd(2,j)=aimag(c)
w=w*wstep
enddo
return
end subroutine cfom
subroutine zaptx(dd,k0,k)
parameter(NMAX=60*96000)
real dd(2,NMAX)
dd(1:2,k0+1:k)=0.
return
end subroutine zaptx

View File

@ -1,48 +0,0 @@
program cfom_iq
parameter(NMAX=60*96000)
integer*2 id2(2,NMAX)
complex*16 c,w,wstep
real*8 fcenter,uth8,twopi,dphi
character*6 mygrid
twopi=8.d0*atan(1.d0)
open(10,file='231028_0131.iq',status='old',access='stream')
open(12,file='231028_0131.cfom',status='unknown',access='stream')
mygrid='FN20OG'
nyear=2023
month=10
nday=28
uth8=01 + 31.d0/60
nfreq=1296
call astrosub00(nyear,month,nday,uth8,nfreq,mygrid,ndop0)
call astrosub00(nyear,month,nday,uth8+1.d0/60.d0,nfreq,mygrid,ndop1)
print*,ndop0,ndop1
read(10) fcenter,id2(1:2,1:56*96000)
id2(1:2,56*96000+1:NMAX)=0
dop0=0.5*ndop0
dop1=0.5*ndop1
j=0
w=1.0
do isec=1,60
dop=dop0 + (isec-0.5)*(dop1-dop0)/60.
dphi=dop*twopi/96000.0
wstep=cmplx(cos(dphi),sin(dphi))
do n=1,96000
j=j+1
x=id2(1,j)
y=id2(2,j)
w=w*wstep
c=100.d0*w*cmplx(x,y)
id2(1,j)=0.01d0*real(c)
id2(2,j)=0.01d0*aimag(c)
enddo
enddo
write(12) fcenter,id2
end program cfom_iq

View File

@ -1,28 +0,0 @@
subroutine chkstat(dd,nhsym,pdb)
real dd(2,5760000)
real pdb(4)
integer ia(4),ib(4)
logical*1 btx0,btx1
btx0=.false.
btx1=.false.
ia(1)=23*96000+1
ib(1)=24*96000
ia(2)=27*96000+1
ib(2)=28*96000
ia(3)=53*96000+1
ib(3)=54*96000
ia(4)=57*96000+1
ib(4)=58*96000
do j=1,4
sq=0.
do i=ia(j),ib(j)
sq=sq + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
enddo
pdb(j)=db(1.0 + sq/(2.0*96000.0))
enddo
return
end subroutine chkstat

View File

@ -3,26 +3,24 @@ subroutine decode0(dd,ss,savg)
use timer_module, only: timer
parameter (NSMAX=60*96000)
real*4 dd(2,NSMAX),ss(400,NFFT),savg(NFFT)
real*4 dd(2,NSMAX),ss(322,NFFT),savg(NFFT)
real*8 fcenter
integer offset
integer hist(0:32768)
logical*1 bAlso30
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,datetime*20
character mycall0*12,hiscall0*12,hisgrid0*6
character*64 result
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
character*60 result
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
common/npar/fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,ntx60,newdat,nfa,nfb,nfcal,nfshift, &
ntx30a,ntx30b,ntol,n60,nCFOM,nfsample,ndop58,nmode, &
ndop00,nsave,max_drift,offset,nhsym,mycall,mygrid, &
hiscall,hisgrid,datetime,junk1,junk2,bAlso30
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
data neme0/-99/
save
nQDecoderDone=0
if(newdat.ne.0) then
nz=96000*nhsym*0.15
nz=96000*nhsym/5.3833
hist=0
do i=1,nz
j1=min(abs(dd(1,i)),32768.0)
@ -41,12 +39,13 @@ subroutine decode0(dd,ss,savg)
mycall0=mycall
hiscall0=hiscall
hisgrid0=hisgrid
neme0=neme
call timer('qmapa ',0)
call qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
mousedf,mousefqso,nagain,ntx30a,ntx30b,nfshift,max_drift,offset, &
mousedf,mousefqso,nagain,nfshift,max_drift, &
nfcal,mycall,hiscall,hisgrid,nfsample,nmode,ndepth, &
datetime,ndop00,fselected,bAlso30,nhsym,NCFOM)
datetime,ndop00,fselected)
call timer('qmapa ',1)
return

View File

@ -1,56 +0,0 @@
subroutine fftbig(dd,nmax)
! Do the full length FFT of complex data stored in array dd(2,nmax).
use, intrinsic :: iso_c_binding
use FFTW3
use timer_module, only: timer
parameter (MAXFFT1=5376000)
real*4 dd(2,nmax) !Input data
complex ca(MAXFFT1) !FFT of input
real*8 df
type(C_PTR) :: plan1 !Pointer to FFTW plan
logical first
common/cacb/ca
equivalence (rfilt,cfilt)
data first/.true./,npatience/0/
save
if(nmax.lt.0) go to 900
nfft1=MAXFFT1
if(first) then
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
! Plan the big FFT just once
call timer('FFTplan ',0)
plan1=fftwf_plan_dft_1d(nfft1,ca,ca,+1,nflags)
call timer('FFTplan ',1)
df=96000.d0/nfft1
first=.false.
endif
nz=min(nmax,nfft1)
do i=1,nz
ca(i)=cmplx(dd(1,i),dd(2,i))
enddo
if(nmax.lt.nfft1) then
do i=nmax+1,nfft1
ca(i)=0.
enddo
endif
call timer('FFTbig ',0)
call fftwf_execute_dft(plan1,ca,ca)
call timer('FFTbig ',1)
go to 999
900 call fftwf_destroy_plan(plan1)
999 return
end subroutine fftbig

123
qmap/libqmap/filbig.f90 Normal file
View File

@ -0,0 +1,123 @@
subroutine filbig(dd,nmax,f0,newdat,nfsample,c4a,n4)
! Filter and downsample complex data stored in array dd(2,nmax).
! Output is downsampled from 96000 Hz to 1375.125 Hz.
use timer_module, only: timer
parameter (MAXFFT1=5376000,MAXFFT2=77175)
real*4 dd(2,nmax) !Input data
complex ca(MAXFFT1) !FFT of input
complex c4a(MAXFFT2) !Output data
real*8 df
real halfpulse(8) !Impulse response of filter (one sided)
complex cfilt(MAXFFT2) !Filter (complex; imag = 0)
real rfilt(MAXFFT2) !Filter (real)
integer*8 plan1,plan2,plan3,plan4,plan5
logical first
include 'fftw3.f'
common/cacb/ca
equivalence (rfilt,cfilt)
data first/.true./,npatience/1/
data halfpulse/114.97547150,36.57879257,-20.93789101, &
5.89886379,1.59355187,-2.49138308,0.60910773,-0.04248129/
save
if(nmax.lt.0) go to 900
nfft1=MAXFFT1
nfft2=MAXFFT2
if(nfsample.eq.95238) then
nfft1=5120000
nfft2=74088
endif
if(first) then
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
! Plan the FFTs just once
call timer('FFTplans ',0)
call sfftw_plan_dft_1d(plan1,nfft1,ca,ca,FFTW_BACKWARD,nflags)
call sfftw_plan_dft_1d(plan3,nfft2,c4a,c4a,FFTW_FORWARD,nflags)
call sfftw_plan_dft_1d(plan5,nfft2,cfilt,cfilt,FFTW_BACKWARD,nflags)
call timer('FFTplans ',1)
! Convert impulse response to filter function
do i=1,nfft2
cfilt(i)=0.
enddo
fac=0.00625/nfft1
cfilt(1)=fac*halfpulse(1)
do i=2,8
cfilt(i)=fac*halfpulse(i)
cfilt(nfft2+2-i)=fac*halfpulse(i)
enddo
call sfftw_execute(plan5)
base=cfilt(nfft2/2+1)
do i=1,nfft2
rfilt(i)=real(cfilt(i))-base
enddo
df=96000.d0/nfft1
if(nfsample.eq.95238) df=95238.1d0/nfft1
first=.false.
endif
! When new data comes along, we need to compute a new "big FFT"
! If we just have a new f0, continue with the existing ca.
if(newdat.ne.0 .or. sum(abs(ca)).eq.0.0) then !### Test on ca should be unnecessary?
nz=min(nmax,nfft1)
do i=1,nz
ca(i)=cmplx(dd(1,i),dd(2,i))
enddo
if(nmax.lt.nfft1) then
do i=nmax+1,nfft1
ca(i)=0.
enddo
endif
call timer('FFTbig ',0)
call sfftw_execute(plan1)
call timer('FFTbig ',1)
!### newdat=0
endif
! NB: f0 is the frequency at which we want our filter centered.
! i0 is the bin number in ca closest to f0.
i0=nint(f0/df) + 1
nh=nfft2/2
do i=1,nh !Copy data into c4a
j=i0+i-1 !and apply the filter function
if(j.ge.1 .and. j.le.nfft1) then
c4a(i)=rfilt(i)*ca(j)
else
c4a(i)=0.
endif
enddo
do i=nh+1,nfft2
j=i0+i-1-nfft2
if(j.lt.1) j=j+nfft1
c4a(i)=rfilt(i)*ca(j)
enddo
! Do the short reverse transform, to go back to time domain.
call timer('FFTsmall',0)
call sfftw_execute(plan3)
call timer('FFTsmall',1)
n4=min(nmax/64,nfft2)
go to 999
900 call sfftw_destroy_plan(plan1)
call sfftw_destroy_plan(plan2)
call sfftw_destroy_plan(plan3)
call sfftw_destroy_plan(plan4)
call sfftw_destroy_plan(plan5)
999 return
end subroutine filbig

115
qmap/libqmap/four2a.f90 Normal file
View File

@ -0,0 +1,115 @@
subroutine four2a(a,nfft,ndim,isign,iform)
! IFORM = 1, 0 or -1, as data is
! complex, real, or the first half of a complex array. Transform
! values are returned in array DATA. They are complex, real, or
! the first half of a complex array, as IFORM = 1, -1 or 0.
! The transform of a real array (IFORM = 0) dimensioned N(1) by N(2)
! by ... will be returned in the same array, now considered to
! be complex of dimensions N(1)/2+1 by N(2) by .... Note that if
! IFORM = 0 or -1, N(1) must be even, and enough room must be
! reserved. The missing values may be obtained by complex conjugation.
! The reverse transformation of a half complex array dimensioned
! N(1)/2+1 by N(2) by ..., is accomplished by setting IFORM
! to -1. In the N array, N(1) must be the true N(1), not N(1)/2+1.
! The transform will be real and returned to the input array.
! This version of four2a makes calls to the FFTW library to do the
! actual computations.
use fftw3
parameter (NPMAX=2100) !Max numberf of stored plans
parameter (NSMALL=16384) !Max size of "small" FFTs
complex a(nfft+1) !Array to be transformed
complex aa(NSMALL) !Local copy of "small" a()
integer nn(NPMAX),ns(NPMAX),nf(NPMAX) !Params of stored plans
integer*8 nl(NPMAX),nloc !More params of plans
integer*8 plan(NPMAX) !Pointers to stored plans
logical found_plan
data nplan/0/ !Number of stored plans
common/patience/npatience,nthreads !Patience and threads for FFTW plans
save plan,nplan,nn,ns,nf,nl
if(nfft.lt.0) go to 999
nloc=loc(a)
found_plan = .false.
!$omp critical(four2a_setup)
do i=1,nplan
if(nfft.eq.nn(i) .and. isign.eq.ns(i) .and. &
iform.eq.nf(i) .and. nloc.eq.nl(i)) then
found_plan = .true.
exit
end if
enddo
if(i.ge.NPMAX) stop 'Too many FFTW plans requested.'
if (.not. found_plan) then
nplan=nplan+1
i=nplan
nn(i)=nfft
ns(i)=isign
nf(i)=iform
nl(i)=nloc
! Planning: FFTW_ESTIMATE, FFTW_ESTIMATE_PATIENT, FFTW_MEASURE,
! FFTW_PATIENT, FFTW_EXHAUSTIVE
nflags=FFTW_ESTIMATE
if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT
if(npatience.eq.2) nflags=FFTW_MEASURE
if(npatience.eq.3) nflags=FFTW_PATIENT
if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE
if(nfft.le.NSMALL) then
jz=nfft
if(iform.eq.0) jz=nfft/2
aa(1:jz)=a(1:jz)
endif
!$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
if(isign.eq.-1 .and. iform.eq.1) then
call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_FORWARD,nflags)
else if(isign.eq.1 .and. iform.eq.1) then
call sfftw_plan_dft_1d(plan(i),nfft,a,a,FFTW_BACKWARD,nflags)
else if(isign.eq.-1 .and. iform.eq.0) then
call sfftw_plan_dft_r2c_1d(plan(i),nfft,a,a,nflags)
else if(isign.eq.1 .and. iform.eq.-1) then
call sfftw_plan_dft_c2r_1d(plan(i),nfft,a,a,nflags)
else
stop 'Unsupported request in four2a'
endif
!$omp end critical(fftw)
if(nfft.le.NSMALL) then
jz=nfft
if(iform.eq.0) jz=nfft/2
a(1:jz)=aa(1:jz)
endif
end if
!$omp end critical(four2a_setup)
call sfftw_execute(plan(i))
return
999 continue
!$omp critical(four2a)
do i=1,nplan
! The test is only to silence a compiler warning:
if(ndim.ne.-999) then
!$omp critical(fftw) ! serialize non thread-safe FFTW3 calls
call sfftw_destroy_plan(plan(i))
!$omp end critical(fftw)
end if
enddo
nplan=0
!$omp end critical(four2a)
return
end subroutine four2a

View File

@ -3,8 +3,10 @@ subroutine ftninit
use timer_impl, only: init_timer !,fini_timer, limtrace
use, intrinsic :: iso_c_binding, only: C_NULL_CHAR
use FFTW3
! character*(*) appd
character*1 appd
character addpfx*8
character wisfile*256
common/pfxcom/addpfx
lu=8
@ -15,6 +17,17 @@ subroutine ftninit
open(12,file=appd//'/all_qmap.txt',status='unknown',position='append')
open(17,file=appd//'/red.dat',status='unknown')
open(19,file=appd//'/livecq.txt',status='unknown')
open(71,file=appd//'/fort.71',status='unknown')
open(72,file=appd//'/fort.72',status='unknown')
open(73,file=appd//'/fort.73',status='unknown')
! Import FFTW wisdom, if available:
iret=fftwf_init_threads() !Initialize FFTW threading
! Default to 1 thread, but use nthreads for the big ones
call fftwf_plan_with_nthreads(1)
! Import FFTW wisdom, if available
wisfile=trim(appd)//'/m65_wisdom.dat'// C_NULL_CHAR
iret=fftwf_import_wisdom_from_filename(wisfile)
return
end subroutine ftninit

View File

@ -2,7 +2,7 @@ subroutine ftnquit
! Destroy the FFTW plans
call four2a(a,-1,1,1,1)
call fftbig(id,-1)
call filbig(id,-1,f0,newdat,nfsample,c4a,n4)
return
end subroutine ftnquit

View File

@ -1,5 +1,4 @@
subroutine getcand2(ss,savg0,nts_q65,nagain,nhsym,ntx30a,ntx30b, &
ntol,f0_selected,bAlso30,cand,ncand2)
subroutine getcand2(ss,savg0,nts_q65,nagain,ntol,f0_selected,cand,ncand)
! Get candidates for Q65 decodes, based on presence of sync tone.
@ -7,18 +6,15 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,nhsym,ntx30a,ntx30b, &
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type candidate
parameter (NFFT=32768) !FFTs done in symspec()
parameter (MAX_CANDIDATES=50)
type(candidate) :: cand(MAX_CANDIDATES)
real ss(400,NFFT) !Symbol spectra
real ss(322,NFFT) !Symbol spectra
real savg0(NFFT),savg(NFFT) !Average spectra over whole Rx sequence
integer ipk1(1) !Peak index of local portion of spectrum
logical sync_ok !True if sync pattern is present
logical*1 bAlso30
data nseg/16/,npct/40/
savg=savg0 !Save the original spectrum
@ -39,7 +35,7 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,nhsym,ntx30a,ntx30b, &
nguard=5 !Guard range in bins
i1=1
i2=NFFT-nbw-nguard
if(nagain.ge.1) then
if(nagain.eq.1) then
i1=nint((1000.0*f0_selected-ntol)/df)
i2=nint((1000.0*f0_selected+ntol)/df)
endif
@ -52,65 +48,20 @@ subroutine getcand2(ss,savg0,nts_q65,nagain,nhsym,ntx30a,ntx30b, &
i0=ipk1(1) + i - 1 !Index of local peak in savg()
fpk=0.001*i0*df !Frequency of peak (kHz)
! Check to see if sync tone is present.
ntrperiod=60
iseq=0
if(nhsym.ge.200) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
call q65_sync(ss,i0,nts_q65,sync_ok,snr_sync,xdt)
if(.not.sync_ok) cycle
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
if(.not.bAlso30) cycle
ntrperiod=30
if(nhsym.le.200 .and. ntx30a.le.5) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
iseq=1
if(nhsym.ge.330 .and. ntx30b.le.5) then
call q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr_sync,xdt)
if(sync_ok) then
! Sync tone is present, we have a candidate for decoding
j=j+1
cand(j)%f=fpk
cand(j)%xdt=xdt
cand(j)%snr=snr_sync
cand(j)%ntrperiod=ntrperiod
cand(j)%iseq=iseq
ia=max(1,min(i,i0-nguard))
ib=min(i0+nbw+nguard,32768)
savg(ia:ib)=0.
if(j.ge.MAX_CANDIDATES) exit
endif
endif
enddo
ncand2=j !Total number of candidates found
ncand=j !Total number of candidates found
return
end subroutine getcand2

View File

@ -1 +1 @@
parameter(NJUNK=42)
parameter(NJUNK=40)

View File

@ -1,42 +1,38 @@
subroutine q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr,xdt)
subroutine q65_sync(ss,i0,nts_q65,sync_ok,snr,xdt)
! Test for presence of Q65 sync tone
parameter (NFFT=32768)
parameter (LAGMAX=33)
real ss(400,NFFT) !Symbol spectra
real ss(322,NFFT) !Symbol spectra
real ccf(0:LAGMAX) !The WSJT "blue curve", peak at DT
logical sync_ok
integer isync0(22),isync(22),ipk(1)
logical first
integer isync(22),ipk(1)
! Q65 sync symbols
data isync0/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
data first/.true./
save first,isync
sync_ok=.false.
! if(ntrperiod.ne.60) return
tstep=0.15 !0.5*tsym_Q65-30x, 0.25*tsys_Q65-60x
nfac=4
if(ntrperiod.eq.30) nfac=2
do i=1,22 !Expand sync stride for Q65-60x
isync(i)=nfac*(isync0(i)-1) + 1
tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65
if(first) then
fac=0.6/tstep !3.230
do i=1,22 !Expand the Q65 sync stride
isync(i)=nint((isync(i)-1)*fac) + 1
enddo
first=.false.
endif
m=nts_q65/2
if(ntrperiod.eq.30) m=nts_q65/4
i1=max(1,i0-m)
i2=min(NFFT,i0+m)
ccf=0.
do lag=0,LAGMAX !Search over range of DT
do j=1,22 !Test for Q65 sync
k=isync(j) + lag + iseq*200
if(k.ge.400) cycle
if(ntrperiod.eq.60) then
k=isync(j) + lag
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2)) &
+ sum(ss(k+2,i1:i2)) + sum(ss(k+3,i1:i2))
else
ccf(lag)=ccf(lag) + sum(ss(k,i1:i2)) + sum(ss(k+1,i1:i2))
endif
+ sum(ss(k+2,i1:i2))
! Q: Should we use weighted sums, perhaps a Lorentzian peak?
enddo
enddo
@ -44,20 +40,16 @@ subroutine q65_sync(ss,i0,nts_q65,ntrperiod,iseq,sync_ok,snr,xdt)
ipk=maxloc(ccf)
lagbest=ipk(1)-1
xdt=lagbest*tstep - 1.0
if(ntrperiod.eq.30) xd=xdt+0.6 !Why ???
xsum=0.
sq=0.
nsum=0
fpk=0.001*i0*96000.0/32768.0 + 32.0
do i=0,lagmax !Compute ave and rms of "blue curve"
if(abs(i-lagbest).gt.2) then
xsum=xsum+ccf(i)
sq=sq+ccf(i)**2
nsum=nsum+1
endif
! write(40,3040) i,i*tstep-1.0,ccf(i),fpk
!3040 format(i5,3f8.2)
enddo
ave=xsum/nsum
rms=sqrt(sq/nsum - ave*ave)

View File

@ -1,7 +1,6 @@
subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
ntrperiod,iseq,mycall0,hiscall0,hisgrid,mode_q65,f0,fqso,nkhz_center, &
newdat,nagain,bClickDecode,max_drift,offset,ndepth,datetime,nCFOM, &
ndop00,nhsym,idec)
mycall0,hiscall0,hisgrid,mode_q65,f0,fqso,nkhz_center, newdat,nagain, &
max_drift,ndepth,datetime,ndop00,idec)
! This routine provides an interface between QMAP and the Q65 decoder
! in WSJT-X. All arguments are input data obtained from the QMAP GUI.
@ -9,32 +8,25 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
! in common/cacb. Decoded messages are sent back to the GUI.
use q65_decode
use wavhdr
use timer_module, only: timer
parameter (MAXFFT1=5376000) !56*96000
parameter (MAXFFT2=336000) !56*6000 (downsampled by 1/16)
parameter (NMAX=60*12000)
parameter (RAD=57.2957795)
type(hdr) h
integer*2 iwave(60*12000)
integer offset
complex ca(MAXFFT1) !FFT of raw I/Q data from Linrad
complex cx(0:MAXFFT2-1),cz(0:MAXFFT2)
real*8 fcenter,freq0,freq1
logical*1 bClickDecode
character*12 mycall0,hiscall0
character*12 mycall,hiscall
character*6 hisgrid
character*4 grid4
character*3 csubmode
character*17 fname
character*64 result,ctmp
character*20 datetime,datetime1
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
character*60 result
character*20 datetime
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
common/cacb/ca
data ifile/0/
save
if(mycall0(1:1).ne.' ') mycall=mycall0
@ -44,18 +36,26 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
! Find best frequency from sync_dat, the "orange sync curve".
df3=96000.0/32768.0
ipk=(1000.0*f0-1.0)/df3
if(nagain.ge.2) ipk = nint(1000.0*(fqso-nkhz_center+48.0)/df3)
nfft1=MAXFFT1
nfft2=MAXFFT2
df=96000.0/NFFT1
if(nfsample.eq.95238) then
nfft1=5120000
nfft2=322560
df=96000.0/nfft1
endif
nh=nfft2/2
f_mouse=1000.0*(fqso+48.0) + mousedf
k0=nint((ipk*df3-1000.0)/df)
if(nagain.eq.1) k0=nint((f_mouse-1000.0)/df)
if(k0.lt.nh .or. k0.gt.MAXFFT1-nfft2+1) go to 900
fac=1.0/nfft2
cx(0:nfft2-1)=fac*ca(k0:k0+nfft2-1)
cx(0:nfft2-1)=ca(k0:k0+nfft2-1)
cx=fac*cx
! Here cx is frequency-domain data around the selected
! QSO frequency, taken from the full-length FFT computed in fftbig().
! QSO frequency, taken from the full-length FFT computed in filbig().
! Values for fsample, nfft1, nfft2, df, and the downsampled data rate
! are as follows:
@ -88,65 +88,19 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
nsubmode=mode_q65-1
nfa=990 !Tight limits around ipk for the wideband decode
nfb=1010
if(nagain.ge.1) then !For nagain>=1, use limits of +/- ntol
if(nagain.eq.1) then !For nagain=1, use limits of +/- ntol
nfa=max(100,1000-ntol)
nfb=min(2500,1000+ntol)
endif
nsnr0=-99 !Default snr for no decode
if(iseq.eq.1) iwave(1:360000)=iwave(360001:720000)
csubmode(1:2)='60'
csubmode(3:3)=char(ichar('A')+nsubmode)
nhhmmss=100*nutc
nutc1=nutc
datetime(12:13)='00'
datetime1=datetime
if(ntrperiod.eq.30) then
csubmode(1:2)='30'
nhhmmss=100*nutc + iseq*30
nutc1=nhhmmss
if(iseq.eq.1) datetime1(12:13)='30'
endif
if(nagain.ge.2) then
ifile=ifile+1
write(fname,1000) ifile
1000 format('000000_',i6.6,'.wav')
open(27,file=fname,status='unknown',access='stream')
if(nagain.eq.2) then
h=default_header(12000,60*12000)
ia=1
ib=60*12000
else if(nagain.eq.3) then
h=default_header(12000,30*12000)
ia=1
ib=30*12000
else
h=default_header(12000,30*12000)
ia=30*12000 + 1
ib=60*12000
endif
write(27) h,iwave(ia:ib)
close(27)
go to 900
endif
! NB: Frequency of ipk is now shifted to 1000 Hz.
nagain2=0
call map65_mmdec(nutc1,iwave,nqd,ntrperiod,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain2,max_drift,ndepth,mycall,hiscall,hisgrid)
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,ndepth,mycall,hiscall,hisgrid)
MHz=fcenter
freq0=MHz + 0.001d0*ikhz
if(nsnr0.gt.-99) then
do i=1,ndecodes !Check for dupes
i1=index(result(i)(42:),trim(msg0))
! If this is a dupe, don't save it again:
if(i1.gt.0 .and. (.not.bClickDecode .or. nhsym.eq.390)) go to 800
enddo
nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal
nq65df=nq65df + nfreq0 - 1000
ikhz1=ikhz
@ -155,16 +109,15 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
if(ndf.lt.-500) ikhz1=ikhz + (nq65df-500)/1000
ndf=nq65df - 1000*(ikhz1-ikhz)
freq1=freq0 + 0.001d0*(ikhz1-ikhz)
ndecodes=ndecodes+1
frx=0.001*k0*df+nkhz_center-48.0+1.0 - 0.001*nfcal
fsked=frx - 0.001*ndop00/2.0 - 0.001*offset
ctmp=csubmode//' '//trim(msg0)
ndecodes=min(ndecodes+1,50)
write(result(ndecodes),1120) nhhmmss,frx,fsked,xdt0,nsnr0,trim(ctmp)
1120 format(i6.6,f9.3,f7.1,f7.2,i5,2x,a)
write(12,1130) datetime1,trim(result(ndecodes)(7:))
1130 format(a13,1x,a)
fsked=frx - 0.001*ndop00/2.0 - 1.5
write(result(ndecodes),1120) nutc,frx,fsked,xdt0,nsnr0,trim(msg0)
1120 format(i4.4,f9.3,f7.1,f7.2,i5,2x,a)
write(12,1130) datetime,trim(result(ndecodes)(5:))
1130 format(a11,1x,a)
result(ndecodes)=trim(result(ndecodes))//char(0)
800 idec=0
idec=0
endif
900 flush(12)

View File

@ -1,4 +1,4 @@
subroutine q65c
subroutine q65c(itimer)
use timer_module, only: timer
use timer_impl, only: fini_timer !, limtrace
@ -10,96 +10,42 @@ subroutine q65c
parameter (NFFT=32768)
include 'njunk.f90'
real*8 fcenter
real*4 pdb(4)
integer nparams0(NJUNK+3),nparams(NJUNK+3)
! integer values(8)
logical first
logical*1 bAlso30
character*120 fname
character*22 revision
character*12 mycall,hiscall
character*6 mygrid,hisgrid
character*20 datetime
character*64 result
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
common/datcom2/dd(2,5760000),ss(400,NFFT),savg(NFFT),nparams0
common/savecom/revision,fname
common/datcom2/dd(2,5760000),ss(322,NFFT),savg(NFFT),nparams0
!### REMEMBER that /npar/ is not updated until nparams=nparams0 is executed. ###
common/npar/fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,ntx60,newdat,nn1,nn2,nfcal,nfshift, &
ntx30a,ntx30b,ntol,n60,nCFOM,nfsample,ndop58,nmode, &
ndop00,nsave,nn3,nn4,nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2,bAlso30
ndepth,ndiskdat,neme,newdat,nfcal,nfshift, &
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
ndop00,nsave,max_nhsym,mycall,mygrid,hiscall,hisgrid, &
datetime,junk1,junk2
equivalence (nparams,fcenter)
data first/.true./
save first
nparams=nparams0 !Copy parameters into common/npar/
datetime(12:)='00 '
if(itimer.ne.0) then
call timer('decode0 ',101)
call fini_timer
return
endif
datetime(18:20)=':00'
npatience=1
newdat=1 !Always on ??
if(ndiskdat.eq.1) then
call chkstat(dd,nhsym,pdb)
if((abs(pdb(1)-pdb(2)).gt.3.0 .and. pdb(1).gt.1.0) .or. &
pdb(1).lt.1.0) ntx30a=20 !Tx 1st half
if((abs(pdb(3)-pdb(4)).gt.3.0 .and. pdb(3).gt.1.0) .or. &
pdb(3).lt.1.0) ntx30b=20 !Tx 2nd half
if(pdb(4).lt.0.04) then
ntx30a=0 !Older 56s files have no Tx
ntx30b=0 !Older 56s files have no Tx
endif
endif
! write(*,3001) 'aa',newdat,nagain,nfa,nfb,ntol,fselected
!3001 format(a2,5i6,f10.3)
! write(*,3001) 'bb',newdat,nagain,nfa,nfb,ntol,fselected
if(ntx30a.gt.5) then
dd(1:2,1:30*96000)=0.
ss(1:200,1:NFFT)=0.
do i=1,NFFT
savg(i)=sum(ss(201:400,i))
enddo
endif
if(ntx30b.gt.5) then
dd(1:2,30*96000+1:60*96000)=0.
ss(201:400,1:NFFT)=0.
do i=1,NFFT
savg(i)=sum(ss(1:200,i))
enddo
endif
if(nhsym.gt.200 .and. ntx30b.gt.5) go to 10
call timer('decode0 ',0)
call decode0(dd,ss,savg)
call timer('decode0 ',1)
10 continue
! call date_and_time(VALUES=values)
! n60b=values(7)
! nd=n60b-n60
! if(nd.lt.0) nd=nd+60
! write(*,3002) nutc,nagain,nhsym,n60,n60b,nd,ntx30a,ntx30b,ndecodes, &
! nsave,revision
!3002 format('A',i5.4,i3,i5,7i4,1x,a22)
! flush(6)
if(ndiskdat.eq.0) then
if(nhsym.eq.390 .and. &
(nsave.eq.2 .or. (nsave.eq.1 .and. ndecodes.ge.1))) then
call save_qm(fname,revision,mycall,mygrid,dd,ntx30a,ntx30b,fcenter, &
nutc,ndop00,ndop58)
endif
endif
return
end subroutine q65c
subroutine all_done
use timer_module, only: timer
use timer_impl, only: fini_timer
call timer('decode0 ',101)
call fini_timer
return
end subroutine all_done

View File

@ -1,7 +1,6 @@
subroutine qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
mousedf,mousefqso,nagain,ntx30a,ntx30b,nfshift,max_drift,offset, &
nfcal,mycall,hiscall,hisgrid,nfsample,nBaseSubmode,ndepth, &
datetime,ndop00,fselected,bAlso30,nhsym,nCFOM)
mousedf,mousefqso,nagain,nfshift,max_drift,nfcal,mycall, &
hiscall,hisgrid,nfsample,nmode,ndepth,datetime,ndop00,fselected)
! Processes timf2 data received from Linrad to find and decode Q65 signals.
@ -11,109 +10,64 @@ subroutine qmapa(dd,ss,savg,newdat,nutc,fcenter,ntol,nfa,nfb, &
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type candidate
type good_decode
real :: f !Freq of sync tone, 0 to 96000 Hz
integer :: ntrperiod !60 for Q65-60x, 30 for Q65-30x
integer :: iseq !0 for first half-minute, 1 for second half
end type good_decode
parameter (NFFT=32768) !Size of FFTs done in symspec()
parameter (MAX_CANDIDATES=50)
parameter (MAXMSG=1000) !Size of decoded message list
parameter (NSMAX=60*96000)
complex cx(NSMAX/64) !Data at 1378.125 samples/s
real dd(2,NSMAX) !I/Q data from Linrad
real ss(400,NFFT) !Symbol spectra
real ss(322,NFFT) !Symbol spectra
real savg(NFFT) !Average spectrum
real*8 fcenter !Center RF frequency, MHz
logical*1 bAlso30,bClickDecode
character mycall*12,hiscall*12,hisgrid*6
type(candidate) :: cand(MAX_CANDIDATES)
type(good_decode) found(MAX_CANDIDATES)
character*64 result
character*60 result
character*20 datetime
common/decodes/ndecodes,ncand2,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,kHzRequested,result(50)
common/decodes/ndecodes,ncand,nQDecoderDone,nWDecoderBusy, &
nWTransmitting,result(50)
save
tsec0=sec_midn()
if(nagain.ge.1) ndepth=3 !Use full depth for click-to-decode
if(nagain.eq.1) ndepth=3 !Use full depth for click-to-decode
nkhz_center=nint(1000.0*(fcenter-int(fcenter)))
mfa=nfa-nkhz_center+48
mfb=nfb-nkhz_center+48
mode_q65=nBaseSubmode
mode_q65=nmode/10
nts_q65=2**(mode_q65-1) !Q65 tone separation factor
f0_selected=fselected - nkhz_center + 48.0
if(nagain.le.1) then
call timer('get_cand',0)
! Get a list of decoding candidates
call getcand2(ss,savg,nts_q65,nagain,nhsym,ntx30a,ntx30b,ntol, &
f0_selected,bAlso30,cand,ncand2)
! Get a list of decoding candidates
call getcand2(ss,savg,nts_q65,nagain,ntol,f0_selected,cand,ncand)
call timer('get_cand',1)
endif
nwrite_q65=0
df=96000.0/NFFT !df = 96000/NFFT = 2.930 Hz
if(nfsample.eq.95238) df=95238.1/NFFT
ftol=0.010 !Frequency tolerance (kHz)
foffset=0.001*(1270 + nfcal) !Offset from sync tone, plus CAL
fqso=mousefqso + foffset - 0.5*(nfa+nfb) + nfshift !fqso at baseband (khz)
nqd=0
bClickDecode=(nagain.ge.1)
nagain2=0
call timer('fftbig ',0)
call fftbig(dd,NSMAX) !Do the full-length FFT
call timer('fftbig ',1)
call timer('filbig ',0)
call filbig(dd,NSMAX,f0,newdat,nfsample,cx,n5) !Do the full-length FFT
call timer('filbig ',1)
if(nagain.ge.2) then
ncand2=1
fqso=fselected
endif
do icand=1,ncand2 !Attempt to decode each candidate
tsec=sec_midn() - tsec0
if(ndiskdat.eq.0) then
! No more realtime decode attempts if it's nearly too late, already
if(nhsym.eq.130 .and. tsec.gt.6.0) exit
if(nhsym.eq.200 .and. tsec.gt.10.0) exit
if(nhsym.eq.330 .and. tsec.gt.6.0) exit
if(nhsym.eq.390 .and. tsec.gt.16.0) exit
endif
do icand=1,ncand !Attempt to decode each candidate
f0=cand(icand)%f
ntrperiod=cand(icand)%ntrperiod
iseq=cand(icand)%iseq
if(nagain.eq.0) then
! Skip this candidate if we already decoded it.
do j=1,ndecodes
if(abs(f0-found(j)%f).lt.0.005 .and. &
ntrperiod.eq.found(j)%ntrperiod .and. &
iseq.eq.found(j)%iseq) go to 10
enddo
endif
mode_q65_tmp=mode_q65
if(ntrperiod.eq.30) mode_q65_tmp=max(1,mode_q65-1)
freq=f0+nkhz_center-48.0-1.27046
freq=cand(icand)%f+nkhz_center-48.0-1.27046
ikhz=nint(freq)
idec=-1
call timer('q65b ',0)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
ntrperiod,iseq,mycall,hiscall,hisgrid,mode_q65_tmp,f0,fqso, &
nkhz_center,newdat,nagain,bClickDecode,max_drift,offset, &
ndepth,datetime,nCFOM,ndop00,nhsym,idec)
mycall,hiscall,hisgrid,mode_q65,f0,fqso,nkhz_center,newdat, &
nagain2,max_drift,ndepth,datetime,ndop00,idec)
call timer('q65b ',1)
if(bClickDecode .and. idec.ge.0) exit
if(idec.ge.0) then
! Save some details on good decodes, to avoid duplicated effort
found(ndecodes)%f=f0
found(ndecodes)%ntrperiod=ntrperiod
found(ndecodes)%iseq=iseq
end if
10 continue
tsec=sec_midn() - tsec0
if(tsec.gt.30.0) exit !Don't start another decode attempt after t=30 s.
enddo ! icand
return

View File

@ -1,44 +0,0 @@
subroutine read_qm(fname,iret)
include 'njunk.f90'
parameter(NMAX=60*96000,NFFT=32768)
character*(*) fname
character prog_id*24,mycall*12,mygrid*6
real*8 fcenter
integer nxtra(15) !For possible future additions
integer*1 id1(2,NMAX)
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT), &
fcenter,nutc,fselected,mousedf,mousefqso,nagain, &
ndepth,ndiskdat,ntx60,newdat,nn1,nn2,nfcal,nfshift, &
ntx30a,ntx30b !...
open(28,file=trim(fname),status='old',access='stream',err=900)
read(28,end=910) prog_id,mycall,mygrid,fcenter,nutc,ntx30a, &
ntx30b,ndop00,ndop58,ia,ib,fac0,nxtra
iret=3
if(ib.eq.NMAX/2) iret=1
if(ia.eq.NMAX/2+1) iret=2
fac=1.0
if(fac0.gt.0.0) fac=1.0/fac0
id1=0
read(28,end=910) id1(1:2,ia:ib)
dd=0.
dd(1:2,ia:ib)=fac*id1(1:2,ia:ib) !Boost back to previous level
go to 999
900 iret=-1; go to 999
910 iret=-2
999 close(28)
! sq1=0.
! sq2=0.
! NH=NMAX/2
! do i=1,NMAX
! if(i.le.NH) sq1=sq1 + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
! if(i.gt.NH) sq2=sq2 + dd(1,i)*dd(1,i) + dd(2,i)*dd(2,i)
! enddo
! print*,'B',sqrt(sq1/NMAX),sqrt(sq2/NMAX)
return
end subroutine read_qm

View File

@ -1,4 +1,4 @@
subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,ndb)
subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8)
! Reformat timf2 data from Linrad and stuff data into r*4 array dd().
@ -11,12 +11,11 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,ndb)
integer*2 jd(4),kd(2),nblock2
real*4 yd(2)
real*8 fcenter
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT),fcenter,nutc, &
common/datcom/dd(2,5760000),ss(322,NFFT),savg(NFFT),fcenter,nutc, &
junk(NJUNK)
equivalence (kd,d4)
equivalence (jd,d8,yd)
gain=10.0**(0.05*ndb)
if(nblock2.eq.-9999) nblock2=-9998 !Silence a compiler warning
if(nsam.eq.-1) then
! Move data from the UDP packet buffer into array dd().
@ -24,15 +23,15 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,ndb)
do i=1,174 !One RF channel, r*4 data
k=k+1
d8=buf8(i)
dd(1,k)=yd(1)*gain
dd(2,k)=yd(2)*gain
dd(1,k)=yd(1)
dd(2,k)=yd(2)
enddo
else if(userx_no.eq.1) then
do i=1,348 !One RF channel, i*2 data
k=k+1
d4=buf4(i)
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
dd(1,k)=kd(1)
dd(2,k)=kd(2)
enddo
endif
else
@ -40,12 +39,12 @@ subroutine recvpkt(nsam,nblock2,userx_no,k,buf4,buf8,ndb)
do i=1,nsam !One RF channel, r*4 data
k=k+1
d4=buf4(i)
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
dd(1,k)=kd(1)
dd(2,k)=kd(2)
k=k+1
dd(1,k)=kd(1)*gain
dd(2,k)=kd(2)*gain
dd(1,k)=kd(1)
dd(2,k)=kd(2)
enddo
endif
endif

View File

@ -1,63 +0,0 @@
subroutine save_qm(fname,revision,mycall,mygrid,dd,ntx30a,ntx30b,fcenter, &
nutc,ndop00,ndop58)
parameter(NMAX=60*96000)
character*120 fname
character*22 revision
character*12 mycall
character*6 mygrid
real*4 dd(2,NMAX)
real*8 fcenter
integer nxtra(15) !For possible future additions
integer*1,allocatable :: id1(:,:)
ia=1
ib=NMAX
if(ntx30a.gt.5) ia=NMAX/2+1
if(ntx30b.gt.5) ib=NMAX/2
sq=0.
do i=ia,ib
x=dd(1,i)
y=dd(2,i)
sq=sq + x*x + y*y
enddo
nsum=2*(ib-ia+1)
rms=sqrt(sq/nsum)
nbad=0
dmax=0.
fac0=10.0/rms
allocate(id1(1:2,1:NMAX))
do i=ia,ib
x=fac0*dd(1,i)
y=fac0*dd(2,i)
ax=abs(x)
ay=abs(y)
dmax=max(dmax,ax,ay)
if(ax.gt.127.0) then
x=0.
nbad=nbad+1
endif
if(ay.gt.127.0) then
y=0.
nbad=nbad+1
endif
id1(1,i)=nint(x)
id1(2,i)=nint(y)
enddo
if(ia.gt.30*96000) id1(1:2,1:ia-1)=0
if(ib.eq.30*96000) id1(1:2,ib+1:60*96000)=0
open(29,file=trim(fname),status='unknown',access='stream')
nxtra=0
write(29) revision//' ',mycall,mygrid,fcenter,nutc,ntx30a,ntx30b, &
ndop00,ndop58,ia,ib,fac0,nxtra !Write header to disk
write(29) id1(1:2,ia:ib) !Write 8-bit data to disk
close(29)
deallocate(id1)
return
end subroutine save_qm

View File

@ -8,7 +8,7 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
! pxdb power in x channel (0-60 dB)
! ssz5a polarized spectrum, for waterfall display
! nkhz integer kHz portion of center frequency, e.g., 125 for 144.125
! ihsym index number of this half-symbol (1-400)
! ihsym index number of this half-symbol (1-322)
! nzap number of samples zero'ed by noise blanker
include 'njunk.f90'
@ -16,9 +16,9 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
parameter (NFFT=32768) !Length of FFTs
real*8 ts,hsym
real*8 fcenter
common/datcom/dd(2,5760000),ss(400,NFFT),savg(NFFT),fcenter,nutc, &
common/datcom/dd(2,5760000),ss(322,NFFT),savg(NFFT),fcenter,nutc, &
junk(NJUNK)
real*4 ssz5a(NFFT),w(NFFT)
real*4 ssz5a(NFFT),w(NFFT),w2a(NFFT),w2b(NFFT)
complex cx(NFFT)
complex cx00(NFFT)
complex cx0(0:1023),cx1(0:1023)
@ -26,24 +26,31 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
data rms/999.0/,k0/99999999/,nadjx/0/,nadjy/0/
save
hsym=0.15d0*96000.d0 !Samples per Q65-30x half-symbol
npts=2*hsym !Full Q65-30x symbol
nfast=1
if(k.gt.5751000) go to 999
if(k.lt.npts) then
if(k.lt.NFFT) then
ihsym=0
go to 999 !Wait for enough samples to start
endif
if(k0.eq.99999999) then
! pi=4.0*atan(1.0)
! do i=1,NFFT
! w(i)=(sin(i*pi/NFFT))**2 !Window
! enddo
w=0.7 !Flat window
pi=4.0*atan(1.0)
w2a=0.
w2b=0.
do i=1,NFFT
w(i)=(sin(i*pi/NFFT))**2 !Window for nfast=1
if(i.lt.17833) w2a(i)=(sin(i*pi/17832.925))**2 !Window a for nfast=2
j=i-8916
if(j.gt.0 .and. j.lt.17833) w2b(i)=(sin(j*pi/17832.925))**2 ! b
enddo
w2a=sqrt(2.0)*w2a
w2b=sqrt(2.0)*w2b
endif
hsym=2048.d0*96000.d0/11025.d0 !Samples per JT65 half-symbol
if(nfsample.eq.95238) hsym=2048.d0*95238.1d0/11025.d0
if(k.lt.k0) then
ts=1.d0 - hsym
ss=0.
savg=0.
ihsym=0
k1=0
@ -78,9 +85,12 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
k1=k1+kstep
enddo
npts=NFFT !Samples used in each half-symbol FFT
ts=ts+hsym
ja=ts !Index of first sample
jb=ja+npts-1 !Last sample
i=0
fac=0.0002
do j=ja,jb !Copy data into cx
@ -89,12 +99,11 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
i=i+1
cx(i)=fac*cmplx(x1,x2)
enddo
cx(npts+1:)=0.
if(nzap/178.lt.50 .and. (ndiskdat.eq.0 .or. ihsym.lt.280)) then
nsum=nblks*kstep - nzap
if(nsum.le.0) nsum=1
rmsx=sqrt(px/nsum)
rmsx=sqrt(0.5*px/nsum)
rms=rmsx
endif
pxdb=0.
@ -103,21 +112,31 @@ subroutine symspec(k,ndiskdat,nb,nbslider,nfsample, &
cx00=cx
do mm=1,nfast
ihsym=ihsym+1
if(nfast.eq.1) then
cx=w*cx00 !Apply window for 2nd forward FFT
else
if(mm.eq.1) then
cx=w2a*cx00
else
cx=w2b*cx00
endif
endif
call four2a(cx,NFFT,1,1,1) !Second forward FFT (X)
n=min(400,ihsym)
n=min(322,ihsym)
do i=1,NFFT
sx=real(cx(i))**2 + aimag(cx(i))**2
ss(n,i)=sx ! Pol = 0
savg(i)=savg(i) + sx
ssz5a(i)=sx
enddo
enddo
nkhz=nint(1000.d0*(fcenter-int(fcenter)))
if(fcenter.eq.0.d0) nkhz=125
! write(*,3001) hsym,ts,ja,jb,ihsym
!3001 format(2f12.3,3i10)
999 return
end subroutine symspec

View File

@ -1,9 +0,0 @@
subroutine zaptx(dd,k0,k)
parameter(NMAX=60*96000)
real dd(2,NMAX)
dd(1:2,k0+1:k)=0.
return
end subroutine zaptx

View File

@ -16,7 +16,6 @@ extern "C" {
void _gfortran_set_args(int argc, char *argv[]);
void _gfortran_set_convert(int conv);
void ftninit_(void);
void fftbig_(float dd[], int* nfft);
}
int main(int argc, char *argv[])
@ -30,7 +29,7 @@ int main(int argc, char *argv[])
// Override programs executable basename as application name.
a.setApplicationName ("QMAP");
a.setApplicationVersion ("0.4");
a.setApplicationVersion ("0.2");
// switch off as we share an Info.plist file with WSJT-X
a.setAttribute (Qt::AA_DontUseNativeMenuBar);
MainWindow w;
@ -46,9 +45,9 @@ int main(int argc, char *argv[])
int iform {1};
// free FFT plan resources
four2a_ (nullptr, &nfft, &ndim, &isign, &iform, 0);
fftbig_(nullptr, &nfft);
}
fftwf_forget_wisdom ();
fftwf_cleanup ();
return result;
}

View File

@ -60,9 +60,8 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionQ65E->setActionGroup(modeGroup2);
QActionGroup* saveGroup = new QActionGroup(this);
ui->actionNone->setActionGroup(saveGroup);
ui->actionSave_all->setActionGroup(saveGroup);
ui->actionSave_decoded->setActionGroup(saveGroup);
ui->actionNone->setActionGroup(saveGroup);
setWindowTitle (program_title ());
@ -72,25 +71,27 @@ MainWindow::MainWindow(QWidget *parent) :
createStatusBar();
connect(m_gui_timer, &QTimer::timeout, this, &MainWindow::guiUpdate);
m_waterfallAvg=1;
m_network=true;
m_waterfallAvg = 1;
m_network = true;
m_restart=false;
m_myCall="K1JT";
m_myGrid="FN20qi";
m_myCallColor=0;
m_saveDir="";
m_azelDir="";
m_loopall=false;
m_startAnother=false;
m_saveAll=false;
m_saveDecoded=false;
m_onlyEME=false;
m_sec0=-1;
m_hsym0=-1;
m_palette="CuteSDR";
m_nutc0=9999;
m_kb8rq=false;
m_NB=false;
m_mode="Q65";
m_fs96000=true;
m_udpPort=50004;
m_nsave=0;
m_modeQ65=0;
m_TRperiod=60;
@ -109,7 +110,8 @@ MainWindow::MainWindow(QWidget *parent) :
memset(ipc_wsjtx,0,memSize); //Zero all of shared memory
mem_qmap.unlock();
// fftwf_import_wisdom_from_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
fftwf_import_wisdom_from_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
readSettings(); //Restore user's setup params
m_pbdecoding_style1="QPushButton{background-color: cyan; \
@ -132,6 +134,14 @@ MainWindow::MainWindow(QWidget *parent) :
if(m_modeQ65==4) on_actionQ65D_triggered();
if(m_modeQ65==5) on_actionQ65E_triggered();
future1 = new QFuture<void>;
watcher1 = new QFutureWatcher<void>;
connect(watcher1, SIGNAL(finished()),this,SLOT(diskDat()));
future2 = new QFuture<void>;
watcher2 = new QFutureWatcher<void>;
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
connect(&watcher3, SIGNAL(finished()),this,SLOT(decoderFinished()));
// Assign input device and start input thread
@ -149,8 +159,6 @@ MainWindow::MainWindow(QWidget *parent) :
m_wide_graph_window->setTol(m_tol);
m_wide_graph_window->setFcal(m_fCal);
m_wide_graph_window->setFsample(96000);
QString rev{"QMAP v" + QCoreApplication::applicationVersion() + " " + revision()};
m_revision=rev;
// Create "m_worked", a dictionary of all calls in wsjt.log
QFile f("wsjt.log");
@ -186,12 +194,14 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow()
{
writeSettings();
all_done_();
int itimer=1;
q65c_(&itimer);
if (soundInThread.isRunning()) {
soundInThread.quit();
soundInThread.wait(3000);
}
fftwf_export_wisdom_to_filename (QDir {m_appDir}.absoluteFilePath ("qmap_wisdom.dat").toLocal8Bit ());
delete ui;
}
@ -208,13 +218,15 @@ void MainWindow::writeSettings()
SettingsGroup g {&settings, "Common"};
settings.setValue("MyCall",m_myCall);
settings.setValue("MyGrid",m_myGrid);
settings.setValue("IDint",m_idInt);
settings.setValue("AstroFont",m_astroFont);
settings.setValue("MyCallColor",m_myCallColor);
settings.setValue("SaveDir",m_saveDir);
settings.setValue("AzElDir",m_azelDir);
settings.setValue("Timeout",m_timeout);
settings.setValue("Fcal",m_fCal);
settings.setValue("Fadd",m_fAdd);
settings.setValue("NetworkInput", m_network);
settings.setValue("FSam96000", m_fs96000);
settings.setValue("paInDevice",m_paInDevice);
settings.setValue("Scale_dB",m_dB);
settings.setValue("UDPport",m_udpPort);
@ -226,13 +238,15 @@ void MainWindow::writeSettings()
settings.setValue("nModeQ65",m_modeQ65);
settings.setValue("SaveNone",ui->actionNone->isChecked());
settings.setValue("SaveAll",ui->actionSave_all->isChecked());
settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
settings.setValue("ContinuousWaterfall",ui->continuous_waterfall->isChecked());
settings.setValue("NEME",m_onlyEME);
settings.setValue("KB8RQ",m_kb8rq);
settings.setValue("NB",m_NB);
settings.setValue("NBslider",m_NBslider);
settings.setValue("GainX",(double)m_gainx);
settings.setValue("GainY",(double)m_gainy);
settings.setValue("PhaseX",(double)m_phasex);
settings.setValue("PhaseY",(double)m_phasey);
settings.setValue("MaxDrift",ui->sbMaxDrift->value());
settings.setValue("Offset",ui->sbOffset->value());
settings.setValue("Also30",m_bAlso30);
}
//---------------------------------------------------------- readSettings()
@ -248,14 +262,16 @@ void MainWindow::readSettings()
SettingsGroup g {&settings, "Common"};
m_myCall=settings.value("MyCall","").toString();
m_myGrid=settings.value("MyGrid","").toString();
m_astroFont=settings.value("AstroFont",18).toInt();
m_myCallColor=settings.value("MyCallColor",1).toInt();
m_idInt=settings.value("IDint",0).toInt();
m_astroFont=settings.value("AstroFont",20).toInt();
m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString();
m_azelDir=settings.value("AzElDir",m_appDir).toString();
m_timeout=settings.value("Timeout",20).toInt();
m_fCal=settings.value("Fcal",0).toInt();
m_fAdd=settings.value("FAdd",0).toDouble();
soundInThread.setFadd(m_fAdd);
m_network = settings.value("NetworkInput",true).toBool();
m_fs96000 = settings.value("FSam96000",true).toBool();
m_dB = settings.value("Scale_dB",0).toInt();
m_udpPort = settings.value("UDPport",50004).toInt();
soundInThread.setScale(m_dB);
@ -265,7 +281,7 @@ void MainWindow::readSettings()
ui->actionLinrad->setChecked(settings.value(
"PaletteLinrad",false).toBool());
m_modeQ65=settings.value("nModeQ65",3).toInt();
m_modeQ65=settings.value("nModeQ65",2).toInt();
if(m_modeQ65==1) ui->actionQ65A->setChecked(true);
if(m_modeQ65==2) ui->actionQ65B->setChecked(true);
if(m_modeQ65==3) ui->actionQ65C->setChecked(true);
@ -274,29 +290,20 @@ void MainWindow::readSettings()
ui->actionNone->setChecked(settings.value("SaveNone",true).toBool());
ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool());
ui->actionSave_decoded->setChecked(settings.value("SaveDecoded",false).toBool());
ui->continuous_waterfall->setChecked(settings.value("ContinuousWaterfall",false).toBool());
m_saveAll=ui->actionSave_all->isChecked();
m_saveDecoded=ui->actionSave_decoded->isChecked();
if(m_saveAll) {
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save all");
} else if(m_saveDecoded) {
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save decoded");
} else {
lab5->setStyleSheet("");
lab5->setText("");
}
m_onlyEME=settings.value("NEME",false).toBool();
ui->actionOnly_EME_calls->setChecked(m_onlyEME);
m_kb8rq=settings.value("KB8RQ",false).toBool();
m_NB=settings.value("NB",false).toBool();
ui->NBcheckBox->setChecked(m_NB);
ui->sbMaxDrift->setValue(settings.value("MaxDrift",0).toInt());
ui->sbOffset->setValue(settings.value("Offset",1500).toInt());
m_NBslider=settings.value("NBslider",40).toInt();
ui->NBslider->setValue(m_NBslider);
m_bAlso30=settings.value("Also30",true).toBool();
ui->actionAlso_Q65_30x->setChecked(m_bAlso30);
on_actionAlso_Q65_30x_toggled(m_bAlso30);
m_gainx=settings.value("GainX",1.0).toFloat();
m_gainy=settings.value("GainY",1.0).toFloat();
m_phasex=settings.value("PhaseX",0.0).toFloat();
m_phasey=settings.value("PhaseY",0.0).toFloat();
if(!ui->actionLinrad->isChecked() && !ui->actionCuteSDR->isChecked() &&
!ui->actionAFMHot->isChecked() && !ui->actionBlue->isChecked()) {
on_actionLinrad_triggered();
@ -310,7 +317,6 @@ void MainWindow::dataSink(int k)
static float s[NFFT],splot[NFFT];
static int n=0;
static int ihsym=0;
static int ihsym0=0;
static int nzap=0;
static int ntrz=0;
static int nkhz;
@ -319,7 +325,6 @@ void MainWindow::dataSink(int k)
static int nsum=0;
static int ndiskdat;
static int nb;
static int k0=0;
static float px=0.0;
static uchar lstrong[1024];
static float slimit;
@ -336,10 +341,7 @@ void MainWindow::dataSink(int k)
nb=0;
if(m_NB) nb=1;
nfsample=96000;
if(m_bWTransmitting) zaptx_(datcom_.d4, &k0, &k);
k0=k;
if(!m_fs96000) nfsample=95238;
symspec_(&k, &ndiskdat, &nb, &m_NBslider, &nfsample,
&px, s, &nkhz, &ihsym, &nzap, &slimit, lstrong);
@ -355,7 +357,6 @@ void MainWindow::dataSink(int k)
}
nsec0=nsec;
if(m_bWTransmitting) px=0.0;
QString t;
m_pctZap=nzap/178.3;
@ -365,9 +366,9 @@ void MainWindow::dataSink(int k)
.arg (m_pctZap, 5, 'f', 1)
);
xSignalMeter->setValue(px); // Update the signal meter
xSignalMeter->setValue(px); // Update the signal meters
//Suppress scrolling if WSJT-X is transmitting
if((m_monitoring and (!m_bWTransmitting or ui->continuous_waterfall->isChecked())) or m_diskData) {
if((m_monitoring and ipc_wsjtx[4] != 1) or m_diskData) {
m_wide_graph_window->dataSink2(s,nkhz,ihsym,m_diskData,lstrong);
}
@ -398,26 +399,26 @@ void MainWindow::dataSink(int k)
n=0;
}
bool bCallDecoder=false;
if(ihsym < m_hsymStop) m_decode_called=false;
if(ihsym==m_hsymStop and !m_decode_called) bCallDecoder=true; //Decode at t=58.5 s
if(ihsym==130) bCallDecoder=true;
if(m_bAlso30 and (ihsym==200)) bCallDecoder=true;
if(ihsym==330) bCallDecoder=true;
if(ihsym==ihsym0) bCallDecoder=false;
ihsym0=ihsym;
if(bCallDecoder) {
if(ihsym==m_hsymStop) m_decode_called=true;
if(ihsym >= m_hsymStop and !m_decode_called) { //Decode at t=56 s (for Q65 and data from disk)
m_decode_called=true;
datcom_.newdat=1;
datcom_.nagain=0;
datcom_.nhsym=ihsym;
decode(); //Prepare to start the decoder
if(ihsym==m_hsymStop) {
m_nTx30a=0;
m_nTx30b=0;
m_nTx60=0;
QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yymmdd_hhmm");
decode(); //Start the decoder
if(m_saveAll and !m_diskData and m_nTransmitted<10) {
QString fname=m_saveDir + "/" + t.date().toString("yyMMdd") + "_" +
t.time().toString("hhmm");
fname += ".iq";
*future2 = QtConcurrent::run(savetf2, fname, false);
watcher2->setFuture(*future2);
}
m_nTransmitted=0;
}
soundInThread.m_dataSinkBusy=false;
}
@ -432,29 +433,33 @@ void MainWindow::on_actionSettings_triggered()
DevSetup dlg(this);
dlg.m_myCall=m_myCall;
dlg.m_myGrid=m_myGrid;
dlg.m_idInt=m_idInt;
dlg.m_astroFont=m_astroFont;
dlg.m_myCallColor=m_myCallColor;
dlg.m_saveDir=m_saveDir;
dlg.m_azelDir=m_azelDir;
dlg.m_timeout=m_timeout;
dlg.m_fCal=m_fCal;
dlg.m_fAdd=m_fAdd;
dlg.m_network=m_network;
dlg.m_fs96000=m_fs96000;
dlg.m_udpPort=m_udpPort;
dlg.m_dB=m_dB;
dlg.initDlg();
if(dlg.exec() == QDialog::Accepted) {
m_myCall=dlg.m_myCall;
m_myGrid=dlg.m_myGrid;
m_idInt=dlg.m_idInt;
m_astroFont=dlg.m_astroFont;
m_myCallColor=dlg.m_myCallColor;
if(m_astro_window && m_astro_window->isVisible()) m_astro_window->setFontSize(m_astroFont);
ui->actionFind_Delta_Phi->setEnabled(false);
m_saveDir=dlg.m_saveDir;
m_azelDir=dlg.m_azelDir;
m_timeout=dlg.m_timeout;
m_fCal=dlg.m_fCal;
m_fAdd=dlg.m_fAdd;
soundInThread.setFadd(m_fAdd);
m_wide_graph_window->setFcal(m_fCal);
m_fs96000=dlg.m_fs96000;
m_network=dlg.m_network;
m_udpPort=dlg.m_udpPort;
m_dB=dlg.m_dB;
@ -590,16 +595,9 @@ void MainWindow::createStatusBar() //createStatusBar
lab4 = new QLabel("");
lab4->setAlignment(Qt::AlignHCenter);
lab4->setMinimumSize(QSize(80,10));
lab4->setMinimumSize(QSize(50,10));
lab4->setFrameStyle(QFrame::Panel | QFrame::Sunken);
statusBar()->addWidget(lab4);
lab5 = new QLabel("");
lab5->setAlignment(Qt::AlignHCenter);
lab5->setMinimumSize(QSize(100,10));
lab5->setFrameStyle(QFrame::Panel | QFrame::Sunken);
lab5->setStyleSheet("");
statusBar()->addWidget(lab5);
}
void MainWindow::on_tolSpinBox_valueChanged(int i) //tolSpinBox
@ -646,11 +644,11 @@ void MainWindow::on_actionOpen_triggered() //Open File
soundInThread.setMonitoring(m_monitoring);
QString fname;
fname=QFileDialog::getOpenFileName(this, "Open File", m_path,
"MAP65/QMAP Files (*.iq *.qm)");
"MAP65/QMAP Files (*.iq)");
if(fname != "") {
m_path=fname;
int i;
i=qMax(fname.indexOf(".iq") - 11, fname.indexOf(".qm") - 11);
i=fname.indexOf(".iq") - 11;
if(i>=0) {
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
lab1->setText(" " + fname.mid(i,15) + " ");
@ -658,13 +656,9 @@ void MainWindow::on_actionOpen_triggered() //Open File
if(m_monitoring) on_monitorButton_clicked();
m_diskData=true;
int dbDgrd=0;
int iret=4;
if(m_path.indexOf(".iq")>0) {
getfile(fname, dbDgrd);
} else {
read_qm_(fname.toLatin1(), &iret, fname.length());
}
if(iret > 0) diskDat(iret);
if(m_myCall=="K1JT" and m_idInt<0) dbDgrd=m_idInt;
*future1 = QtConcurrent::run(getfile, fname, false, dbDgrd);
watcher1->setFuture(*future1);
}
}
@ -673,11 +667,7 @@ void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
int i,len;
QFileInfo fi(m_path);
QStringList list;
if(m_path.indexOf(".iq")>0) {
list= fi.dir().entryList().filter(".iq");
} else {
list= fi.dir().entryList().filter(".qm");
}
for (i = 0; i < list.size()-1; ++i) {
if(i==list.size()-2) m_loopall=false;
len=list.at(i).length();
@ -686,20 +676,16 @@ void MainWindow::on_actionOpen_next_in_directory_triggered() //Open Next
QString fname=m_path.replace(n-len,len,list.at(i+1));
m_path=fname;
int i;
i=qMax(fname.indexOf(".iq") - 11, fname.indexOf(".qm") - 11);
i=fname.indexOf(".iq") - 11;
if(i>=0) {
lab1->setStyleSheet("QLabel{background-color: #66ff66}");
lab1->setText(" " + fname.mid(i,len) + " ");
}
m_diskData=true;
int dbDgrd=0;
int iret=4;
if(m_path.indexOf(".iq")>0) {
getfile(fname, dbDgrd);
} else {
read_qm_(fname.toLatin1(), &iret, fname.length());
}
if(iret > 0) diskDat(iret);
if(m_myCall=="K1JT" and m_idInt<0) dbDgrd=m_idInt;
*future1 = QtConcurrent::run(getfile, fname, false, dbDgrd);
watcher1->setFuture(*future1);
return;
}
}
@ -711,54 +697,41 @@ void MainWindow::on_actionDecode_remaining_files_in_directory_triggered()
on_actionOpen_next_in_directory_triggered();
}
void MainWindow::diskDat(int iret) //diskDat()
void MainWindow::diskDat() //diskDat()
{
int ia=0;
int ib=400;
if(iret==1) ib=202;
m_bDiskDatBusy=true;
double hsym;
//These may be redundant??
m_diskData=true;
datcom_.newdat=1;
m_nTx30a=datcom_.ntx30a;
m_nTx30b=datcom_.ntx30b;
hsym=0.15*96000.0; //Samples per Q65-30x half-symbol or Q65-60x quarter-symbol
for(int i=ia; i<ib; i++) { // Do the half-symbol FFTs
int k = i*hsym + 0.5;
if(k > 60*96000) break;
hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol
for(int i=0; i<304; i++) { // Do the half-symbol FFTs
int k = i*hsym + 2048.5;
dataSink(k);
qApp->processEvents(); // Allow the waterfall to update
while(m_decoderBusy) {
qApp->processEvents(); // Wait for an early decode to finish
}
}
m_bDiskDatBusy=false;
}
void MainWindow::decoderFinished()
void MainWindow::diskWriteFinished() //diskWriteFinished
{
// qDebug() << "diskWriteFinished";
}
void MainWindow::decoderFinished() //diskWriteFinished
{
m_startAnother=m_loopall;
ui->DecodeButton->setStyleSheet("");
decodeBusy(false);
decodes_.nQDecoderDone=1;
decodes_.kHzRequested=0;
if(m_diskData) decodes_.nQDecoderDone=2;
mem_qmap.lock();
decodes_.nWDecoderBusy=ipc_wsjtx[3]; //Prevent overwriting values
decodes_.nWTransmitting=ipc_wsjtx[4]; //written here by WSJT-X
m_bWTransmitting=decodes_.nWTransmitting>0;
memcpy((char*)ipc_wsjtx, &decodes_, sizeof(decodes_)); //Send decodes and flags to WSJT-X
mem_qmap.unlock();
QString t1;
t1=t1.asprintf(" %.1f s %d/%d ", 0.15*datcom2_.nhsym, decodes_.ndecodes, decodes_.ncand);
t1=t1.asprintf(" %d ",decodes_.ndecodes);
lab4->setText(t1);
decodeBusy(false);
if(m_bDecodeAgain) {
datcom_.nhsym=390;
datcom_.nagain=1;
m_bDecodeAgain=false;
decode();
}
QDateTime now=QDateTime::currentDateTimeUtc();
}
void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
@ -766,7 +739,7 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
int i;
QString fname;
int ret = QMessageBox::warning(this, "Confirm Delete",
"Are you sure you want to delete all *.iq and *.qm files in\n" +
"Are you sure you want to delete all *.iq files in\n" +
QDir::toNativeSeparators(m_saveDir) + " ?",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if(ret==QMessageBox::Yes) {
@ -777,8 +750,6 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
fname=*f;
i=(fname.indexOf(".iq"));
if(i==11) dir.remove(fname);
i=(fname.indexOf(".qm"));
if(i==11) dir.remove(fname);
}
}
}
@ -786,25 +757,13 @@ void MainWindow::on_actionDelete_all_iq_files_in_SaveDir_triggered()
void MainWindow::on_actionNone_triggered() //Save None
{
m_saveAll=false;
m_saveDecoded=false;
lab5->setStyleSheet("");
lab5->setText("");
}
void MainWindow::on_actionSave_decoded_triggered()
{
m_saveDecoded=true;
m_saveAll=false;
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save decoded");
}
// ### Implement "Save Last" here? ###
void MainWindow::on_actionSave_all_triggered()
void MainWindow::on_actionSave_all_triggered() //Save All
{
m_saveAll=true;
m_saveDecoded=false;
lab5->setStyleSheet("QLabel{background-color: #ffff00}");
lab5->setText("Save all");
}
void MainWindow::on_DecodeButton_clicked() //Decode request
@ -812,23 +771,12 @@ void MainWindow::on_DecodeButton_clicked() //Decode request
if(!m_decoderBusy) {
datcom_.newdat=0;
datcom_.nagain=1;
if(m_bAlso30 and m_nTx30a<5) {
datcom_.nhsym=200; //Decode the first half-minute
if(m_nTx30b<5) m_bDecodeAgain=true; //Queue up decoding of the seciond half minute
}
decode();
}
}
void MainWindow::freezeDecode(int n) //freezeDecode()
{
if(n==3) {
decodes_.kHzRequested=m_wide_graph_window->QSOfreq();
mem_qmap.lock();
ipc_wsjtx[5]=decodes_.kHzRequested;
mem_qmap.unlock();
return;
}
if(n==2) {
ui->tolSpinBox->setValue(5);
datcom_.ntol=m_tol;
@ -841,17 +789,17 @@ void MainWindow::freezeDecode(int n) //freezeDecode()
if(!m_decoderBusy) {
datcom_.nagain=1;
datcom_.newdat=0;
on_DecodeButton_clicked();
decode();
}
}
void MainWindow::decode() //decode()
{
if(m_decoderBusy) {
return; //Don't attempt decode if decoder already busy
}
decodeBusy(true);
//Don't attempt to decode if decoder is already busy, or if we transmitted for 10 s or more.
if(m_decoderBusy or m_nTransmitted>10) return;
QString fname=" ";
ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
if(datcom_.nagain==0 && (!m_diskData)) {
qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000;
int imin=ms/60000;
@ -866,11 +814,24 @@ void MainWindow::decode() //decode()
datcom_.ndiskdat=0;
if(m_diskData) {
datcom_.ndiskdat=1;
int i0=qMax(m_path.indexOf(".iq"),m_path.indexOf(".qm"));
int 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_.ndop00=ndop00; //Send self Doppler to decoder, via datcom
fname=m_path.mid(i0-11,11);
}
}
datcom_.neme=0;
if(ui->actionOnly_EME_calls->isChecked()) datcom_.neme=1;
int ispan=int(m_wide_graph_window->fSpan());
if(ispan%2 == 1) ispan++;
@ -883,12 +844,19 @@ void MainWindow::decode() //decode()
datcom_.nfb=nfb;
datcom_.nfcal=m_fCal;
datcom_.nfshift=nfshift;
datcom_.mcall3=0;
if(m_call3Modified) datcom_.mcall3=1;
datcom_.ntimeout=m_timeout;
datcom_.ntol=m_tol;
datcom_.nxant=0;
m_nutc0=datcom_.nutc;
datcom_.junk_1=0;
datcom_.nfsample=96000;
datcom_.nBaseSubmode=m_modeQ65;
if(!m_fs96000) datcom_.nfsample=95238;
datcom_.nxpol=0;
datcom_.nmode=10*m_modeQ65;
datcom_.nsave=m_nsave;
datcom_.max_drift=ui->sbMaxDrift->value();
datcom_.offset=ui->sbOffset->value();
datcom_.ndepth=1;
if(datcom_.nagain==1) datcom_.ndepth=3;
@ -902,64 +870,24 @@ void MainWindow::decode() //decode()
} else {
memcpy(datcom_.datetime, m_dateTime.toLatin1(), 11);
}
datcom_.ntx30a=m_nTx30a;
datcom_.ntx30b=m_nTx30b;
datcom_.ntx60=m_nTx60;
datcom_.nsave=0;
if(m_saveDecoded) datcom_.nsave=1;
if(m_saveAll) datcom_.nsave=2;
datcom_.n60=m_n60;
datcom_.junk1=1234; //Check for these values in m65
datcom_.junk1=1234; //Cecck for these values in m65
datcom_.junk2=5678;
datcom_.bAlso30=m_bAlso30;
datcom_.ndop00=m_dop00;
datcom_.ndop58=m_dop58;
char *to = (char*) datcom2_.d4;
char *from = (char*) datcom_.d4;
memcpy(to, from, sizeof(datcom_)); //Copy the full datcom_ common block into datcom2_
memcpy(to, from, sizeof(datcom_));
datcom_.nagain=0;
datcom_.ndiskdat=0;
m_call3Modified=false;
if((!m_bAlso30 and (datcom2_.nhsym==330)) or (m_bAlso30 and (datcom2_.nhsym==130))) {
decodes_.ndecodes=0; //Start the decode cycle with a clean slate
m_fetched=0;
}
decodes_.ndecodes=0;
decodes_.ncand=0;
decodes_.nQDecoderDone=0;
m_fetched=0;
int itimer=0;
m_decoder_start_time=QDateTime::currentDateTimeUtc();
watcher3.setFuture(QtConcurrent::run (std::bind (q65c_, &itimer)));
m_saveFileName="NoSave";
if(!m_diskData) {
QDateTime t = QDateTime::currentDateTimeUtc();
m_dateTime=t.toString("yyMMdd_hhmm");
QDir dir(m_saveDir);
if (!dir.exists()) dir.mkpath(".");
m_saveFileName=m_saveDir + "/" + m_dateTime + ".qm";
}
bool bSkipDecode=false;
//No need to call decoder for first half, if we transmitted in the first half:
if((datcom2_.nhsym<=200) and (m_nTx30a>5)) bSkipDecode=true;
//No need to call decoder at 330, if we transmitted in 2nd half:
if((datcom2_.nhsym==330) and (m_nTx30b>5)) bSkipDecode=true;
//No need to call decoder at all, if we transmitted in a 60 s submode.
if(m_nTx60>5) bSkipDecode=true;
if(bSkipDecode) {
decodeBusy(false);
return;
}
int len1=m_saveFileName.length();
int len2=m_revision.length();
memcpy(savecom_.revision, m_revision.toLatin1(), len2);
memcpy(savecom_.saveFileName, m_saveFileName.toLatin1(),len1);
ui->actionExport_wav_file_at_fQSO->setEnabled(m_diskData);
watcher3.setFuture(QtConcurrent::run (q65c_));
decodeBusy(true);
}
@ -967,7 +895,6 @@ void MainWindow::on_EraseButton_clicked()
{
ui->decodedTextBrowser->clear();
lab4->clear();
m_nline=0;
}
@ -975,8 +902,6 @@ void MainWindow::decodeBusy(bool b) //decodeBusy()
{
m_decoderBusy=b;
ui->DecodeButton->setEnabled(!b);
if(!b) ui->DecodeButton->setStyleSheet("");
if(b) ui->DecodeButton->setStyleSheet(m_pbdecoding_style1);
ui->actionOpen->setEnabled(!b);
ui->actionOpen_next_in_directory->setEnabled(!b);
ui->actionDecode_remaining_files_in_directory->setEnabled(!b);
@ -998,7 +923,7 @@ void MainWindow::guiUpdate()
m_wide_graph_window->updateFreqLabel();
if(m_startAnother and !m_bDiskDatBusy) {
if(m_startAnother) {
m_startAnother=false;
on_actionOpen_next_in_directory_triggered();
}
@ -1009,59 +934,30 @@ void MainWindow::guiUpdate()
QString t=QString::fromLatin1(decodes_.result[m_fetched]);
if(m_UTC0!="" and m_UTC0!=t.left(4)) {
t1="-";
ui->decodedTextBrowser->append(t1.repeated(60));
m_nline++;
QTextCursor cursor(ui->decodedTextBrowser->document()->findBlockByLineNumber(m_nline-1));
QTextBlockFormat f = cursor.blockFormat();
f.setBackground(QBrush(Qt::white));
cursor.setBlockFormat(f);
ui->decodedTextBrowser->append(t1.repeated(56));
}
m_UTC0=t.left(4);
t=t.trimmed();
ui->decodedTextBrowser->append(t);
ui->decodedTextBrowser->append(t.trimmed());
m_fetched++;
m_nline++;
QTextCursor cursor(ui->decodedTextBrowser->document()->findBlockByLineNumber(m_nline-1));
QTextBlockFormat f = cursor.blockFormat();
f.setBackground(QBrush(Qt::white));
if(t.mid(36,2)=="30") f.setBackground(QBrush(Qt::yellow));
if(t.indexOf(m_myCall)>10 and m_myCallColor==1) f.setBackground(QColor(255,102,102));
if(t.indexOf(m_myCall)>10 and m_myCallColor==2) f.setBackground(QBrush(Qt::green));
if(t.indexOf(m_myCall)>10 and m_myCallColor==3) f.setBackground(QBrush(Qt::cyan));
cursor.setBlockFormat(f);
}
}
t1="";
t1=t1.asprintf("%.3f",datcom_.fcenter);
ui->labFreq->setText(t1);
if(nsec != m_sec0) { //Once per second
// qDebug() << "AAA" << nsec << m_fAdd;
static int n60z=99;
m_n60=nsec%60;
// See if WSJT-X is transmitting
int n60=nsec%60;
int itest[5];
mem_qmap.lock();
memcpy(&itest, (char*)ipc_wsjtx, 20);
mem_qmap.unlock();
if(itest[4]>0) {
m_WSJTX_TRperiod=itest[4];
m_bWTransmitting=true;
if(m_WSJTX_TRperiod==30 and m_n60<30) m_nTx30a++;
if(m_WSJTX_TRperiod==30 and m_n60>=30) m_nTx30b++;
if(m_WSJTX_TRperiod==60) m_nTx60++;
} else {
m_bWTransmitting=false;
}
if((m_n60<n60z) and !m_diskData) {
m_nTx30a=0;
m_nTx30b=0;
m_nTx60=0;
}
n60z=m_n60;
if(itest[4]==1) m_nTransmitted++;
// qDebug() << "AAA" << n60 << itest[0] << itest[1] << itest[2] << itest[3] << itest[4]
// << m_nTransmitted;
if(n60<n60z) m_nTransmitted=0;
n60z=n60;
if(m_pctZap>30.0) {
lab2->setStyleSheet("QLabel{background-color: #ff0000}");
@ -1069,7 +965,8 @@ void MainWindow::guiUpdate()
lab2->setStyleSheet("");
}
if(m_monitoring and !m_bWTransmitting) {
if(m_monitoring) {
lab1->setStyleSheet("QLabel{background-color: #00ff00}");
m_nrx=soundInThread.nrx();
khsym=soundInThread.mhsym();
@ -1088,30 +985,26 @@ void MainWindow::guiUpdate()
lab1->setStyleSheet("QLabel{background-color: #ffc0cb}");
}
lab1->setText("Receiving " + t);
} else if(m_bWTransmitting) {
lab1->setStyleSheet("QLabel{background-color: #ffff00}"); //Yellow
lab1->setText("WSJT-X Transmitting");
} else if(!m_diskData) {
} else if (!m_diskData) {
lab1->setStyleSheet("");
lab1->setText("");
}
datcom_.mousefqso=m_wide_graph_window->QSOfreq();
QDateTime t = QDateTime::currentDateTimeUtc();
m_astro_window->astroUpdate(t, m_myGrid, m_azelDir, m_xavg);
int fQSO=m_wide_graph_window->QSOfreq();
m_astro_window->astroUpdate(t, m_myGrid, m_hisGrid, fQSO, m_setftx,
m_txFreq, m_azelDir, m_xavg);
m_setftx=0;
QString utc = t.date().toString(" yyyy MMM dd \n") + t.time().toString();
ui->labUTC->setText(utc);
m_hsym0=khsym;
m_sec0=nsec;
if(m_n60==0) m_dop00=datcom_.ndop00;
if(m_n60==58) m_dop58=datcom_.ndop00;
}
}
void MainWindow::on_actionQ65A_triggered()
{
m_modeQ65=1;
ui->actionAlso_Q65_30x->setText("Also Q65-30A");
lab3->setStyleSheet("QLabel{background-color: #ffb266}");
lab3->setText("Q65-60A");
}
@ -1119,7 +1012,6 @@ void MainWindow::on_actionQ65A_triggered()
void MainWindow::on_actionQ65B_triggered()
{
m_modeQ65=2;
ui->actionAlso_Q65_30x->setText("Also Q65-30A");
lab3->setStyleSheet("QLabel{background-color: #b2ff66}");
lab3->setText("Q65-60B");
}
@ -1127,7 +1019,6 @@ void MainWindow::on_actionQ65B_triggered()
void MainWindow::on_actionQ65C_triggered()
{
m_modeQ65=3;
ui->actionAlso_Q65_30x->setText("Also Q65-30B");
lab3->setStyleSheet("QLabel{background-color: #66ffff}");
lab3->setText("Q65-60C");
}
@ -1135,15 +1026,13 @@ void MainWindow::on_actionQ65C_triggered()
void MainWindow::on_actionQ65D_triggered()
{
m_modeQ65=4;
ui->actionAlso_Q65_30x->setText("Also Q65-30C");
lab3->setStyleSheet("QLabel{background-color: #d9b3ff}");
lab3->setStyleSheet("QLabel{background-color: #b266ff}");
lab3->setText("Q65-60D");
}
void MainWindow::on_actionQ65E_triggered()
{
m_modeQ65=5;
ui->actionAlso_Q65_30x->setText("Also Q65-30D");
lab3->setStyleSheet("QLabel{background-color: #ff66ff}");
lab3->setText("Q65-60E");
}
@ -1180,35 +1069,3 @@ void MainWindow::on_actionQuick_Start_Guide_to_WSJT_X_2_7_and_QMAP_triggered()
QDesktopServices::openUrl (QUrl {"https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf"});
}
void MainWindow::on_actionAlso_Q65_30x_toggled(bool b)
{
m_bAlso30=b;
}
void MainWindow::on_sbMaxDrift_valueChanged(int n)
{
if(n==0) ui->sbMaxDrift->setStyleSheet("");
if(n==5) ui->sbMaxDrift->setStyleSheet("QSpinBox { background-color: #ffff82; }");
if(n>=10) ui->sbMaxDrift->setStyleSheet("QSpinBox { background-color: #ffff00; }");
}
void MainWindow::on_actionExport_wav_file_at_fQSO_triggered()
{
datcom_.newdat=0;
datcom_.nagain=2;
decode();
}
void MainWindow::on_actionExport_wav_file_at_fQSO_30a_triggered()
{
datcom_.newdat=0;
datcom_.nagain=3;
decode();
}
void MainWindow::on_actionExport_wav_file_at_fQSO_30b_triggered()
{
datcom_.newdat=0;
datcom_.nagain=4;
decode();}

View File

@ -39,7 +39,8 @@ public slots:
void showSoundInError(const QString& errorMsg);
void showStatusMessage(const QString& statusMsg);
void dataSink(int k);
void diskDat(int iret);
void diskDat();
void diskWriteFinished();
void decoderFinished();
void freezeDecode(int n);
void guiUpdate();
@ -81,14 +82,6 @@ private slots:
void on_actionQ65E_triggered();
void on_actionQuick_Start_Guide_to_Q65_triggered();
void on_actionQuick_Start_Guide_to_WSJT_X_2_7_and_QMAP_triggered();
void on_actionAlso_Q65_30x_toggled(bool b);
void on_sbMaxDrift_valueChanged(int arg1);
void on_actionSave_decoded_triggered();
void on_actionExport_wav_file_at_fQSO_triggered();
void on_actionExport_wav_file_at_fQSO_30a_triggered();
void on_actionExport_wav_file_at_fQSO_30b_triggered();
private:
Ui::MainWindow *ui;
@ -97,11 +90,16 @@ private:
QScopedPointer<Astro> m_astro_window;
QScopedPointer<WideGraph> m_wide_graph_window;
QPointer<QTimer> m_gui_timer;
qint32 m_idInt;
qint32 m_waterfallAvg;
qint32 m_DF;
qint32 m_tol;
qint32 m_QSOfreq0;
qint32 m_astroFont;
qint32 m_timeout;
qint32 m_fCal;
qint32 m_txFreq;
qint32 m_setftx;
qint32 m_sec0;
qint32 m_nutc0;
qint32 m_nrx;
@ -109,20 +107,15 @@ private:
qint32 m_paInDevice;
qint32 m_udpPort;
qint32 m_NBslider;
qint32 m_nsum;
qint32 m_nsave;
qint32 m_TRperiod;
qint32 m_modeQ65;
qint32 m_dB;
qint32 m_fetched=0;
qint32 m_hsymStop=390; //390*0.15 = 58.5 s
qint32 m_nTx30a=0;
qint32 m_nTx30b=0;
qint32 m_nTx60=0;
qint32 m_hsymStop=302;
qint32 m_nTransmitted=0;
qint32 m_nDoubleClicked=0;
qint32 m_nline=0;
qint32 m_WSJTX_TRperiod=0;
qint32 m_dop00=0;
qint32 m_dop58=0;
qint32 m_n60;
double m_fAdd;
double m_xavg;
@ -132,20 +125,21 @@ private:
bool m_loopall;
bool m_decoderBusy=false;
bool m_restart;
bool m_call3Modified;
bool m_startAnother;
bool m_saveAll;
bool m_saveDecoded;
bool m_onlyEME;
bool m_kb8rq;
bool m_NB;
bool m_fs96000;
bool m_decode_called=false;
bool m_bAlso30=true;
bool m_bDiskDatBusy=false;
bool m_bWTransmitting=false;
bool m_bDecodeAgain=false;
float m_gainx;
float m_gainy;
float m_phasex;
float m_phasey;
float m_pctZap;
int m_myCallColor;
QRect m_wideGraphGeom;
QLabel* lab1; // labels in status bar
@ -158,8 +152,15 @@ private:
QMessageBox msgBox0;
QFuture<void>* future1;
QFuture<void>* future2;
QFutureWatcher<void>* watcher1;
QFutureWatcher<void>* watcher2;
QFutureWatcher<void> watcher3; //For decoder
QDateTime m_decoder_start_time;
QString m_path;
QString m_pbdecoding_style1;
QString m_pbmonitor_style;
@ -174,12 +175,13 @@ private:
QString m_dateTime;
QString m_mode;
QString m_UTC0="";
QString m_revision;
QString m_saveFileName;
QDateTime m_dateTimeSeqStart; //Nominal start time of Rx sequence about to be decoded
QHash<QString,bool> m_worked;
SignalMeter *xSignalMeter;
SignalMeter *ySignalMeter;
SoundInThread soundInThread; //Instantiate the audio threads
//---------------------------------------------------- private functions
@ -192,7 +194,7 @@ private:
};
extern void getfile(QString fname, bool xpol, int idInt);
extern void save_iq(QString fname);
extern void savetf2(QString fname, bool xpol);
extern int killbyname(const char* progName);
extern "C" {
@ -204,18 +206,7 @@ extern "C" {
void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
const char* mygrid, int* ndop00, int len1);
void q65c_();
void all_done_();
void zaptx_(float d4[], int* k0, int* k);
void save_qm_(const char* fname, const char* prog_id, const char* mycall, const char* mygrid,
float d4[], int* ntx30a, int* ntx30b, double* fcenter, int* nutc,
int* dop00, int* dop58, int len1, int len2, int len3, int len4);
void read_qm_(const char* fname, int* iret, int len);
void q65c_(int* itimer);
}
#endif // MAINWINDOW_H

View File

@ -24,8 +24,8 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
<width>640</width>
<height>1080</height>
</size>
</property>
<property name="windowTitle">
@ -40,8 +40,8 @@
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="5">
<widget class="QPushButton" name="DecodeButton">
<item row="0" column="3" colspan="2">
<widget class="QPushButton" name="EraseButton">
<property name="minimumSize">
<size>
<width>50</width>
@ -49,7 +49,26 @@
</size>
</property>
<property name="text">
<string>&amp;Decode</string>
<string>&amp;Erase</string>
</property>
</widget>
</item>
<item row="1" column="4" colspan="2">
<widget class="QSpinBox" name="sbMaxDrift">
<property name="toolTip">
<string>Maximum drift rate in units of symbol rate per transmissiion.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Drift </string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
</widget>
</item>
@ -77,34 +96,95 @@
</property>
</widget>
</item>
<item row="3" column="4" colspan="2">
<widget class="QSlider" name="NBslider">
<property name="enabled">
<bool>false</bool>
<item row="0" column="5">
<widget class="QPushButton" name="DecodeButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&amp;Decode</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QCheckBox" name="NBcheckBox">
<property name="text">
<string>NB</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QLabel" name="labUTC">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>165</width>
<height>60</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="text">
<string> 2023 Feb 02
01:23:45 </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QFrame" name="xMeterFrame">
<property name="minimumSize">
<size>
<width>50</width>
<height>150</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="monitorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>40</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="text">
<string>&amp;Monitor</string>
</property>
</widget>
</item>
@ -194,141 +274,33 @@
</layout>
</item>
<item row="2" column="4" colspan="2">
<widget class="QSpinBox" name="sbOffset">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select offset announced by calling station, or use commonly used value for the band in use. Manually set WSJT-X TX and RX offset to same value.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<widget class="QSlider" name="NBslider">
<property name="enabled">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="suffix">
<string> Hz</string>
</property>
<property name="prefix">
<string>Offset </string>
</property>
<property name="minimum">
<number>500</number>
</property>
<property name="maximum">
<number>2000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1500</number>
</property>
</widget>
</item>
<item row="0" column="3" colspan="2">
<widget class="QPushButton" name="EraseButton">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&amp;Erase</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4">
<widget class="QFrame" name="xMeterFrame">
<property name="minimumSize">
<size>
<width>50</width>
<height>150</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="3">
<widget class="QLabel" name="labUTC">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>165</width>
<height>60</height>
</size>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="text">
<string> 2023 Feb 02
01:23:45 </string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="monitorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Monitor</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QCheckBox" name="NBcheckBox">
<property name="text">
<string>NB</string>
</property>
</widget>
</item>
<item row="1" column="4" colspan="2">
<widget class="QSpinBox" name="sbMaxDrift">
<property name="toolTip">
<string>Maximum drift rate in units of symbol rate per transmission.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Drift </string>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>50</number>
<number>100</number>
</property>
<property name="singleStep">
<number>5</number>
<property name="value">
<number>40</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@ -337,7 +309,7 @@
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
@ -350,31 +322,31 @@
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>620</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string> UTC Frx Fsked DT dB Q65- Message</string>
<string> UTC Frx Fsked DT dB Message</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0" colspan="2">
<widget class="DisplayText" name="decodedTextBrowser">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
<width>500</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>610</width>
<height>16777215</height>
</size>
</property>
@ -398,8 +370,9 @@
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@ -421,7 +394,7 @@ p, li { white-space: pre-wrap; }
<x>0</x>
<y>0</y>
<width>640</width>
<height>21</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -434,9 +407,6 @@ p, li { white-space: pre-wrap; }
<addaction name="separator"/>
<addaction name="actionDelete_all_iq_files_in_SaveDir"/>
<addaction name="separator"/>
<addaction name="actionExport_wav_file_at_fQSO"/>
<addaction name="actionExport_wav_file_at_fQSO_30a"/>
<addaction name="actionExport_wav_file_at_fQSO_30b"/>
<addaction name="actionSettings"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
@ -456,15 +426,12 @@ p, li { white-space: pre-wrap; }
<addaction name="actionWide_Waterfall"/>
<addaction name="separator"/>
<addaction name="menuWaterfall_palette"/>
<addaction name="separator"/>
<addaction name="continuous_waterfall"/>
</widget>
<widget class="QMenu" name="menuSave">
<property name="title">
<string>Save</string>
</property>
<addaction name="actionNone"/>
<addaction name="actionSave_decoded"/>
<addaction name="actionSave_all"/>
</widget>
<widget class="QMenu" name="menuHelp">
@ -486,8 +453,6 @@ p, li { white-space: pre-wrap; }
<addaction name="actionQ65C"/>
<addaction name="actionQ65D"/>
<addaction name="actionQ65E"/>
<addaction name="separator"/>
<addaction name="actionAlso_Q65_30x"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
@ -511,7 +476,7 @@ p, li { white-space: pre-wrap; }
</action>
<action name="actionAbout">
<property name="text">
<string>About QMAP</string>
<string> About QMAP</string>
</property>
<property name="shortcut">
<string>Ctrl+F1</string>
@ -563,7 +528,7 @@ p, li { white-space: pre-wrap; }
</action>
<action name="actionDelete_all_iq_files_in_SaveDir">
<property name="text">
<string>Delete all *.iq and *.qm files in SaveDir</string>
<string>Delete all *.iq files in SaveDir</string>
</property>
</action>
<action name="actionErase_Band_Map_and_Messages">
@ -765,7 +730,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65-60A</string>
<string>Q65A</string>
</property>
</action>
<action name="actionQ65B">
@ -773,7 +738,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65-60B</string>
<string>Q65B</string>
</property>
</action>
<action name="actionQ65C">
@ -784,7 +749,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65-60C</string>
<string>Q65C</string>
</property>
</action>
<action name="actionQ65D">
@ -792,7 +757,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65-60D</string>
<string>Q65D</string>
</property>
</action>
<action name="actionQ65E">
@ -800,7 +765,7 @@ p, li { white-space: pre-wrap; }
<bool>true</bool>
</property>
<property name="text">
<string>Q65-60E</string>
<string>Q65E</string>
</property>
</action>
<action name="actionQSG_Q65">
@ -808,6 +773,16 @@ p, li { white-space: pre-wrap; }
<string>Quick-Start Guide to Q65</string>
</property>
</action>
<action name="actionQSG_MAP65_v3">
<property name="text">
<string>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</string>
</property>
</action>
<action name="actionQ65_Sensitivity_in_MAP65_3_0">
<property name="text">
<string>Q65 Sensitivity in MAP65 3.0</string>
</property>
</action>
<action name="actionRelease_Notes">
<property name="text">
<string>Release Notes</string>
@ -831,48 +806,6 @@ p, li { white-space: pre-wrap; }
<string>Quick-Start Guide to Q65</string>
</property>
</action>
<action name="continuous_waterfall">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Continuous Waterfall</string>
</property>
</action>
<action name="actionAlso_Q65_30x">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Also Q65-30x</string>
</property>
</action>
<action name="actionSave_decoded">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Save decoded</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO">
<property name="text">
<string>Export .wav file at fQSO (60 s)</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO_30b">
<property name="text">
<string>Export .wav file at fQSO (30 s, second part)</string>
</property>
</action>
<action name="actionExport_wav_file_at_fQSO_30a">
<property name="text">
<string>Export .wav file at fQSO (30 s, first part)</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
@ -891,8 +824,8 @@ p, li { white-space: pre-wrap; }
<slot>update()</slot>
<hints>
<hint type="sourcelabel">
<x>287</x>
<y>281</y>
<x>269</x>
<y>255</y>
</hint>
<hint type="destinationlabel">
<x>126</x>

View File

@ -602,7 +602,6 @@ void CPlotter::mousePressEvent(QMouseEvent *event) //mousePressEvent
if(y < h+30) { // Wideband waterfall
if(button==1) {
setFQSO(x,false);
if(event->modifiers() & Qt::ControlModifier) emit freezeDecode1(3);
}
if(button==2 and !m_bLockTxRx) {
if(x<0) x=0; // x is pixel number

View File

@ -15,43 +15,37 @@ extern "C"
struct
{
double d8[60*96000]; //This is "common/datcom/..." in fortran
float ss[400*NFFT];
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 ss[322*NFFT];
float savg[NFFT];
double fcenter;
int nutc;
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 ndiskdat; //1 ==> data read from *.tf2 or *.iq file
int neme; //Hinted decoding tries only for EME calls
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 mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntol; //+/- decoding range around fQSO (Hz)
int junk5; //
int junk4; //
int nxant; //1 ==> add 45 deg to measured pol angle
int junk_1; //Flags to control log files
int nfsample; //Input sample rate
int junk3; //
int nBaseSubmode; //Base submode for Q65-60x (aka m_modeQ65)
int ndop00; //EME Self Doppler
int nxpol; //1 if using xpol antennas, 0 otherwise
int mode65; //JT65 sub-mode: A=1, B=2, C=4
int nfast; //1No longer used
int nsave; //Number of s3(64,63) spectra saved
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_;
}
@ -214,10 +208,12 @@ void SoundInThread::inputUDP()
// If buffer will not overflow, move data into datcom_
if ((k+iz) <= 60*96000) {
int nsam=-1;
recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8, &m_dB);
recvpkt_(&nsam, &b.iblk, &b.nrx, &k, b.d8, b.d8);
datcom_.fcenter=b.cfreq + m_fAdd;
// qDebug() << "bb" << b.cfreq << m_fAdd << datcom_.fcenter;
}
m_hsym=(k-2048)/14400; //14400 = 0.15 * 96000
m_hsym=(k-2048)*11025.0/(2048.0*m_rate);
if(m_hsym != nhsym0) {
if(!m_dataSinkBusy) {
m_dataSinkBusy=true;

View File

@ -67,8 +67,7 @@ private:
};
extern "C" {
void recvpkt_(int* nsam, quint16* iblk, qint8* nrx, int* k,
double s1[], double s2[], int* ndb);
void recvpkt_(int* nsam, quint16* iblk, qint8* nrx, int* k, double s1[], double s2[]);
}
#endif // SOUNDIN_H

View File

@ -318,7 +318,7 @@
<message>
<location filename="../widgets/colorhighlighting.ui" line="150"/>
<source>New Call</source>
<translation>Indicatiu nou</translation>
<translation>Nou Indicatiu</translation>
</message>
<message>
<location filename="../widgets/colorhighlighting.ui" line="157"/>
@ -2238,12 +2238,12 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="1683"/>
<source>Maximum drift rate in units of symbol rate per transmission.</source>
<translation>Taxa de deriva màxima en unitats de taxa de símbols per transmissió.</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1686"/>
<source>Max Drift </source>
<translation>Deriva màxima </translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2604"/>
@ -3658,7 +3658,7 @@ La llista es pot mantenir a la configuració (F2).</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="3429"/>
<source>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</source>
<translation>Guia d&apos;inici ràpid de WSJT-X 2.5.0 i MAP65 3.0</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="258"/>
@ -3685,7 +3685,7 @@ La llista es pot mantenir a la configuració (F2).</translation>
<message>
<location filename="../widgets/mainwindow.cpp" line="523"/>
<source>Scanned ADIF log, %1 worked-before records created. CTY: %2</source>
<translation>Log ADIF escanejat, %1 funcionava abans de la creació de registres. CTY: %2</translation>
<translation>Log ADIF escanejat, %1 funcionava abans de la creació de registres</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="631"/>

View File

@ -2480,17 +2480,17 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="1683"/>
<source>Maximum drift rate in units of symbol rate per transmission.</source>
<translation>Tasa de deriva máxima en unidades de tasa de símbolos por transmisión.</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1686"/>
<source>Max Drift </source>
<translation>Máxima deriva </translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3416"/>
<source>Quick-Start Guide to Q65</source>
<translation>Guía de inicio rápido de Q65 (inglés)</translation>
<translation>Guía de inicio rápido de Q65</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3424"/>
@ -2500,7 +2500,7 @@ Error(%2): %3</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="3429"/>
<source>Quick-Start Guide to WSJT-X 2.5.0 and MAP65 3.0</source>
<translation>Guía de inicio rápido para WSJT-X 2.5.0 y MAP65 3.0 (inglés)</translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1588"/>
@ -2703,7 +2703,7 @@ Amarillo cuando esta muy bajo.</translation>
<message>
<location filename="../widgets/mainwindow.ui" line="876"/>
<source>&amp;Lookup</source>
<translation>Buscar (&amp;L)</translation>
<translation>Buscar</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="988"/>
@ -3044,7 +3044,7 @@ No está disponible para los titulares de indicativo no estándar.</translatorco
<location filename="../widgets/mainwindow.ui" line="1215"/>
<source>Best S+P</source>
<translatorcomment>El mejor S+P </translatorcomment>
<translation>Mejor S+P</translation>
<translation>Mejor S+P (&amp;B)</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1225"/>
@ -3181,8 +3181,7 @@ Cuando no está marcado, puede verse los resultados de la calibración.</transla
Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</source>
<translatorcomment>Enviar este mensaje en el siguiente intervalo de transmisión.
Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translatorcomment>
<translation>Enviar este mensaje en el siguiente intervalo de TX.
Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translation>
<translation>Enviar este mensaje en el siguiente intervalo de TX. Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1826"/>
@ -3247,8 +3246,7 @@ Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una
<location filename="../widgets/mainwindow.ui" line="2035"/>
<source>Send this message in next Tx interval
Double-click to reset to the standard 73 message</source>
<translation>Enviar este mensaje en el siguiente intervalo de TX.
Doble clic para restablecer el mensaje 73 estándar.</translation>
<translation>Enviar este mensaje en el siguiente intervalo de TX. Doble clic para restablecer el mensaje 73 estándar.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2045"/>
@ -3302,9 +3300,7 @@ RR73 messages should only be used when you are reasonably confident that no mess
<translatorcomment>Cambia a este mensaje de TX AHORA.
Haz doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).
Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translatorcomment>
<translation>Cambiar a este mensaje de TX AHORA.
Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).
Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translation>
<translation>Cambiar a este mensaje de TX AHORA. Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2). Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1951"/>
@ -3401,7 +3397,7 @@ predefinida. La lista se puede modificar en &quot;Ajustes&quot; (F2).</translati
<message>
<location filename="../widgets/mainwindow.ui" line="3358"/>
<source>Quick-Start Guide to FST4 and FST4W</source>
<translation>Guía de inicio rápido a FST4 y FST4W (inglés)</translation>
<translation>Guía de inicio rápido a FST4 y FST4W</translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="3384"/>
@ -4243,7 +4239,7 @@ predefinida. La lista se puede modificar en &quot;Ajustes&quot; (F2).</translati
<location filename="../widgets/mainwindow.cpp" line="523"/>
<source>Scanned ADIF log, %1 worked-before records created. CTY: %2</source>
<translatorcomment>Log ADIF escaneado, %1 funcionaba antes de la creación de registros</translatorcomment>
<translation>Log ADIF escaneado, %1 registros trabajados B4 creados. CTY: %2</translation>
<translation>Log ADIF escaneado, %1 registros trabajados B4 creados</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="631"/>
@ -4916,7 +4912,7 @@ ya está en CALL3.TXT, ¿desea reemplazarlo?</translation>
<location filename="../widgets/mainwindow.cpp" line="8593"/>
<source>Confirm Reset</source>
<translatorcomment>Confirmar reinicio</translatorcomment>
<translation>Confirmar borrado</translation>
<translation>Confirmar restablecer</translation>
</message>
<message>
<location filename="../widgets/mainwindow.cpp" line="6841"/>
@ -5358,7 +5354,7 @@ Error(%2): %3</translation>
<message>
<location filename="../SampleDownloader.cpp" line="112"/>
<source>Base URL for samples:</source>
<translation>Enlace de las muestras:</translation>
<translation>Enlace para muestras:</translation>
</message>
<message>
<location filename="../SampleDownloader.cpp" line="113"/>
@ -5487,7 +5483,7 @@ Error(%2): %3</translation>
<message>
<location filename="../Audio/soundout.cpp" line="95"/>
<source>No audio output device configured.</source>
<translation>No hay dispositivo de salida de audio configurado.</translation>
<translation>No hay dispositivo de salida de audio configurado</translation>
</message>
<message>
<location filename="../Audio/soundout.cpp" line="184"/>
@ -5978,7 +5974,7 @@ Error(%2): %3</translation>
<location filename="../Configuration.ui" line="237"/>
<source>Font...</source>
<translatorcomment>Letra...</translatorcomment>
<translation>Tipo de letra para la aplicación..</translation>
<translation>Tipo de letra para la aplicación</translation>
</message>
<message>
<location filename="../Configuration.ui" line="244"/>
@ -6224,7 +6220,7 @@ período de silencio cuando se ha realizado la decodificación.</translation>
<message>
<location filename="../Configuration.ui" line="628"/>
<source>4800</source>
<translation>4800</translation>
<translation></translation>
</message>
<message>
<location filename="../Configuration.ui" line="633"/>
@ -6836,7 +6832,7 @@ Haz clic derecho para acciones específicas del artículo.
Clic, Mayúsculas+Clic y, CTRL+Clic para seleccionar elementos.</translatorcomment>
<translation>Arrastre y suelte elementos para reorganizar el orden
Clic derecho para acciones específicas del elemento.
Clic, Mayús+Clic y CTRL+Clic para seleccionar elementos</translation>
Clic, Mayús+Clic y CTRL+Clic para seleccionar elementos.</translation>
</message>
<message>
<location filename="../Configuration.ui" line="1709"/>
@ -7563,7 +7559,7 @@ Clic derecho para insertar y eliminar opciones.</translation>
<location filename="../Configuration.ui" line="2970"/>
<source>Waterfall spectra</source>
<translatorcomment>Espectros de la cascada</translatorcomment>
<translation>Cascada (Waterfall)</translation>
<translation>Espectro de la cascada (waterfall)</translation>
</message>
<message>
<location filename="../Configuration.ui" line="2976"/>

View File

@ -21,7 +21,7 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"WSJT-X implements a number of digital modes designed for <br />"
"weak-signal Amateur Radio communication. <br /><br />"
"&copy; 2001-2024 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />"
"&copy; 2001-2023 by Joe Taylor, K1JT, Bill Somerville, G4WJS, <br />"
"Steve Franke, K9AN, Nico Palermo, IV3NWV, <br />"
"Uwe Risse, DG2YCB, and Brian Moran, N9ADG <br /><br />"
"We gratefully acknowledge contributions from AC6SL, AE4JY,<br />"

View File

@ -47,7 +47,7 @@ void ActiveStations::read_settings ()
ui->sbMaxRecent->setValue(settings_->value("MaxRecent",10).toInt());
ui->sbMaxAge->setValue(settings_->value("MaxAge",10).toInt());
ui->cbReadyOnly->setChecked(settings_->value("ReadyOnly",false).toBool());
ui->cbWantedOnly->setChecked(settings_->value("# WantedOnly",false).toBool());
ui->cbWantedOnly->setChecked(settings_->value("WantedOnly",false).toBool());
}
void ActiveStations::write_settings ()
@ -64,11 +64,9 @@ void ActiveStations::displayRecentStations(QString mode, QString const& t)
{
if(mode!=m_mode) {
m_mode=mode;
ui->cbReadyOnly->setText(" Ready only");
if(m_mode=="Q65") {
ui->header_label2->setText(" N Frx Fsked S/N Q65 Call Grid Tx Age");
ui->header_label2->setText(" N Frx Fsked S/N Call Grid Tx Age");
ui->label->setText("QSOs:");
ui->cbReadyOnly->setText("* CQ only");
} else if(m_mode=="Q65-pileup") {
ui->header_label2->setText(" N Freq Call Grid El Age(h)");
} else {
@ -92,32 +90,6 @@ void ActiveStations::displayRecentStations(QString mode, QString const& t)
bool bClickOK=m_clickOK;
m_clickOK=false;
ui->RecentStationsPlainTextEdit->setPlainText(t);
//White background for Q65-60x decodes, yellow for Q65-30x:
int i0=0;
int i1=0;
int npos=0;
int nlines=t.count("\n");
QTextCursor cursor=ui->RecentStationsPlainTextEdit->textCursor();
QTextCharFormat fmt;
for(int i=0; i<nlines; i++) {
i1=t.indexOf("\n",i0);
npos=t.indexOf(QRegularExpression(" 30[ABCD] "), i0);
if(npos>0) {
cursor.setPosition(npos);
cursor.select(QTextCursor::LineUnderCursor);
fmt.setBackground(QBrush(Qt::yellow));
fmt.setForeground(QBrush(Qt::black));
} else {
cursor.setPosition(i0+10);
cursor.select(QTextCursor::LineUnderCursor);
fmt.clearForeground();
fmt.clearBackground();
}
cursor.setCharFormat(fmt);
i0=i1+1;
}
m_clickOK=bClickOK;
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>340</height>
<width>395</width>
<height>339</height>
</rect>
</property>
<property name="windowTitle">
@ -17,30 +17,32 @@
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,1,0,0,1">
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Band Changes:</string>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="2">
<widget class="QSpinBox" name="sbMaxRecent">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QLineEdit" name="score">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Total score accumulated since most recent reset of Cabrillo log.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum number of displayed lines.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>0</string>
<property name="prefix">
<string>Max N </string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<property name="maximum">
<number>50</number>
</property>
<property name="readOnly">
<bool>true</bool>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
@ -48,7 +50,7 @@
<widget class="QLineEdit" name="rate">
<property name="maximumSize">
<size>
<width>16777215</width>
<width>80</width>
<height>16777215</height>
</size>
</property>
@ -76,24 +78,30 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cbWantedOnly">
<property name="visible">
<bool>false</bool>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string># Wanted only</string>
<string>Band Changes:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_2">
<item row="1" column="5">
<widget class="QLineEdit" name="score">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Total score accumulated since most recent reset of Cabrillo log.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Score:</string>
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="4">
@ -116,22 +124,19 @@
</property>
<property name="minimumSize">
<size>
<width>0</width>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum elapsed number of T/R sequences.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max Age </string>
</property>
@ -146,34 +151,13 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="sbMaxRecent">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set maximum number of displayed lines.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<item row="1" column="4">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Score:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="prefix">
<string>Max N </string>
</property>
<property name="maximum">
<number>50</number>
</property>
<property name="value">
<number>10</number>
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@ -193,6 +177,16 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cbWantedOnly">
<property name="visible">
<bool>false</bool>
</property>
<property name="text">
<string>Wanted only</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">

View File

@ -387,17 +387,6 @@ QString DisplayText::appendWorkedB4 (QString message, QString call, QString cons
countryName.replace ("European", "EU");
countryName.replace ("African", "AF");
// assign WAE entities to the correct DXCC when "Include extra WAE entities" is not selected
if (!(m_config->include_WAE_entities())) {
countryName.replace ("Bear Is.", "Svalbard");
countryName.replace ("Shetland Is.", "Scotland");
countryName.replace ("AF Italy", "Italy");
countryName.replace ("Sicily", "Italy");
countryName.replace ("Vienna Intl Ctr", "Austria");
countryName.replace ("AF Turkey", "Turkey");
countryName.replace ("EU Turkey", "Turkey");
}
extra += countryName;
}
}
@ -531,8 +520,7 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
QString t2;
t2 = t2.asprintf("%4d",txFreq);
QString t;
if(bFastMode or modeTx=="FT8" or modeTx=="FT4" or (TRperiod<60) or
(modeTx=="Q65" and TRperiod==60)) {
if(bFastMode or modeTx=="FT8" or modeTx=="FT4" or (TRperiod<60)) {
t = QDateTime::currentDateTimeUtc().toString("hhmmss") + \
" Tx " + t2 + t1 + text;
} else if(modeTx.mid(0,6)=="FT8fox") {

View File

@ -213,7 +213,6 @@ QVector<QColor> g_ColorTbl;
using SpecOp = Configuration::SpecialOperatingActivity;
bool blocked = false;
bool m_displayBand = false;
bool no_a7_decodes = false;
bool keep_frequency = false;
@ -225,8 +224,7 @@ struct {
int nQDecoderDone; //QMAP decoder is finished (0 or 1)
int nWDecoderBusy; //WSJT-X decoder is busy (0 or 1)
int nWTransmitting; //WSJT-X is transmitting (0 or 1)
int kHzRequested; //Integer kHz dial frequency requested from QMAP
char result[50][64]; //Decodes as character*64 arrays
char result[50][60]; //Decodes as character*60 arrays
} qmapcom;
int* ipc_qmap;
@ -1086,35 +1084,18 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
QString jpleph = m_config.data_dir().absoluteFilePath("JPLEPH");
jpl_setup_(const_cast<char *>(jpleph.toLocal8Bit().constData()),256);
#ifdef WIN32
// backup libhamlib-4.dll file, so it is still available after the next program update
QDir dataPath = QCoreApplication::applicationDirPath();
QFile f {dataPath.absolutePath() + "/" + "libhamlib-4_old.dll"};
if (!f.exists()) {
QFile::copy(dataPath.absolutePath() + "/" + "libhamlib-4.dll", dataPath.absolutePath() + "/" + "libhamlib-4_old.dll");
QTimer::singleShot (5000, [=] { //wait until hamlib has been started
extern char* hamlib_version2;
QString hamlib = QString(QLatin1String(hamlib_version2));
m_settings->beginGroup("Configuration");
m_settings->setValue ("HamlibBackedUp", hamlib);
m_settings->endGroup();
});
}
#endif
// this must be the last statement of constructor
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
}
void MainWindow::not_GA_warning_message ()
{
if(m_config.my_callsign()=="K1JT" or m_config.my_callsign()=="W2ZQ") return;
MessageBox::critical_message (this,
"This is a pre-release version of WSJT-X " + version (false) + " made\n"
"This is a pre-release version of WSJT-X 2.7.0-rc2 made\n"
"available for testing purposes. By design it will\n"
"be nonfunctional after October 30, 2024.");
"be nonfunctional after Jan 15, 2024.");
auto now = QDateTime::currentDateTimeUtc ();
if (now >= QDateTime {{2024, 10, 30}, {23, 59, 59, 999}, Qt::UTC}) {
if (now >= QDateTime {{2024, 01, 15}, {23, 59, 59, 999}, Qt::UTC}) {
Q_EMIT finished ();
}
}
@ -1225,16 +1206,6 @@ void MainWindow::writeSettings()
m_settings->setValue ("SerialNumber",ui->sbSerialNumber->value ());
m_settings->endGroup();
// do this in the General group because we save the parameters from various places
if(m_mode=="JT9") {
m_settings->setValue("SubMode",ui->sbSubmode->value());
m_settings->setValue("TRPeriod", ui->sbTR->value());
}
if(m_mode=="MSK144") m_settings->setValue("ShMsgs_MSK144",m_bShMsgs);
if(m_mode=="Q65") m_settings->setValue("ShMsgs_Q65",m_bShMsgs);
if(m_mode=="JT65") m_settings->setValue("ShMsgs_JT65",m_bShMsgs);
if(m_mode=="JT4") m_settings->setValue("ShMsgs_JT4",m_bShMsgs);
m_settings->beginGroup("Common");
m_settings->setValue("Mode",m_mode);
m_settings->setValue("SaveNone",ui->actionNone->isChecked());
@ -1248,12 +1219,13 @@ void MainWindow::writeSettings()
m_settings->setValue("FST4W_FTol",ui->sbFST4W_FTol->value());
m_settings->setValue("FST4_FLow",ui->sbF_Low->value());
m_settings->setValue("FST4_FHigh",ui->sbF_High->value());
// m_settings->setValue("SubMode",ui->sbSubmode->value());
m_settings->setValue("DTtol",m_DTtol);
m_settings->setValue("Ftol", ui->sbFtol->value ());
m_settings->setValue("MinSync",m_minSync);
m_settings->setValue ("AutoSeq", ui->cbAutoSeq->isChecked ());
m_settings->setValue ("RxAll", ui->cbRxAll->isChecked ());
// m_settings->setValue("ShMsgs",m_bShMsgs);
m_settings->setValue("ShMsgs",m_bShMsgs);
m_settings->setValue("SWL",ui->cbSWL->isChecked());
m_settings->setValue ("DialFreq", QVariant::fromValue(m_lastMonitoredFrequency));
m_settings->setValue("OutAttenuation", ui->outAttenuation->value ());
@ -1269,6 +1241,7 @@ void MainWindow::writeSettings()
m_settings->setValue("UploadSpots",m_uploadWSPRSpots);
m_settings->setValue("NoOwnCall",ui->cbNoOwnCall->isChecked());
m_settings->setValue ("BandHopping", ui->band_hopping_group_box->isChecked ());
// m_settings->setValue ("TRPeriod", ui->sbTR->value ());
m_settings->setValue ("MaxDrift", ui->sbMaxDrift->value());
m_settings->setValue ("TRPeriod_FST4W", ui->sbTR_FST4W->value ());
m_settings->setValue("FastMode",m_bFastMode);
@ -1336,58 +1309,16 @@ void MainWindow::readSettings()
ui->sbSerialNumber->setValue (m_settings->value ("SerialNumber", 1).toInt ());
m_settings->endGroup();
m_settings->beginGroup("Common");
m_mode=m_settings->value("Mode","FT8").toString();
m_settings->endGroup();
// do this outside of settings group because it uses groups internally
ui->actionAstronomical_data->setChecked (displayAstro);
// do this in the General group because we save the parameters from various places
if(m_mode=="JT9") {
blocked=true;
m_nSubMode=m_settings->value("SubMode",0).toInt();
ui->sbSubmode->setValue(m_nSubMode);
ui->sbFtol->setValue (m_settings->value("Ftol_JT9", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt());
QTimer::singleShot (50, [=] {blocked = false;});
}
if (m_mode=="Q65") {
m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_Q65);
ui->sbFtol->setValue (m_settings->value("Ftol_Q65", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
}
if (m_mode=="JT65") {
m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_JT65);
ui->sbFtol->setValue (m_settings->value("Ftol_JT65", 50).toInt());
}
if (m_mode=="JT4") {
m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
ui->sbSubmode->setValue(m_nSubMode_JT4);
ui->sbFtol->setValue (m_settings->value("Ftol_JT4", 50).toInt());
ui->sbTR->setValue (m_settings->value ("TRPeriod_FST4", 60).toInt());
}
if (m_mode=="MSK144") {
ui->sbFtol->setValue (m_settings->value("Ftol_MSK144",50).toInt());
if (!(m_currentBand=="6m" or m_currentBand=="4m" or m_currentBand=="2m")) ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 30).toInt());
if (m_currentBand=="6m" or m_currentBand=="4m") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144_6m", 15).toInt());
if (m_currentBand=="2m") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144_2m", 30).toInt());
}
if (m_mode=="MSK144") m_bShMsgs=m_settings->value("ShMsgs_MSK144",false).toBool();
if (m_mode=="Q65") m_bShMsgs=m_settings->value("ShMsgs_Q65",false).toBool();
if (m_mode=="JT65") m_bShMsgs=m_settings->value("ShMsgs_JT65",false).toBool();
if (m_mode=="JT4") m_bShMsgs=m_settings->value("ShMsgs_JT4",false).toBool();
m_settings->beginGroup("Common");
ui->labDXped->setText(m_settings->value("labDXpedText",QString {}).toString ());
ui->actionDon_t_split_ALL_TXT->setChecked(m_settings->value("actionDontSplitALLTXT", true).toBool());
ui->actionSplit_ALL_TXT_yearly->setChecked(m_settings->value("splitAllTxtYearly", false).toBool());
ui->actionSplit_ALL_TXT_monthly->setChecked(m_settings->value("splitAllTxtMonthly", false).toBool());
ui->actionDisable_writing_of_ALL_TXT->setChecked(m_settings->value("disableWritingOfAllTxt", false).toBool());
// m_mode=m_settings->value("Mode","FT8").toString();
m_mode=m_settings->value("Mode","FT8").toString();
ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
ui->actionSave_decoded->setChecked(m_settings->value("SaveDecoded",false).toBool());
ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool());
@ -1397,16 +1328,28 @@ void MainWindow::readSettings()
ui->sbFST4W_RxFreq->setValue(m_settings->value("FST4W_RxFreq",1500).toInt());
ui->sbF_Low->setValue(m_settings->value("FST4_FLow",600).toInt());
ui->sbF_High->setValue(m_settings->value("FST4_FHigh",1400).toInt());
// m_nSubMode=m_settings->value("SubMode",0).toInt();
if (m_mode=="Q65") m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
if (m_mode=="JT65") m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
if (m_mode=="JT4") m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
// ui->sbSubmode->setValue(m_nSubMode);
if (m_mode=="Q65") ui->sbSubmode->setValue(m_nSubMode_Q65);
if (m_mode=="JT65") ui->sbSubmode->setValue(m_nSubMode_JT65);
if (m_mode=="JT4") ui->sbSubmode->setValue(m_nSubMode_JT4);
ui->sbFtol->setValue (m_settings->value("Ftol", 50).toInt());
ui->sbFST4W_FTol->setValue(m_settings->value("FST4W_FTol",100).toInt());
m_minSync=m_settings->value("MinSync",0).toInt();
ui->syncSpinBox->setValue(m_minSync);
ui->cbAutoSeq->setChecked (m_settings->value ("AutoSeq", false).toBool());
ui->cbRxAll->setChecked (m_settings->value ("RxAll", false).toBool());
// m_bShMsgs=m_settings->value("ShMsgs",false).toBool();
m_bShMsgs=m_settings->value("ShMsgs",false).toBool();
m_bSWL=m_settings->value("SWL",false).toBool();
m_bFast9=m_settings->value("Fast9",false).toBool();
m_bFastMode=m_settings->value("FastMode",false).toBool();
// ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt());
if (m_mode=="Q65") ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
if (m_mode=="MSK144") ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt());
if (m_mode=="FST4") ui->sbTR->setValue (m_settings->value ("TRPeriod_FST4", 60).toInt());
ui->sbMaxDrift->setValue (m_settings->value ("MaxDrift",0).toInt());
ui->sbTR_FST4W->setValue (m_settings->value ("TRPeriod_FST4W", 15).toInt());
m_lastMonitoredFrequency = m_settings->value ("DialFreq",
@ -1734,7 +1677,6 @@ void MainWindow::dataSink(qint64 frames)
float width=m_fSpread;
echocom_.nclearave=m_nclearave;
int nDop=m_fAudioShift;
if(m_astroWidget->DopplerMethod()==2) nDop=0; //Using CFOM
int nDopTotal=m_fDop;
int navg=ui->sbEchoAvg->value();
if(m_diskData) {
@ -2251,13 +2193,6 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
bool bAltF1F6=m_config.alternate_bindings();
switch(e->key())
{
case Qt::Key_A:
if(m_mode=="Q65" && e->modifiers() & Qt::AltModifier) {
m_EMECall.clear();
qmapcom.ndecodes=0;
readWidebandDecodes();
}
return;
case Qt::Key_B:
if(m_mode=="FT4" && e->modifiers() & Qt::AltModifier) {
on_pbBestSP_clicked();
@ -2556,7 +2491,7 @@ void MainWindow::statusChanged()
.arg (f.fileName ()).arg (f.errorString ()));
}
on_dxGridEntry_textChanged(m_hisGrid);
if (m_specOp!=SpecOp::HOUND) {
if(m_specOp!=SpecOp::HOUND) {
ui->txb2->setEnabled(true);
ui->txrb2->setEnabled(true);
ui->txb4->setEnabled(true);
@ -2567,27 +2502,6 @@ void MainWindow::statusChanged()
ui->txrb6->setEnabled(true);
ui->houndButton->setChecked(false);
}
if (m_config.enable_VHF_features() && (m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65")) {
ui->actionInclude_averaging->setVisible(true);
ui->actionAuto_Clear_Avg->setVisible(true);
} else {
ui->actionInclude_averaging->setVisible(false);
ui->actionAuto_Clear_Avg->setVisible(false);
}
if (m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65") {
if (ui->actionInclude_averaging->isVisible() && ui->actionInclude_averaging->isChecked()) {
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
} else {
if (m_config.enable_VHF_features()) {
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
ui->rh_decodes_title_label->setText(tr ("Decodes containing My Call"));
} else {
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
ui->rh_decodes_title_label->setText(tr ("Rx Frequency"));
}
}
}
}
bool MainWindow::eventFilter (QObject * object, QEvent * event)
@ -2889,7 +2803,7 @@ void MainWindow::on_actionCopyright_Notice_triggered()
"\"The algorithms, source code, look-and-feel of WSJT-X and related "
"programs, and protocol specifications for the modes FSK441, FST4, FT8, "
"JT4, JT6M, JT9, JT65, JTMS, QRA64, Q65, MSK144 are Copyright (C) "
"2001-2024 by one or more of the following authors: Joseph Taylor, "
"2001-2023 by one or more of the following authors: Joseph Taylor, "
"K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, "
"IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; "
"Philip Karn, KA9Q; Uwe Risse, DG2YCB; Brian Moran, N9ADG; "
@ -3266,7 +3180,6 @@ void MainWindow::on_actionKeyboard_shortcuts_triggered()
<tr><td><b>Ctrl+Shift+F12 </b></td><td>Move dial frequency up 1000 Hz</td></tr>
<tr><td><b>Alt+1-6 </b></td><td>Set now transmission to this number on Tab 1</td></tr>
<tr><td><b>Ctl+1-6 </b></td><td>Set next transmission to this number on Tab 1</td></tr>
<tr><td><b>Alt+A </b></td><td>Clear Active Stations for QMAP</td></tr>
<tr><td><b>Alt+B </b></td><td>Toggle "Best S+P" status</td></tr>
<tr><td><b>Alt+C </b></td><td>Toggle "Call 1st" checkbox</td></tr>
<tr><td><b>Alt+D </b></td><td>Decode again at QSO frequency</td></tr>
@ -3313,7 +3226,7 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
<td><b>Click</b> to set Rx frequency.<br/>
<b>Shift-click</b> to set Tx frequency.<br/>
<b>Ctrl-click</b> or <b>Right-click</b> to set Rx and Tx frequencies.<br/>
<b>Double-click</b> to also decode at Rx frequency.
<b>Double-click</b> to also decode at Rx frequency.<br/>
</td>
</tr>
<tr>
@ -3324,7 +3237,7 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
messages.<br/>
If <b>Hold Tx Freq</b> is checked or first callsign in message<br/>
is your own call, Tx frequency is not changed unless <br/>
<b>Ctrl</b> is held down.
<b>Ctrl</b> is held down.<br/>
</td>
</tr>
<tr>
@ -3333,18 +3246,6 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
<b>Double-click</b> to erase QSO and Band Activity windows.
</td>
</tr>
<tr>
<td align="right">Q65 Button:</td>
<td><b>Click</b> to switch to Q65 Mode.<br/>
<b>Right-click</b> to switch to Q65 Pileup Mode.
</td>
</tr>
<tr>
<td align="right">JT65 Button:</td>
<td><b>Click</b> to switch to JT65 Mode.<br/>
<b>Right-click</b> to switch to JT9 Mode.
</td>
</tr>
</table>)"), font});
}
m_mouseCmnds->showNormal ();
@ -3929,9 +3830,9 @@ void MainWindow::callSandP2(int n)
int nMHz=m_freqNominal/1000000;
m_freqNominal=(nMHz*1000 + kHz)* 1000;
}
m_deCall=w[4];
m_deGrid=w[5];
m_txFirst=(w[6]=="0");
m_deCall=w[3];
m_deGrid=w[4];
m_txFirst=(w[5]=="0");
// ui->TxFreqSpinBox->setValue(1500);
} else {
m_deCall=w[0];
@ -3939,18 +3840,6 @@ void MainWindow::callSandP2(int n)
ui->RxFreqSpinBox->setValue(w[4].toInt());
m_txFirst = (w[5]=="0");
}
if(w[3].left(2)=="30") {
ui->sbTR->setValue(30);
} else {
ui->sbTR->setValue(60);
}
if(w[3].right(1)=="A") ui->sbSubmode->setValue(0);
if(w[3].right(1)=="B") ui->sbSubmode->setValue(1);
if(w[3].right(1)=="C") ui->sbSubmode->setValue(2);
if(w[3].right(1)=="D") ui->sbSubmode->setValue(3);
if(w[3].right(1)=="E") ui->sbSubmode->setValue(4);
m_bDoubleClicked=true; //### needed?
ui->dxCallEntry->setText(m_deCall);
ui->dxGridEntry->setText(m_deGrid);
@ -3962,14 +3851,7 @@ void MainWindow::callSandP2(int n)
}
setTxMsg(1);
ui->txFirstCheckBox->setChecked(m_txFirst);
static qint64 ms0=0;
qint64 ms=QDateTime::currentMSecsSinceEpoch();
if(ui->autoButton->isChecked()) {
if((ms-ms0)<=500) ui->autoButton->click(); // Disable Tx on double click
} else if((ms-ms0)>500) {
ui->autoButton->click(); // Enable Tx on single click
}
ms0=ms;
if (!ui->autoButton->isChecked()) ui->autoButton->click(); // Enable Tx
if(m_transmitting) m_restart=true;
}
@ -4272,9 +4154,7 @@ void MainWindow::readFromStdout() //readFromStdout
if((abs(audioFreq - m_wideGraph->rxFreq()) <= 10) and
!m_config.enable_VHF_features()) bDisplayRight=true;
}
if(m_mode=="Q65" and !bAvgMsg and !decodedtext.string().contains(m_baseCall)) bDisplayRight=false;
if((m_mode=="JT4" or m_mode=="Q65" or m_mode=="JT65") and decodedtext.string().contains(m_baseCall) && ui->actionInclude_averaging->isVisible() && !ui->actionInclude_averaging->isChecked()) bDisplayRight=true;
if(m_mode=="FT8" and SpecOp::HOUND==m_specOp && decodedtext0.string().replace("<","").replace(">","").contains(" " + m_baseCall + " ")) bDisplayRight=true;
if(m_mode=="Q65" and !bAvgMsg) bDisplayRight=false;
if (bDisplayRight) {
// This msg is within 10 hertz of our tuned frequency, or a JT4 or JT65 avg,
@ -5100,24 +4980,19 @@ void MainWindow::guiUpdate()
if(m_decoderBusy) n=1;
ipc_qmap[3]=n;
n=0;
if(m_transmitting) n=m_TRperiod;
if(m_transmitting) n=1;
ipc_qmap[4]=n;
if(ipc_qmap[0] > 0) { //ndecodes
memcpy(&qmapcom, (char*)ipc_qmap, sizeof(qmapcom)); //Fetch the new decode(s)
readWidebandDecodes();
}
if(ipc_qmap[5]>0) {
// qDebug() << "aa" << m_freqNominal << ipc_qmap[5];
setRig((m_freqNominal/1000000)*1000000 + 1000*ipc_qmap[5]);
ipc_qmap[5]=0;
// qDebug() << "bb" << m_freqNominal << ipc_qmap[5];
}
mem_qmap.unlock();
}
//Once per second (onesec)
if(nsec != m_sec0) {
// qDebug() << "AAA" << nsec%60 << ipc_qmap[5];
// qDebug() << "AAA" << nsec%60 << int(m_specOp);
if(m_mode=="FST4") chk_FST4_freq_range();
m_currentBand=m_config.bands()->find(m_freqNominal);
if( SpecOp::HOUND == m_specOp ) {
@ -5523,24 +5398,7 @@ void MainWindow::doubleClickOnCall(Qt::KeyboardModifiers modifiers)
} else {
cursor=ui->decodedTextBrowser2->textCursor();
}
DecodedText message {cursor.block().text().trimmed().left(61).remove("TU; ")};
if(message.string().contains(";") && message.string().contains("<")) {
QVector<qint32> Freq = {1840000,3573000,7074000,10136000,14074000,18100000,21074000,24915000,28074000,50313000,70154000,3575000,7047500,10140000,14080000,18104000,21140000,24919000,28180000,50318000};
for(int i=0; i<Freq.length()-1; i++) {
int kHzdiff=m_freqNominal - Freq[i];
if(qAbs(kHzdiff) < 3000 ) {
m_bTxTime=false;
if (m_auto) auto_tx_mode (false);
if (m_tune) stop_tuning();
// auto const& msg2 = tr("Double-clicking on combined messages\n"
// "not allowed on the standard FT8 sub-bands.");
// QTimer::singleShot (0, [=] { // don't block guiUpdate
// MessageBox::warning_message (this, tr ("Potential hash collision"), msg2);
// });
return;
}
}
}
if(modifiers==(Qt::ShiftModifier + Qt::ControlModifier + Qt::AltModifier)) {
//### What was the purpose of this ??? ###
cursor.setPosition(0);
@ -5555,6 +5413,7 @@ void MainWindow::doubleClickOnCall(Qt::KeyboardModifiers modifiers)
}
return;
}
DecodedText message {cursor.block().text().trimmed().left(61).remove("TU; ")};
m_bDoubleClicked = true;
processMessage (message, modifiers);
}
@ -5658,7 +5517,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
QString firstcall = message.call();
if(firstcall.length()>=4 and firstcall.mid(0,3)=="CQ ") firstcall="CQ";
if(!m_bFastMode and (!m_config.enable_VHF_features() or m_mode=="FT8" or m_mode=="FT4" or m_mode=="FST4")) {
if(!m_bFastMode and (!m_config.enable_VHF_features() or m_mode=="FT8")) {
// Don't change Tx freq if in a fast mode, or VHF features enabled; also not if a
// station is calling me, unless CTRL or SHIFT is held down.
if ((Radio::is_callsign (firstcall)
@ -6114,7 +5973,7 @@ void MainWindow::genCQMsg ()
( tlist.at(1)==my_callsign or
tlist.at(2)==my_callsign ) and
stdCall(my_callsign)) {
if(m_config.Individual_Contest_Name() && SpecOp::FOX != m_specOp) {
if(m_config.Individual_Contest_Name()) {
m_cqStr = m_config.Contest_Name();
} else {
if(SpecOp::NA_VHF == m_specOp) m_cqStr="TEST";
@ -6243,9 +6102,6 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
t1 = t1.asprintf("%4.4d",ui->sbSerialNumber->value());
sent=rst + t1;
}
if(t1.contains(QRegularExpression {"\\d\\d\\d\\d"})) {
t1 = m_config.RTTY_Exchange();
}
}
if(SpecOp::EU_VHF==m_specOp) {
QString a;
@ -6434,7 +6290,7 @@ void MainWindow::lookup()
{
QString hisCall {ui->dxCallEntry->text()};
QString hisgrid0 {ui->dxGridEntry->text()};
if (!hisCall.size () or (!(m_specOp==SpecOp::NONE or m_specOp==SpecOp::HOUND or m_specOp==SpecOp::Q65_PILEUP))) return;
if (!hisCall.size ()) return;
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("CALL3.TXT")};
if (f.open (QIODevice::ReadOnly | QIODevice::Text))
{
@ -6664,14 +6520,18 @@ void MainWindow::on_RoundRobin_currentTextChanged(QString text)
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if(ui->q65Button->hasFocus() && (event->button() & Qt::RightButton)) { // switch to Q65_Pileup mode
if(ui->q65Button->hasFocus() && (event->button() & Qt::RightButton)) {
m_specOp=m_config.special_op_id();
if (m_specOp==SpecOp::Q65_PILEUP) {
m_config.setSpecial_None();
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
} else {
m_config.setSpecial_Q65_Pileup();
}
m_specOp=m_config.special_op_id();
on_actionQ65_triggered();
}
if(ui->jt65Button->hasFocus() && (event->button() & Qt::RightButton)) { // switch to JT9 mode
on_actionJT9_triggered();
}
}
void MainWindow::on_dxCallEntry_textChanged (QString const& call)
@ -6791,10 +6651,6 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
m_xSent=m_config.my_grid().left(4);
m_xRcvd=m_hisGrid;
break;
case SpecOp::Q65_PILEUP:
m_xSent=m_config.my_grid().left(4);
m_xRcvd=m_hisGrid;
break;
default: break;
}
@ -6984,10 +6840,6 @@ void MainWindow::on_actionFST4_triggered()
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_mode="FST4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFST4->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -7030,10 +6882,6 @@ void MainWindow::on_actionFST4_triggered()
void MainWindow::on_actionFST4W_triggered()
{
m_mode="FST4W";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFST4W->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -7069,10 +6917,6 @@ void MainWindow::on_actionFT4_triggered()
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_mode="FT4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
m_TRperiod=7.5;
bool bVHF=m_config.enable_VHF_features();
m_bFast9=false;
@ -7239,10 +7083,6 @@ void MainWindow::on_actionJT4_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
m_mode="JT4";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
switch_mode (Modes::JT4);
@ -7263,16 +7103,15 @@ void MainWindow::on_actionJT4_triggered()
m_bFast9=false;
setup_status_bar (bVHF);
ui->sbSubmode->setMaximum(6);
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
if(bVHF) {
// restore last used parameters
ui->sbFtol->setValue (m_settings->value ("Ftol_JT4", 50).toInt());
m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_JT4",0).toInt());
QTimer::singleShot (50, [=] {on_sbSubmode_valueChanged(ui->sbSubmode->value());});
m_bShMsgs=m_settings->value("ShMsgs_JT4",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_JT4",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_JT4",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
} else {
ui->sbSubmode->setValue(0);
}
@ -7289,25 +7128,8 @@ void MainWindow::on_actionJT4_triggered()
void MainWindow::on_actionJT9_triggered()
{
m_mode="JT9";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
bool bVHF=m_config.enable_VHF_features();
// restore last used parameters
if(bVHF && m_mode!="JT65" && !blocked) {
ui->sbSubmode->setMaximum(7);
m_bFast9=m_settings->value("JT9_Fast",false).toBool();
ui->cbFast9->setChecked(m_bFast9 or m_bFastMode);
ui->sbFtol->setValue (m_settings->value ("Ftol_JT9", 50).toInt());
m_nSubMode=m_settings->value("SubMode",0).toInt();
ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
}
// m_bFast9=ui->cbFast9->isChecked();
m_bFast9=ui->cbFast9->isChecked();
m_bFastMode=m_bFast9;
WSPR_config(false);
switch_mode (Modes::JT9);
@ -7330,7 +7152,6 @@ void MainWindow::on_actionJT9_triggered()
ui->sbSubmode->setMaximum(7);
if(m_bFast9) {
ui->sbTR->values ({5, 10, 15, 30});
if(bVHF && m_mode!="JT65" && !blocked) ui->sbTR->setValue (m_settings->value ("TRPeriod", 15).toInt()); // restore last used TRperiod
on_sbTR_valueChanged (ui->sbTR->value());
m_wideGraph->hide();
m_fastGraph->showNormal();
@ -7370,10 +7191,6 @@ void MainWindow::on_actionJT65_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
on_actionJT9_triggered();
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
m_mode="JT65";
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
@ -7399,13 +7216,12 @@ void MainWindow::on_actionJT65_triggered()
m_bFast9=false;
ui->sbSubmode->setMaximum(2);
if(bVHF) {
// restore last used parameters
ui->sbFtol->setValue (m_settings->value ("Ftol_JT65", 50).toInt());
m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_JT65",0).toInt());
QTimer::singleShot (50, [=] {on_sbSubmode_valueChanged(ui->sbSubmode->value());});
m_bShMsgs=m_settings->value("ShMsgs_JT65",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_JT65",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_JT65",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
} else {
ui->sbSubmode->setValue(0);
ui->lh_decodes_title_label->setText(tr ("Band Activity"));
@ -7432,10 +7248,6 @@ void MainWindow::on_actionQ65_triggered()
ui->RxFreqSpinBox->setValue(m_settings->value("RxFreq_old",1500).toInt());
});
m_mode="Q65";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionQ65->setChecked(true);
switch_mode(Modes::Q65);
ui->cbAutoSeq->setChecked(true);
@ -7449,17 +7261,12 @@ void MainWindow::on_actionQ65_triggered()
Q_EMIT FFTSize(m_FFTSize);
m_hsymStop=49;
ui->sbTR->values ({15, 30, 60, 120, 300});
// restore last used parameters
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt());
ui->sbFtol->setValue (m_settings->value ("Ftol_Q65", 50).toInt());
m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();
ui->sbSubmode->setValue(m_settings->value("SubMode_Q65",0).toInt());
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_bShMsgs=m_settings->value("ShMsgs_Q65",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
ui->sbTR->setValue (m_settings->value ("TRPeriod_Q65", 30).toInt()); // remember sbTR settings by mode
QTimer::singleShot (50, [=] {on_sbTR_valueChanged (ui->sbTR->value());});
// ui->sbSubmode->setValue(m_nSubMode);
QTimer::singleShot (50, [=] {m_nSubMode=m_settings->value("SubMode_Q65",0).toInt();});
QTimer::singleShot (75, [=] {ui->sbSubmode->setValue(m_settings->value("SubMode_Q65",0).toInt());});
QTimer::singleShot (100, [=] {on_sbSubmode_valueChanged(m_nSubMode);});
QString fname {QDir::toNativeSeparators(m_config.temp_dir().absoluteFilePath ("red.dat"))};
m_wideGraph->setRedFile(fname);
m_wideGraph->setMode(m_mode);
@ -7470,6 +7277,8 @@ void MainWindow::on_actionQ65_triggered()
switch_mode (Modes::Q65);
// 01234567890123456789012345678901234567
displayWidgets(nWidgets("11111101011011010011100000010000000011"));
ui->lh_decodes_title_label->setText(tr ("Single-Period Decodes"));
ui->rh_decodes_title_label->setText(tr ("Average Decodes"));
ui->lh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
ui->rh_decodes_headings_label->setText("UTC dB DT Freq " + tr ("Message"));
@ -7521,10 +7330,6 @@ void MainWindow::on_actionMSK144_triggered()
return;
}
m_mode="MSK144";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionMSK144->setChecked(true);
switch_mode (Modes::MSK144);
m_nsps=6;
@ -7538,10 +7343,11 @@ void MainWindow::on_actionMSK144_triggered()
m_bFastMode=true;
m_bFast9=false;
ui->sbTR->values ({5, 10, 15, 30});
ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt()); // restore last used TRperiod
QTimer::singleShot (50, [=] {on_sbTR_valueChanged (ui->sbTR->value());});
m_bShMsgs=m_settings->value("ShMsgs_MSK144",false).toBool();
ui->cbShMsgs->setChecked(m_bShMsgs);
ui->sbTR->setValue (m_settings->value ("TRPeriod_MSK144", 15).toInt()); // remember sbTR settings by mode
QTimer::singleShot (50, [=] {
on_sbTR_valueChanged (ui->sbTR->value());
on_sbSubmode_valueChanged(ui->sbSubmode->value());
});
m_wideGraph->hide();
m_fastGraph->showNormal();
ui->TxFreqSpinBox->setValue(1500);
@ -7582,10 +7388,6 @@ void MainWindow::on_actionMSK144_triggered()
void MainWindow::on_actionWSPR_triggered()
{
m_mode="WSPR";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
WSPR_config(true);
switch_mode (Modes::WSPR);
m_TRperiod=120.0;
@ -7622,10 +7424,6 @@ void MainWindow::on_actionEcho_triggered()
if(nd==3) ui->actionDeepestDecode->setChecked (true);
m_mode="Echo";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionEcho->setChecked(true);
m_TRperiod=3.0;
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
@ -7660,10 +7458,6 @@ void MainWindow::on_actionFreqCal_triggered()
{
on_actionJT9_triggered();
m_mode="FreqCal";
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
ui->actionFreqCal->setChecked(true);
switch_mode(Modes::FreqCal);
m_wideGraph->setMode(m_mode);
@ -7858,7 +7652,6 @@ void MainWindow::on_actionDeepestDecode_toggled (bool checked)
void MainWindow::on_actionInclude_averaging_toggled (bool checked)
{
m_ndepth ^= (-checked ^ m_ndepth) & 0x00000010;
statusChanged();
}
void MainWindow::on_actionInclude_correlation_toggled (bool checked)
@ -8215,7 +8008,6 @@ void MainWindow::setXIT(int n, Frequency base)
void MainWindow::setFreq4(int rxFreq, int txFreq)
{
if (m_mode=="ECHO") return; // we do not adjust rx/tx for echo mode -- always 1500Hz
if (ui->RxFreqSpinBox->isEnabled ()) ui->RxFreqSpinBox->setValue(rxFreq);
if(m_mode=="WSPR" or m_mode=="FST4W") {
ui->WSPRfreqSpinBox->setValue(txFreq);
@ -8657,14 +8449,6 @@ void MainWindow::on_sbFtol_valueChanged(int value)
{
m_wideGraph->setTol (value);
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue ("Ftol_Q65", ui->sbFtol->value());
if (m_mode=="MSK144") m_settings->setValue ("Ftol_MSK144", ui->sbFtol->value());
if (m_mode=="JT65") m_settings->setValue ("Ftol_JT65", ui->sbFtol->value ());
if (m_mode=="JT4") m_settings->setValue ("Ftol_JT4", ui->sbFtol->value());
if (m_mode=="JT9") m_settings->setValue ("Ftol_JT9", ui->sbFtol->value ());
});
}
void::MainWindow::VHF_features_enabled(bool b)
@ -8726,25 +8510,19 @@ void MainWindow::on_sbTR_valueChanged(int value)
m_wideGraph->setPeriod (value, m_nsps);
progressBar.setMaximum (value);
}
if (m_mode=="Q65") {
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_Q65", ui->sbTR->value ());});
}
if (m_mode=="MSK144") {
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_MSK144", ui->sbTR->value ());});
}
if (m_mode=="FST4") {
chk_FST4_freq_range();
QTimer::singleShot (200, [=] {m_settings->setValue ("TRPeriod_FST4", ui->sbTR->value ());});
}
// if(m_transmitting) on_stopTxButton_clicked(); //### Is this needed or desirable? ###
if (m_mode=="FST4") chk_FST4_freq_range();
on_sbSubmode_valueChanged(ui->sbSubmode->value());
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue ("TRPeriod_Q65", ui->sbTR->value ());
if (m_mode=="MSK144" && (!(m_currentBand=="6m" or m_currentBand=="4m" or m_currentBand=="2m"))) {
m_settings->setValue ("TRPeriod_MSK144", ui->sbTR->value ());
}
if (m_mode=="MSK144" && (m_currentBand=="6m" or m_currentBand=="4m")) {
m_settings->setValue ("TRPeriod_MSK144_6m", ui->sbTR->value ());
}
if (m_mode=="MSK144" && m_currentBand=="2m") {
m_settings->setValue ("TRPeriod_MSK144_2m", ui->sbTR->value ());
}
if (m_mode=="FST4") m_settings->setValue ("TRPeriod_FST4", ui->sbTR->value ());
if (m_mode=="JT9") m_settings->setValue ("TRPeriod", ui->sbTR->value ());
});
}
void MainWindow::on_sbTR_FST4W_valueChanged(int value)
@ -8791,21 +8569,17 @@ void MainWindow::on_sbSubmode_valueChanged(int n)
ui->sbTR->setVisible(false);
m_TRperiod=60.0;
} else {
if(!blocked) ui->cbFast9->setEnabled(true);
ui->cbFast9->setEnabled(true);
}
ui->sbTR->setVisible(m_bFast9);
if(m_bFast9) ui->TxFreqSpinBox->setValue(700);
}
if(m_transmitting and m_bFast9 and m_nSubMode>=4) transmit (99.0);
if (m_mode !="Q65") ui->TxFreqSpinBox->setStyleSheet("");
if (m_mode=="Q65") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_Q65",ui->sbSubmode->value());});}
if (m_mode=="JT65") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_JT65",ui->sbSubmode->value());});}
if (m_mode=="JT4") {QTimer::singleShot (200, [=] {m_settings->setValue("SubMode_JT4",ui->sbSubmode->value());});}
statusUpdate ();
// save last used parameters
QTimer::singleShot (200, [=] {
if (m_mode=="Q65") m_settings->setValue("SubMode_Q65",ui->sbSubmode->value());
if (m_mode=="JT65") m_settings->setValue("SubMode_JT65",ui->sbSubmode->value());
if (m_mode=="JT4") m_settings->setValue("SubMode_JT4",ui->sbSubmode->value());
if (m_mode=="JT9") m_settings->setValue("SubMode",ui->sbSubmode->value());
});
}
void MainWindow::on_cbFast9_clicked(bool b)
@ -8813,12 +8587,7 @@ void MainWindow::on_cbFast9_clicked(bool b)
if(m_mode=="JT9") {
m_bFast9=b;
// ui->cbAutoSeq->setVisible(b);
blocked=true; // needed to prevent a loop
on_actionJT9_triggered();
QTimer::singleShot (50, [=] {blocked = false;}); // needed to prevent a loop
QTimer::singleShot (200, [=] {
if(m_mode=="JT9") m_settings->setValue("JT9_Fast",m_bFast9);
});
}
if(b) {
@ -8850,12 +8619,6 @@ void MainWindow::on_cbShMsgs_toggled(bool b)
if(ntx==4) ui->txrb4->setChecked(true);
if(ntx==5) ui->txrb5->setChecked(true);
if(ntx==6) ui->txrb6->setChecked(true);
QTimer::singleShot (200, [=] {
if(m_mode=="MSK144") m_settings->setValue("ShMsgs_MSK144",m_bShMsgs);
if(m_mode=="Q65") m_settings->setValue("ShMsgs_Q65",m_bShMsgs);
if(m_mode=="JT65") m_settings->setValue("ShMsgs_JT65",m_bShMsgs);
if(m_mode=="JT4") m_settings->setValue("ShMsgs_JT4",m_bShMsgs);
});
}
void MainWindow::on_cbSWL_toggled(bool b)
@ -9060,7 +8823,6 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
}
killFileTimer.start (45*1000); //Kill in 45s (for slow modes)
}
ndecodes_label.setText(QString::number(m_nWSPRdecodes));
m_nWSPRdecodes=0;
ui->DecodeButton->setChecked (false);
if(m_uploadWSPRSpots && m_config.is_transceiver_online()) { // need working rig control
@ -9678,35 +9440,28 @@ void MainWindow::readWidebandDecodes()
if(m_ActiveStationsWidget==NULL) return;
int nhr=0;
int nmin=0;
int nsec=0;
int nsnr=0;
while(m_fetched < qmapcom.ndecodes) {
// Recover and parse each decoded line.
QString line=QString::fromLatin1(qmapcom.result[m_fetched]);
m_fetched++;
nhr=line.mid(0,2).toInt();
nmin=line.mid(2,2).toInt();
nsec=line.mid(4,2).toInt();
double frx=line.mid(6,9).toDouble();
double fsked=line.mid(16,7).toDouble();
QString submode=line.mid(36,3);
QString msg=line.mid(41,-1);
double frx=line.mid(4,9).toDouble();
double fsked=line.mid(13,7).toDouble();
QString msg=line.mid(34,-1);
int i1=msg.indexOf(" ");
int i2=i1 +1 + msg.mid(i1+1,-1).indexOf(" ");
QString dxcall=msg.mid(i1+1,i2-i1-1);
if(stdCall(dxcall)) {
QString w3=msg.mid(i2+1,-1);
nsnr=line.mid(31,3).toInt();
nsnr=line.mid(29,3).toInt();
m_EMECall[dxcall].frx=frx;
m_EMECall[dxcall].fsked=fsked;
m_EMECall[dxcall].nsnr=nsnr;
m_EMECall[dxcall].t=3600*nhr + 60*nmin + nsec;
m_EMECall[dxcall].submode=submode;
//### Make sure WSJT-X is set to a Q65 submode consistent with the executing QMAP.
m_EMECall[dxcall].t=60*nhr + nmin;
if(w3.contains(grid_regexp)) m_EMECall[dxcall].grid4=w3;
bool bCQ=line.contains(" CQ ");
// m_EMECall[dxcall].ready2call=(bCQ or line.contains(" 73") or line.contains(" RR73"));
m_EMECall[dxcall].ready2call=(bCQ);
m_EMECall[dxcall].ready2call=(bCQ or line.contains(" 73") or line.contains(" RR73"));
Frequency frequency = (m_freqNominal/1000000) * 1000000 + int(fsked*1000.0);
bool bFromDisk=qmapcom.nQDecoderDone==2;
if(!bFromDisk and (m_EMECall[dxcall].grid4.contains(grid_regexp) or bCQ)) {
@ -9742,11 +9497,8 @@ void MainWindow::readWidebandDecodes()
if(m_ActiveStationsWidget->readyOnly() and !i->ready2call) bSkip=true;
if(!bSkip) {
int snr=i->nsnr;
QString submode=i->submode;
int odd=0;
if(submode.left(2)=="30" and (i->t%60)==0) odd=1;
if(submode.left(2)=="60" and (i->t%120)==0) odd=1;
int age=(3600*nhr + 60*nmin + nsec - (i->t))/60;
int odd=1 - (i->t)%2;
int age=60*nhr + nmin - (i->t);
char c2[3]={32,32,0};
if(age<0) age += 1440;
if(age<=maxAge) {
@ -9754,8 +9506,7 @@ void MainWindow::readWidebandDecodes()
dxgrid4=(i->grid4+"... ").left(4);
if(!m_EMEworked[dxcall.trimmed()]) c2[0]=35; //# for not in log
if(i->ready2call) c2[1]=42; //* for ready to call
t1=t1.asprintf("%7.3f %5.1f %+03d %3s %8s %4s %3d %3d %2s\n",i->frx,i->fsked,snr,
submode.toLatin1().constData(),dxcall.toLatin1().constData(),
t1=t1.asprintf("%7.3f %5.1f %+03d %8s %4s %3d %3d %2s\n",i->frx,i->fsked,snr,dxcall.toLatin1().constData(),
dxgrid4.toLatin1().constData(),odd,age,c2);
f[k]=i->fsked;
list.append(t1);
@ -10213,6 +9964,9 @@ list1Done:
break;
}
if(m_foxQSO.count()>=5*3 /* could have 5 slots * 3 states ([0-2],4,5) */) {
break;
}
}
list2Done:
@ -10721,7 +10475,7 @@ void MainWindow::remote_configure (QString const& mode, quint32 frequency_tolera
{
if (mode.size ())
{
if (mode != m_mode) set_mode (mode);
set_mode (mode);
}
auto is_FST4W = "FST4W" == m_mode;
if (frequency_tolerance != quint32_max && (ui->sbFtol->isVisible () || is_FST4W))
@ -10842,7 +10596,7 @@ void MainWindow::on_houndButton_clicked (bool checked)
void MainWindow::on_ft8Button_clicked()
{
if (m_specOp==SpecOp::HOUND) {
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
@ -10851,17 +10605,25 @@ void MainWindow::on_ft8Button_clicked()
void MainWindow::on_ft4Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionFT4_triggered();
}
void MainWindow::on_msk144Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionMSK144_triggered();
}
void MainWindow::on_q65Button_clicked()
{
if (m_specOp==SpecOp::Q65_PILEUP) {
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
@ -10870,5 +10632,9 @@ void MainWindow::on_q65Button_clicked()
void MainWindow::on_jt65Button_clicked()
{
if(m_specOp==SpecOp::HOUND) {
m_config.setSpecial_None();
m_specOp=m_config.special_op_id();
}
on_actionJT65_triggered();
}

View File

@ -719,7 +719,6 @@ private:
qint32 t;
bool worked;
bool ready2call;
QString submode;
};
QMap<QString,EMECall> m_EMECall;

View File

@ -3017,7 +3017,7 @@ QLabel[oob=&quot;true&quot;] {
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to Q65 mode.&lt;br&gt; Right-click to switch to Q65 Pileup mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to Q65 mode. Right-click to toggle Q65 Pileup mode On/Off.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Q65</string>
@ -3038,11 +3038,8 @@ QLabel[oob=&quot;true&quot;] {
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to JT65 mode. &lt;br&gt;Right-click to switch to JT9 mode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>Switch to JT65 mode</string>
</property>
<property name="text">
<string>JT65</string>

View File

@ -263,7 +263,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
painter1.drawText (5, painter1.fontMetrics ().ascent (), t);
}
if(m_mode=="JT4" or (m_mode=="Q65" and m_nSubMode>=3)) {
if(m_mode=="JT4" or (m_mode=="Q65" and m_nSubMode>=2)) {
DrawOverlay();
QPen pen3(Qt::yellow); //Mark freqs of JT4/Q65 single-tone msgs
painter2D.setPen(pen3);