mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-08-27 09:52:35 -04:00
Compare commits
17 Commits
wsjtx-2.7.
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
2b9d65408d | ||
|
c5a266b5e0 | ||
|
de9dc8e3fb | ||
|
5e410a982b | ||
|
2a9d0b6998 | ||
|
75f6b9b423 | ||
|
c7a93fca4a | ||
|
08785eff56 | ||
|
40fbc208fd | ||
|
1ac2fc23c3 | ||
|
d4a5ea60e6 | ||
|
86fd50304f | ||
|
75b4e0e798 | ||
|
ee68285583 | ||
|
ae50058498 | ||
|
587a16cd21 | ||
|
45151bda3b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,6 +7,7 @@ GTAGS
|
||||
*~
|
||||
junk*
|
||||
jnq*
|
||||
*.exe
|
||||
*.o
|
||||
*.mod
|
||||
*.pro.user
|
||||
|
@ -148,6 +148,7 @@ void SoundOutput::stop ()
|
||||
m_stream->reset ();
|
||||
m_stream->stop ();
|
||||
}
|
||||
m_stream.reset ();
|
||||
}
|
||||
|
||||
qreal SoundOutput::attenuation () const
|
||||
|
@ -50,7 +50,6 @@ project (wsjtx
|
||||
)
|
||||
set (PROJECT_DESCRIPTION "WSJT-X: Digital Modes for Weak Signal Communications in Amateur Radio")
|
||||
set (CMAKE_PROJECT_DESCRIPTION ${PROJECT_DESCRIPTION})
|
||||
set (CMAKE_AUTOUIC ON)
|
||||
|
||||
#
|
||||
# Local CMake modules and support files
|
||||
@ -72,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 7)
|
||||
set_build_type (RC 4)
|
||||
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
|
||||
|
||||
#
|
||||
@ -81,7 +80,7 @@ set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_
|
||||
set (PROJECT_BUNDLE_NAME "WSJT-X")
|
||||
set (PROJECT_VENDOR "Joe Taylor, K1JT")
|
||||
set (PROJECT_CONTACT "Joe Taylor <k1jt@arrl.net>")
|
||||
set (PROJECT_COPYRIGHT "Copyright (C) 2001-2024 by Joe Taylor, K1JT")
|
||||
set (PROJECT_COPYRIGHT "Copyright (C) 2001-2023 by Joe Taylor, K1JT")
|
||||
set (PROJECT_HOMEPAGE https://wsjt.sourceforge.io/wsjtx.html)
|
||||
set (PROJECT_MANUAL wsjtx-main)
|
||||
set (PROJECT_MANUAL_DIRECTORY_URL https://wsjt.sourceforge.io/wsjtx-doc/)
|
||||
@ -127,7 +126,6 @@ option (WSJT_GENERATE_DOCS "Generate documentation files." ON)
|
||||
option (WSJT_RIG_NONE_CAN_SPLIT "Allow split operation with \"None\" as rig.")
|
||||
option (WSJT_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.")
|
||||
option (WSJT_BUILD_UTILS "Build simulators and code demonstrators." ON)
|
||||
option (WSJT_FOX_OTP "Enable Fox OTP Verification Messages." ON)
|
||||
CMAKE_DEPENDENT_OPTION (WSJT_QDEBUG_IN_RELEASE "Leave Qt debugging statements in Release configuration." OFF
|
||||
"NOT is_debug_build" OFF)
|
||||
CMAKE_DEPENDENT_OPTION (WSJT_ENABLE_EXPERIMENTAL_FEATURES "Enable features not fully ready for public releases." ON
|
||||
@ -163,13 +161,6 @@ 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")
|
||||
|
||||
if (WSJT_FOX_OTP)
|
||||
set (wsjt_fox_CXXSRCS
|
||||
|
||||
)
|
||||
message (STATUS "Including Fox verification code feature")
|
||||
endif ()
|
||||
|
||||
#
|
||||
# Project sources
|
||||
#
|
||||
@ -231,7 +222,6 @@ set (wsjt_qt_CXXSRCS
|
||||
widgets/DoubleClickableRadioButton.cpp
|
||||
Network/LotWUsers.cpp
|
||||
Network/FileDownload.cpp
|
||||
Network/FoxVerifier.cpp
|
||||
models/DecodeHighlightingModel.cpp
|
||||
widgets/DecodeHighlightingListView.cpp
|
||||
models/FoxLog.cpp
|
||||
@ -251,7 +241,6 @@ set (wsjt_qt_CXXSRCS
|
||||
widgets/LazyFillComboBox.cpp
|
||||
widgets/CheckableItemComboBox.cpp
|
||||
widgets/BandComboBox.cpp
|
||||
otpgenerator.cpp
|
||||
)
|
||||
|
||||
set (wsjt_qtmm_CXXSRCS
|
||||
@ -302,7 +291,6 @@ set (wsjt_CXXSRCS
|
||||
lib/crc10.cpp
|
||||
lib/crc13.cpp
|
||||
lib/crc14.cpp
|
||||
${wsjt_fox_CXXSRCS}
|
||||
)
|
||||
# deal with a GCC v6 UB error message
|
||||
set_source_files_properties (
|
||||
@ -353,10 +341,6 @@ set (wsjt_FSRCS
|
||||
lib/wavhdr.f90
|
||||
lib/qra/q65/q65_encoding_modules.f90
|
||||
lib/ft8/ft8_a7.f90
|
||||
lib/superfox/sfox_mod.f90
|
||||
lib/superfox/julian.f90
|
||||
lib/superfox/popen_module.f90
|
||||
lib/superfox/qpc/qpc_mod.f90
|
||||
|
||||
# remaining non-module sources
|
||||
lib/addit.f90
|
||||
@ -442,7 +426,7 @@ set (wsjt_FSRCS
|
||||
lib/fspread_lorentz.f90
|
||||
lib/ft8/foxfilt.f90
|
||||
lib/ft8/foxgen.f90
|
||||
# lib/ft8/foxgen_wrap.f90
|
||||
lib/ft8/foxgen_wrap.f90
|
||||
lib/freqcal.f90
|
||||
lib/ft8/ft8apset.f90
|
||||
lib/ft8/ft8b.f90
|
||||
@ -601,27 +585,6 @@ set (wsjt_FSRCS
|
||||
lib/fst4/get_crc24.f90
|
||||
lib/fst4/fst4_baseline.f90
|
||||
lib/77bit/hash22calc.f90
|
||||
|
||||
lib/superfox/foxgen2.f90
|
||||
lib/superfox/qpc_decode2.f90
|
||||
lib/superfox/qpc_likelihoods2.f90
|
||||
lib/superfox/qpc_snr.f90
|
||||
lib/superfox/qpc_sync.f90
|
||||
lib/superfox/sfox_ana.f90
|
||||
lib/superfox/sfox_assemble.f90
|
||||
lib/superfox/sfox_demod.f90
|
||||
lib/superfox/sfox_pack.f90
|
||||
lib/superfox/sfox_remove_ft8.f90
|
||||
lib/superfox/sfox_remove_tone.f90
|
||||
lib/superfox/sfox_unpack.f90
|
||||
lib/superfox/sfox_wave.f90
|
||||
lib/superfox/sfox_wave_gfsk.f90
|
||||
lib/superfox/sfrx_sub.f90
|
||||
lib/superfox/sftx_sub.f90
|
||||
lib/superfox/twkfreq2.f90
|
||||
lib/superfox/sfox_gen_gfsk.f90
|
||||
lib/superfox/ran1.f90
|
||||
lib/superfox/sfoxsim.f90
|
||||
)
|
||||
|
||||
# temporary workaround for a gfortran v7.3 ICE on Fedora 27 64-bit
|
||||
@ -664,15 +627,6 @@ set (wsjt_CSRCS
|
||||
lib/wrapkarn.c
|
||||
${ldpc_CSRCS}
|
||||
${qra_CSRCS}
|
||||
|
||||
lib/superfox/qpc/dbgprintf.c
|
||||
lib/superfox/qpc/nhash2.c
|
||||
lib/superfox/qpc/np_qpc.c
|
||||
lib/superfox/qpc/np_rnd.c
|
||||
lib/superfox/qpc/qpc_fwht.c
|
||||
lib/superfox/qpc/qpc_n127k50q128.c
|
||||
lib/superfox/qpc/qpc_subs.c
|
||||
|
||||
)
|
||||
|
||||
set (wsjt_qt_UISRCS
|
||||
@ -946,9 +900,7 @@ check_type_size (CACHE_ALL HAMLIB_OLD_CACHING)
|
||||
check_symbol_exists (rig_set_cache_timeout_ms "hamlib/rig.h" HAVE_HAMLIB_CACHING)
|
||||
|
||||
find_package (Usb REQUIRED)
|
||||
if (WSJT_FOX_OTP)
|
||||
add_definitions (-DFOX_OTP)
|
||||
endif ()
|
||||
|
||||
#
|
||||
# Qt5 setup
|
||||
#
|
||||
@ -1201,9 +1153,6 @@ target_link_libraries (test_snr wsjt_fort)
|
||||
add_executable (q65sim lib/qra/q65/q65sim.f90)
|
||||
target_link_libraries (q65sim wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (cwsim lib/cwsim.f90)
|
||||
target_link_libraries (cwsim wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (q65code lib/qra/q65/q65code.f90)
|
||||
target_link_libraries (q65code wsjt_fort wsjt_cxx)
|
||||
|
||||
@ -1258,15 +1207,6 @@ target_link_libraries (echosim wsjt_fort wsjt_cxx)
|
||||
add_executable (ft8sim lib/ft8/ft8sim.f90)
|
||||
target_link_libraries (ft8sim wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (sfoxsim lib/superfox/sfoxsim.f90)
|
||||
target_link_libraries (sfoxsim wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (sfrx lib/superfox/sfrx.f90)
|
||||
target_link_libraries (sfrx wsjt_fort wsjt_cxx)
|
||||
|
||||
#add_executable (sftx lib/superfox/sftx.f90)
|
||||
#target_link_libraries (sftx wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (msk144sim lib/msk144sim.f90)
|
||||
target_link_libraries (msk144sim wsjt_fort wsjt_cxx)
|
||||
|
||||
@ -1351,7 +1291,9 @@ set (LANGUAGES
|
||||
ru # Russian
|
||||
#sv # Swedish
|
||||
zh # Chinese
|
||||
zh_HK # Chinese per Hong Kong
|
||||
zh_TW # Chinese traditional
|
||||
it # Italian
|
||||
)
|
||||
foreach (lang_ ${LANGUAGES})
|
||||
file (TO_NATIVE_PATH ${CMAKE_SOURCE_DIR}/translations/wsjtx_${lang_}.ts ts_)
|
||||
@ -1654,7 +1596,7 @@ install (TARGETS udp_daemon message_aggregator wsjtx_app_version
|
||||
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||
)
|
||||
|
||||
install (TARGETS jt9 wsprd fmtave fcal fmeasure
|
||||
install (TARGETS jt9 wsprd fmtave fcal fmeasure
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||
)
|
||||
|
@ -193,7 +193,6 @@
|
||||
#include "models/FrequencyList.hpp"
|
||||
#include "models/StationList.hpp"
|
||||
#include "Network/NetworkServerLookup.hpp"
|
||||
#include "Network/FoxVerifier.hpp"
|
||||
#include "widgets/MessageBox.hpp"
|
||||
#include "validators/MaidenheadLocatorValidator.hpp"
|
||||
#include "validators/CallsignValidator.hpp"
|
||||
@ -280,7 +279,6 @@ namespace
|
||||
constexpr quint32 qrg_version_100 {100};
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Dialog to get a new Frequency item
|
||||
//
|
||||
@ -388,7 +386,6 @@ private:
|
||||
QDateTimeEdit *start_date_time_edit_;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Dialog to get a new Station item
|
||||
//
|
||||
@ -461,9 +458,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Internal implementation of the Configuration class.
|
||||
class Configuration::impl final
|
||||
: public QDialog
|
||||
@ -585,25 +579,9 @@ private:
|
||||
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);
|
||||
Q_SLOT void on_gbSpecialOpActivity_clicked (bool);
|
||||
Q_SLOT void on_rbFox_clicked (bool);
|
||||
Q_SLOT void on_rbHound_clicked (bool);
|
||||
Q_SLOT void on_rbNA_VHF_Contest_clicked (bool);
|
||||
Q_SLOT void on_rbEU_VHF_Contest_clicked (bool);
|
||||
Q_SLOT void on_rbWW_DIGI_clicked (bool);
|
||||
Q_SLOT void on_rbQ65pileup_clicked (bool);
|
||||
Q_SLOT void on_rbField_Day_clicked (bool);
|
||||
Q_SLOT void on_rbRTTY_Roundup_clicked (bool);
|
||||
Q_SLOT void on_rbARRL_Digi_clicked (bool);
|
||||
Q_SLOT void on_cbSuperFox_clicked (bool);
|
||||
Q_SLOT void on_cbContestName_clicked (bool);
|
||||
Q_SLOT void on_cbOTP_clicked (bool);
|
||||
Q_SLOT void on_cbShowOTP_clicked (bool);
|
||||
|
||||
void error_during_hamlib_download (QString const& reason);
|
||||
void after_hamlib_downloaded();
|
||||
void display_file_information();
|
||||
void check_visibility();
|
||||
|
||||
Q_SLOT void on_cbx2ToneSpacing_clicked(bool);
|
||||
Q_SLOT void on_cbx4ToneSpacing_clicked(bool);
|
||||
@ -611,8 +589,6 @@ private:
|
||||
Q_SLOT void on_cbAutoLog_clicked(bool);
|
||||
Q_SLOT void on_Field_Day_Exchange_textEdited (QString const&);
|
||||
Q_SLOT void on_RTTY_Exchange_textEdited (QString const&);
|
||||
Q_SLOT void on_OTPUrl_textEdited (QString const&);
|
||||
Q_SLOT void on_OTPSeed_textEdited (QString const&);
|
||||
Q_SLOT void on_Contest_Name_textEdited (QString const&);
|
||||
|
||||
// typenames used as arguments must match registered type names :(
|
||||
@ -712,12 +688,6 @@ private:
|
||||
QString Contest_Name_;
|
||||
QString hamlib_backed_up_;
|
||||
|
||||
QString OTPUrl_;
|
||||
QString OTPSeed_;
|
||||
bool OTPEnabled_;
|
||||
bool ShowOTP_;
|
||||
qint32 OTPinterval_;
|
||||
|
||||
qint32 id_interval_;
|
||||
qint32 ntrials_;
|
||||
qint32 aggressive_;
|
||||
@ -750,7 +720,6 @@ private:
|
||||
bool decode_at_52s_;
|
||||
bool single_decode_;
|
||||
bool twoPass_;
|
||||
bool bSuperFox_;
|
||||
bool Individual_Contest_Name_;
|
||||
bool bSpecialOp_;
|
||||
int SelectedActivity_;
|
||||
@ -792,7 +761,6 @@ private:
|
||||
|
||||
#include "Configuration.moc"
|
||||
|
||||
|
||||
// delegate to implementation class
|
||||
Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
|
||||
QSettings * settings, LogBook * logbook, QWidget * parent)
|
||||
@ -859,7 +827,6 @@ bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features
|
||||
bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;}
|
||||
bool Configuration::single_decode () const {return m_->single_decode_;}
|
||||
bool Configuration::twoPass() const {return m_->twoPass_;}
|
||||
bool Configuration::superFox() const {return m_->bSuperFox_;}
|
||||
bool Configuration::Individual_Contest_Name() const {return m_->Individual_Contest_Name_;}
|
||||
bool Configuration::x2ToneSpacing() const {return m_->x2ToneSpacing_;}
|
||||
bool Configuration::x4ToneSpacing() const {return m_->x4ToneSpacing_;}
|
||||
@ -988,26 +955,6 @@ void Configuration::invalidate_audio_output_device (QString /* error */)
|
||||
m_->audio_output_device_ = QAudioDeviceInfo {};
|
||||
}
|
||||
|
||||
// OTP seed can be empty, in which case it is not used, or a valid 16 character base32 string.
|
||||
bool Configuration::validate_otp_seed(QString seed)
|
||||
{
|
||||
if (seed.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (seed.size() != 16)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (QChar c: seed)
|
||||
{
|
||||
if (!QString(BASE32_CHARSET).contains(c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Configuration::valid_n1mm_info () const
|
||||
{
|
||||
// do very rudimentary checking on the n1mm server name and port number.
|
||||
@ -1097,43 +1044,6 @@ void Configuration::setSpecial_None()
|
||||
m_->SelectedActivity_ = static_cast<int> (SpecialOperatingActivity::HOUND); // brings backward compatibility to versions without Q65_PILEUP
|
||||
m_->write_settings();
|
||||
}
|
||||
|
||||
void Configuration::toggle_SF()
|
||||
{
|
||||
if (m_->bSuperFox_) {
|
||||
m_->ui_->cbSuperFox->setChecked(false);
|
||||
} else {
|
||||
m_->ui_->cbSuperFox->setChecked(true);
|
||||
}
|
||||
m_->bSuperFox_ = m_->ui_->cbSuperFox->isChecked ();
|
||||
m_->write_settings();
|
||||
}
|
||||
|
||||
QString Configuration::OTPSeed() const
|
||||
{
|
||||
return m_->OTPSeed_;
|
||||
}
|
||||
|
||||
QString Configuration::OTPUrl() const
|
||||
{
|
||||
return m_->OTPUrl_;
|
||||
}
|
||||
|
||||
unsigned int Configuration::OTPinterval() const
|
||||
{
|
||||
return m_->OTPinterval_;
|
||||
}
|
||||
|
||||
bool Configuration::OTPEnabled() const
|
||||
{
|
||||
return m_->OTPSeed_.size() == 16 && m_->OTPEnabled_;
|
||||
}
|
||||
|
||||
bool Configuration::ShowOTP () const
|
||||
{
|
||||
return m_->ShowOTP_;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
#if defined (Q_OS_MAC)
|
||||
@ -1304,8 +1214,6 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
||||
ui_->add_macro_line_edit->setValidator (new QRegularExpressionValidator {message_alphabet, this});
|
||||
ui_->Field_Day_Exchange->setValidator (new QRegularExpressionValidator {field_day_exchange_re, this});
|
||||
ui_->RTTY_Exchange->setValidator (new QRegularExpressionValidator {RTTY_roundup_exchange_re, this});
|
||||
QRegularExpression b32(QString("(^[") + QString(BASE32_CHARSET)+QString(BASE32_CHARSET).toLower() + QString("]{16}$)|(^$)"));
|
||||
ui_->OTPSeed->setValidator(new QRegularExpressionValidator(b32, this));
|
||||
|
||||
//
|
||||
// assign ids to radio buttons
|
||||
@ -1549,7 +1457,6 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->decode_at_52s_check_box->setChecked(decode_at_52s_);
|
||||
ui_->single_decode_check_box->setChecked(single_decode_);
|
||||
ui_->cbTwoPass->setChecked(twoPass_);
|
||||
ui_->cbSuperFox->setChecked(bSuperFox_);
|
||||
ui_->cbContestName->setChecked(Individual_Contest_Name_);
|
||||
ui_->gbSpecialOpActivity->setChecked(bSpecialOp_);
|
||||
ui_->special_op_activity_button_group->button (SelectedActivity_)->setChecked (true);
|
||||
@ -1633,8 +1540,6 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->cbHighlightDXcall->setChecked(highlight_DXcall_);
|
||||
ui_->cbHighlightDXgrid->setChecked(highlight_DXgrid_);
|
||||
|
||||
check_visibility ();
|
||||
|
||||
set_rig_invariants ();
|
||||
}
|
||||
|
||||
@ -1669,19 +1574,6 @@ void Configuration::impl::read_settings ()
|
||||
ui_->Contest_Name->setText(Contest_Name_);
|
||||
hamlib_backed_up_ = settings_->value ("HamlibBackedUp",QString {}).toString ();
|
||||
|
||||
OTPinterval_ = settings_->value ("OTPinterval", 1).toUInt ();
|
||||
OTPUrl_ = settings_->value ("OTPUrl", FoxVerifier::default_url()).toString ();
|
||||
OTPSeed_ = settings_->value ("OTPSeed", QString {}).toString ();
|
||||
OTPEnabled_ = settings_->value ("OTPEnabled", false).toBool ();
|
||||
ShowOTP_ = settings_->value ("ShowOTP", false).toBool ();
|
||||
|
||||
ui_->sbOTPinterval->setValue(OTPinterval_);
|
||||
ui_->OTPUrl->setText(OTPUrl_);
|
||||
ui_->OTPSeed->setText(OTPSeed_);
|
||||
ui_->cbOTP->setChecked(OTPEnabled_);
|
||||
ui_->cbShowOTP->setChecked(ShowOTP_);
|
||||
|
||||
|
||||
if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
|
||||
&& next_font_ != font_)
|
||||
{
|
||||
@ -1833,7 +1725,6 @@ void Configuration::impl::read_settings ()
|
||||
decode_at_52s_ = settings_->value("Decode52",false).toBool ();
|
||||
single_decode_ = settings_->value("SingleDecode",false).toBool ();
|
||||
twoPass_ = settings_->value("TwoPass",true).toBool ();
|
||||
bSuperFox_ = settings_->value("SuperFox",true).toBool ();
|
||||
Individual_Contest_Name_ = settings_->value("Individual_Contest_Name",true).toBool ();
|
||||
bSpecialOp_ = settings_->value("SpecialOpActivity",false).toBool ();
|
||||
SelectedActivity_ = settings_->value("SelectedActivity",1).toInt ();
|
||||
@ -1982,7 +1873,6 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("Decode52", decode_at_52s_);
|
||||
settings_->setValue ("SingleDecode", single_decode_);
|
||||
settings_->setValue ("TwoPass", twoPass_);
|
||||
settings_->setValue ("SuperFox", bSuperFox_);
|
||||
settings_->setValue ("Individual_Contest_Name", Individual_Contest_Name_);
|
||||
settings_->setValue ("SelectedActivity", SelectedActivity_);
|
||||
settings_->setValue ("SpecialOpActivity", bSpecialOp_);
|
||||
@ -2007,11 +1897,6 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("AutoGrid", use_dynamic_grid_);
|
||||
settings_->setValue ("highlight_DXcall", highlight_DXcall_);
|
||||
settings_->setValue ("highlight_DXgrid", highlight_DXgrid_);
|
||||
settings_->setValue ("OTPinterval", OTPinterval_);
|
||||
settings_->setValue ("OTPUrl", OTPUrl_);
|
||||
settings_->setValue ("OTPSeed", OTPSeed_);
|
||||
settings_->setValue ("OTPEnabled", OTPEnabled_);
|
||||
settings_->setValue ("ShowOTP", ShowOTP_);
|
||||
settings_->sync ();
|
||||
}
|
||||
|
||||
@ -2417,7 +2302,6 @@ void Configuration::impl::accept ()
|
||||
decode_at_52s_ = ui_->decode_at_52s_check_box->isChecked ();
|
||||
single_decode_ = ui_->single_decode_check_box->isChecked ();
|
||||
twoPass_ = ui_->cbTwoPass->isChecked ();
|
||||
bSuperFox_ = ui_->cbSuperFox->isChecked ();
|
||||
Individual_Contest_Name_ = ui_->cbContestName->isChecked ();
|
||||
bSpecialOp_ = ui_->gbSpecialOpActivity->isChecked ();
|
||||
SelectedActivity_ = ui_->special_op_activity_button_group->checkedId();
|
||||
@ -2428,11 +2312,6 @@ void Configuration::impl::accept ()
|
||||
pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked ();
|
||||
pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked ();
|
||||
opCall_=ui_->opCallEntry->text();
|
||||
OTPinterval_=ui_->sbOTPinterval->value();
|
||||
OTPSeed_=ui_->OTPSeed->text();
|
||||
OTPUrl_=ui_->OTPUrl->text();
|
||||
OTPEnabled_=ui_->cbOTP->isChecked();
|
||||
ShowOTP_=ui_->cbShowOTP->isChecked();
|
||||
|
||||
auto new_server = ui_->udp_server_line_edit->text ().trimmed ();
|
||||
auto new_interfaces = get_selected_network_interfaces (ui_->udp_interfaces_combo_box);
|
||||
@ -3222,160 +3101,6 @@ void Configuration::impl::on_cbx4ToneSpacing_clicked(bool b)
|
||||
if(b) ui_->cbx2ToneSpacing->setChecked(false);
|
||||
}
|
||||
|
||||
void Configuration::impl::on_gbSpecialOpActivity_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbFox_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbHound_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbNA_VHF_Contest_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbEU_VHF_Contest_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbWW_DIGI_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbQ65pileup_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbField_Day_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbRTTY_Roundup_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_rbARRL_Digi_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_cbSuperFox_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_cbContestName_clicked (bool)
|
||||
{
|
||||
check_visibility ();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_cbOTP_clicked(bool)
|
||||
{
|
||||
check_visibility();
|
||||
}
|
||||
|
||||
void Configuration::impl::on_cbShowOTP_clicked(bool)
|
||||
{
|
||||
check_visibility();
|
||||
}
|
||||
|
||||
void Configuration::impl::check_visibility ()
|
||||
{
|
||||
if (ui_->rbField_Day->isChecked() and ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->labFD->setEnabled (true);
|
||||
ui_->Field_Day_Exchange->setEnabled (true);
|
||||
} else {
|
||||
ui_->labFD->setEnabled (false);
|
||||
ui_->Field_Day_Exchange->setEnabled (false);
|
||||
}
|
||||
if (ui_->rbRTTY_Roundup->isChecked() and ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->labRTTY->setEnabled (true);
|
||||
ui_->RTTY_Exchange->setEnabled (true);
|
||||
} else {
|
||||
ui_->labRTTY->setEnabled (false);
|
||||
ui_->RTTY_Exchange->setEnabled (false);
|
||||
}
|
||||
if (ui_->cbContestName->isChecked() and !ui_->rbFox->isChecked() and !ui_->rbHound->isChecked()
|
||||
and !ui_->rbQ65pileup->isChecked() and ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->labCN->setEnabled (true);
|
||||
ui_->Contest_Name->setEnabled (true);
|
||||
} else {
|
||||
ui_->labCN->setEnabled (false);
|
||||
ui_->Contest_Name->setEnabled (false);
|
||||
}
|
||||
if ((ui_->rbFox->isChecked() or ui_->rbHound->isChecked()) and ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->cbSuperFox->setEnabled (true);
|
||||
ui_->cbOTP->setEnabled (true);
|
||||
} else {
|
||||
ui_->cbSuperFox->setEnabled (false);
|
||||
ui_->cbOTP->setEnabled (false);
|
||||
ui_->cbShowOTP->setEnabled(false);
|
||||
}
|
||||
if (!ui_->rbFox->isChecked() and !ui_->rbHound->isChecked() and !ui_->rbQ65pileup->isChecked()
|
||||
and ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->cbContestName->setEnabled (true);
|
||||
} else {
|
||||
ui_->cbContestName->setEnabled (false);
|
||||
}
|
||||
if (!ui_->cbOTP->isChecked() or !ui_->gbSpecialOpActivity->isChecked()) {
|
||||
ui_->OTPSeed->setEnabled(false);
|
||||
ui_->OTPUrl->setEnabled(false);
|
||||
ui_->sbOTPinterval->setEnabled(false);
|
||||
ui_->lblOTPSeed->setEnabled(false);
|
||||
ui_->lblOTPUrl->setEnabled(false);
|
||||
ui_->lblOTPEvery->setEnabled(false);
|
||||
ui_->cbShowOTP->setEnabled(false);
|
||||
} else {
|
||||
if (ui_->rbHound->isChecked()) {
|
||||
if (ui_->OTPUrl->text().isEmpty())
|
||||
{
|
||||
ui_->OTPUrl->setText(FoxVerifier::default_url());
|
||||
}
|
||||
ui_->OTPUrl->setEnabled(true);
|
||||
ui_->lblOTPUrl->setEnabled(true);
|
||||
ui_->cbShowOTP->setEnabled(true);
|
||||
} else {
|
||||
ui_->OTPUrl->setEnabled(false);
|
||||
ui_->lblOTPUrl->setEnabled(false);
|
||||
}
|
||||
if (ui_->rbFox->isChecked()) {
|
||||
ui_->sbOTPinterval->setEnabled(true);
|
||||
ui_->OTPSeed->setEnabled(true);
|
||||
ui_->lblOTPSeed->setEnabled(true);
|
||||
ui_->lblOTPEvery->setEnabled(true);
|
||||
ui_->cbShowOTP->setEnabled(false);
|
||||
} else {
|
||||
ui_->OTPSeed->setEnabled(false);
|
||||
ui_->lblOTPSeed->setEnabled(false);
|
||||
ui_->lblOTPEvery->setEnabled(false);
|
||||
ui_->sbOTPinterval->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Configuration::impl::on_OTPUrl_textEdited (QString const& url){
|
||||
auto text = url;
|
||||
if (text.size() == 0)
|
||||
{
|
||||
ui_->OTPUrl->setText(FoxVerifier::default_url());
|
||||
}
|
||||
}
|
||||
void Configuration::impl::on_OTPSeed_textEdited (QString const& url){
|
||||
ui_->OTPSeed->setText(url.toUpper());
|
||||
}
|
||||
|
||||
void Configuration::impl::on_Field_Day_Exchange_textEdited (QString const& exchange)
|
||||
{
|
||||
auto text = exchange.simplified ().toUpper ();
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "models/IARURegions.hpp"
|
||||
#include "Audio/AudioDevice.hpp"
|
||||
#include "Transceiver/Transceiver.hpp"
|
||||
#include "otpgenerator.h"
|
||||
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
@ -138,7 +137,6 @@ public:
|
||||
bool decode_at_52s () const;
|
||||
bool single_decode () const;
|
||||
bool twoPass() const;
|
||||
bool superFox() const;
|
||||
bool bFox() const;
|
||||
bool bHound() const;
|
||||
bool bLowSidelobes() const;
|
||||
@ -189,16 +187,10 @@ public:
|
||||
void setSpecial_Hound();
|
||||
void setSpecial_Fox();
|
||||
void setSpecial_None();
|
||||
void toggle_SF();
|
||||
bool highlight_DXcall () const;
|
||||
bool highlight_DXgrid () const;
|
||||
bool Individual_Contest_Name() const;
|
||||
bool validate_otp_seed(QString);
|
||||
QString OTPSeed() const;
|
||||
QString OTPUrl() const;
|
||||
bool OTPEnabled() const;
|
||||
bool ShowOTP() const;
|
||||
unsigned int OTPinterval() const;
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, WW_DIGI, FOX, HOUND, ARRL_DIGI, Q65_PILEUP};
|
||||
SpecialOperatingActivity special_op_id () const;
|
||||
@ -233,8 +225,7 @@ 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
|
||||
|
516
Configuration.ui
516
Configuration.ui
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>760</width>
|
||||
<height>648</height>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -1251,7 +1251,7 @@ a few, particularly some Kenwood rigs, require it).</string>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<layout class="QHBoxLayout" name="testCATPTT_Layout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="test_CAT_push_button">
|
||||
<property name="toolTip">
|
||||
@ -2907,8 +2907,49 @@ Right click for insert and delete options.</string>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15" columnstretch="1,1,0,2">
|
||||
<item row="2" column="3">
|
||||
<layout class="QGridLayout" name="gridLayout_15" columnstretch="1,0,0,0">
|
||||
<item row="0" column="3">
|
||||
<widget class="QRadioButton" name="rbHound">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>FT8 DXpedition mode: Hound operator calling the DX.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>Hound</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hound</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="rbNA_VHF_Contest">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>NA VHF Contest</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NA VHF</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17" stretch="2,1,1">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbField_Day">
|
||||
@ -2977,63 +3018,55 @@ Right click for insert and delete options.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<layout class="QHBoxLayout" name="OTP_Layout_2" stretch="0,0,0,1">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbShowOTP">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Show OTP messages in the Band Activity window.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show OTP messages</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblOTPUrl">
|
||||
<property name="text">
|
||||
<string>OTP URL:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="OTPUrl">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>URL used to verify OTP codes.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>https://www.9dx.cc</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<item row="3" column="3">
|
||||
<widget class="QRadioButton" name="rbARRL_Digi">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>ARRL International Digital Contest</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ARRL Digi Contest</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="0" column="1" rowspan="3">
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QRadioButton" name="rbWW_DIGI">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>World-Wide Digi-mode contest</p><p><br/></p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>WW Digital Contest</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>WW Digi Contest</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="rbQ65pileup">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
@ -3052,153 +3085,7 @@ Right click for insert and delete options.</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="rbNA_VHF_Contest">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>NA VHF Contest</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NA VHF</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QRadioButton" name="rbEU_VHF_Contest">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>European VHF+ contests requiring a signal report, serial number, and 6-character locator.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>EU VHF Contest</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>EU VHF Contest</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="cbSuperFox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Check this box to transmit (Fox) or receive (Hound) the SuperFox waveform.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SuperFox mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="rbFox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>FT8 DXpedition mode: Fox (DXpedition) operator.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>Fox</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Fox</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QRadioButton" name="rbARRL_Digi">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>ARRL International Digital Contest</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ARRL Digi Contest</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbContestName">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Call CQ with an individual contest name instead of TEST, RU, or WW. </p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CQ with individual contest name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_25">
|
||||
<item>
|
||||
<widget class="QLabel" name="labCN">
|
||||
<property name="text">
|
||||
<string>Contest name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="Contest_Name">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="cursorPosition">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="2" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="2,1,1">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbRTTY_Roundup">
|
||||
@ -3267,51 +3154,61 @@ Right click for insert and delete options.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="rbWW_DIGI">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>18</height>
|
||||
</size>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="rbFox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>World-Wide Digi-mode contest</p><p><br/></p></body></html></string>
|
||||
<string><html><head/><body><p>FT8 DXpedition mode: Fox (DXpedition) operator.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>WW Digital Contest</string>
|
||||
<string>Fox</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>WW Digi Contest</string>
|
||||
<string>Fox</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_27" stretch="0,1">
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="rbEU_VHF_Contest">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>European VHF+ contests requiring a signal report, serial number, and 6-character locator.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>EU VHF Contest</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>EU VHF Contest</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_24">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rbHound">
|
||||
<widget class="QCheckBox" name="cbContestName">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>FT8 DXpedition mode: Hound operator calling the DX.</p></body></html></string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string>Hound</string>
|
||||
<string><html><head/><body><p>Call CQ with an individual contest name instead of TEST, RU, or WW. </p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hound</string>
|
||||
<string>CQ with individual contest name</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">special_op_activity_button_group</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_15">
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@ -3323,110 +3220,38 @@ Right click for insert and delete options.</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="OTP_Layout" stretch="0,0,0,1,0,0,0,1">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbOTP">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Click to enable OTP method of Fox verification. Requires internet.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>OTP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>7</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblOTPSeed">
|
||||
<property name="text">
|
||||
<string>Key:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="OTPSeed">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Fox's key to generate OTP Codes.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>M2ZUU5CW6EVOY2HU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_14">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblOTPEvery">
|
||||
<property name="text">
|
||||
<string>Interval</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sbOTPinterval">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Interval at which the OTP messages are sent. Select 1 to sign every message.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_15">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_25">
|
||||
<item>
|
||||
<widget class="QLabel" name="labCN">
|
||||
<property name="text">
|
||||
<string>Contest name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="Contest_Name">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="cursorPosition">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@ -3595,8 +3420,13 @@ Right click for insert and delete options.</string>
|
||||
<tabstop>rbLowSidelobes</tabstop>
|
||||
<tabstop>rbMaxSensitivity</tabstop>
|
||||
<tabstop>gbSpecialOpActivity</tabstop>
|
||||
<tabstop>rbFox</tabstop>
|
||||
<tabstop>rbHound</tabstop>
|
||||
<tabstop>rbNA_VHF_Contest</tabstop>
|
||||
<tabstop>rbField_Day</tabstop>
|
||||
<tabstop>rbEU_VHF_Contest</tabstop>
|
||||
<tabstop>rbRTTY_Roundup</tabstop>
|
||||
<tabstop>rbWW_DIGI</tabstop>
|
||||
<tabstop>Field_Day_Exchange</tabstop>
|
||||
<tabstop>RTTY_Exchange</tabstop>
|
||||
</tabstops>
|
||||
@ -3669,12 +3499,12 @@ Right click for insert and delete options.</string>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="special_op_activity_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
<buttongroup name="TX_mode_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="CAT_data_bits_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"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
@ -1,132 +1,122 @@
|
||||
Notes on WSJT-X Installation for Mac OS X
|
||||
-----------------------------------------
|
||||
|
||||
If you have already downloaded a previous version of WSJT-X then I suggest
|
||||
you change the name in the Applications folder from WSJT-X to WSJT-X_previous
|
||||
before proceeding.
|
||||
|
||||
I recommend that you follow the installation instructions especially if you
|
||||
are moving from v2.5 to v2.6 or later, of WSJT-X or you have upgraded macOS.
|
||||
|
||||
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from the main web-site.
|
||||
Make sure that you leave this window open for the remaining installation steps.
|
||||
|
||||
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
|
||||
|
||||
Along with this ReadMe file there is a file: com.wsjtx.sysctl.plist which must be copied to a
|
||||
system area by typing these lines in the Terminal window and then pressing the Return key after
|
||||
each line.
|
||||
|
||||
sudo cp /Volumes/WSJT-X/com.wsjtx.sysctl.plist /Library/LaunchDaemons
|
||||
sudo chown root:wheel /Library/LaunchDaemons/com.wsjtx.sysctl.plist
|
||||
|
||||
you will be asked for your normal password because authorisation is needed to copy this file.
|
||||
(Your password will not be echoed but press the Return key when completed.)
|
||||
|
||||
If your Mac is using Sonoma 14.6 or later then in addition to these two commands you must visit:
|
||||
|
||||
System Settings > General > Login Items > sysctl and select ON for sysctl.
|
||||
|
||||
IMPORTANT: Now re-boot your Mac otherwise these changes will not take effect.
|
||||
|
||||
After the reboot you should re-open the Terminal window as before and you can check
|
||||
that the change has been made by typing:
|
||||
|
||||
sysctl -a | grep sysv.shm
|
||||
|
||||
If shmmax is not shown as 52428800 then contact me since WSJT-X will fail to load with
|
||||
an error message: "Unable to create shared memory segment". If the value of shmmax
|
||||
is shown as 20971520 then it is probable that you have download JTDX. WSJT-X and JTDX
|
||||
cannot both control the shmmax parameter. Contact me for advice.
|
||||
|
||||
You can now close the Terminal window. It will not be necessary to repeat this procedure
|
||||
again, even when you download an updated version of WSJT-X. It might be necessary if you
|
||||
upgrade macOS.
|
||||
|
||||
Drag the WSJT-X app to your preferred location, such as Applications, and close the window.
|
||||
|
||||
You need to configure your sound card. Visit Applications > Utilities > Audio MIDI
|
||||
Setup and select your sound card and then set Format to be "48000Hz 2ch-16bit" for
|
||||
input and output. On rare occasions problems with audio output to your rig can be
|
||||
corrected if you select 44100Hz for output format.
|
||||
|
||||
Now double-click on the WSJT-X app and two windows will appear. Select Preferences
|
||||
under the WSJT-X Menu and fill in various station details on the General panel.
|
||||
I recommend checking the 4 boxes under the Display heading and the first 4 boxes under
|
||||
the Behaviour heading.
|
||||
|
||||
Depending on your macOS you might see a pop-up window suggesting that wsjtx wants to use the
|
||||
microphone. What this means is that audio input must be allowed. Agree.
|
||||
|
||||
Next visit the Audio panel and select the Audio Codec you use to communicate between
|
||||
WSJT-X and your rig. There are so many audio interfaces available that it is not
|
||||
possible to give detailed advice on selection. If you have difficulties contact me.
|
||||
Note the location of the Save Directory. Decoded wave forms are located here.
|
||||
|
||||
Look at the Reporting panel. If you check the "Prompt me" box, a logging panel will appear
|
||||
at the end of the QSO. Visit Section 11 of the User Guide for information about log files
|
||||
and how to access them.
|
||||
|
||||
Finally, visit the Radio panel. WSJT-X is most effective when operated with CAT
|
||||
control. You will need to install the relevant Mac device driver for your rig,
|
||||
and then re-launch WSJT-X. Return to the Radio panel in Preferences and in
|
||||
the "Serial port" panel select your driver from the list that is presented.
|
||||
|
||||
You may need a device driver for your Mac. The USB/UART Bridge chip inside the Icom,
|
||||
Yaesu and Kenwood radios is a Silicon Labs USB to UART Bridge Controller and the Mac
|
||||
drivers are available here:
|
||||
|
||||
https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
|
||||
|
||||
Visit the SiLabs site and download v6 for a Mac. Then in WSJT-X if you use the drop-down menu
|
||||
for Serial Port you should see something like /dev/tty.SLAB_USBtoUART if the driver has been
|
||||
installed correctly. Make sure you read the release notes that come with the driver.
|
||||
|
||||
WSJT-X needs the Mac clock to be accurate. Visit System Preferences > Date & Time
|
||||
and make sure that Date and Time are set automatically. The drop-down menu will
|
||||
normally offer you several time servers to choose from.
|
||||
|
||||
On the Help menu, have a look at the new Online User's Guide for operational hints
|
||||
and tips and possible solutions to any problem you might have.
|
||||
|
||||
Please email me if you have problems.
|
||||
|
||||
--- John G4KLA (g4kla@rmnjmn.co.uk)
|
||||
|
||||
Addendum: Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X.
|
||||
|
||||
WSJT-X makes use of a block of memory which is shared between different parts of
|
||||
the code. The normal allocation of shared memory on a Mac is insufficient and this
|
||||
has to be increased. The com.wsjtx.sysctl.plist file is used for this purpose. You can
|
||||
use a Mac editor to examine the file. (Do not use another editor - the file
|
||||
would probably be corrupted.)
|
||||
|
||||
It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2
|
||||
Frequently asked Questions" in the User Guide. If you wish to run more than two instances
|
||||
simultaneously, the shmall parameter in the com.wsjtx.sysctl.plist file needs to be modified as follows.
|
||||
|
||||
The shmall parameter determines the amount of shared memory which is allocated in 4096 byte pages
|
||||
with 50MB (52428800) required for each instance. The shmall parameter is calculated as:
|
||||
(n * 52428800)/4096 where 'n' is the number of instances required to run simultaneously.
|
||||
Replace your new version of this file in /Library/LaunchDaemons and remember to reboot your
|
||||
Mac afterwards.
|
||||
|
||||
Note that the shmmax parameter remains unchanged. This is the maximum amount of shared memory that
|
||||
any one instance is allowed to request from the total shared memory allocation and should not
|
||||
be changed.
|
||||
|
||||
If two instances of WSJT-X are running, it is likely that you might need additional
|
||||
audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device
|
||||
which will allow you to specify more than one interface. I recommend you consult Apple's guide
|
||||
on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000.
|
||||
|
||||
2. Preventing WSJT-X from being put into 'sleep' mode (App Nap).
|
||||
|
||||
In normal circumstances an application which has not been directly accessed for a while can be
|
||||
subject to App Nap which means it is suspended until such time as its windows are accessed. If
|
||||
you find that WSJT-X seems disabled check this by opening Applications > Utilities > Activity Monitor and
|
||||
then select Energy and look at the column marked App Nap. If you see wsjtx marked "Yes" then you need
|
||||
to disable App Nap by opening a Terminal window and typing:
|
||||
defaults write NSGlobalDomain NSAppSleepDisabled -bool YES
|
||||
This will disable App Nap for all applications. If you wish to reverse this type:
|
||||
defaults delete NSGlobalDomain NSAppSleepDisabled
|
||||
Notes on WSJT-X Installation for Mac OS X
|
||||
-----------------------------------------
|
||||
|
||||
If you have already downloaded a previous version of WSJT-X then I suggest
|
||||
you change the name in the Applications folder from WSJT-X to WSJT-X_previous
|
||||
before proceeding.
|
||||
|
||||
I recommend that you follow the installation instructions especially if you
|
||||
are moving from v2.5 to v2.6 or later, of WSJT-X or you have upgraded macOS.
|
||||
|
||||
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
|
||||
Make sure that you leave this window open for the remaining installation steps.
|
||||
|
||||
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
|
||||
|
||||
Along with this ReadMe file there is a file: com.wsjtx.sysctl.plist which must be copied to a
|
||||
system area by typing these lines in the Terminal window and then pressing the Return key after
|
||||
each line.
|
||||
|
||||
sudo cp /Volumes/WSJT-X/com.wsjtx.sysctl.plist /Library/LaunchDaemons
|
||||
sudo chown root:wheel /Library/LaunchDaemons/com.wsjtx.sysctl.plist
|
||||
|
||||
you will be asked for your normal password because authorisation is needed to copy this file.
|
||||
(Your password will not be echoed but press the Return key when completed.)
|
||||
|
||||
IMPORTANT: Now re-boot your Mac otherwise these changes will not take effect.
|
||||
|
||||
After the reboot you should re-open the Terminal window as before and you can check
|
||||
that the change has been made by typing:
|
||||
|
||||
sysctl -a | grep sysv.shm
|
||||
|
||||
If shmmax is not shown as 52428800 then contact me since WSJT-X will fail to load with
|
||||
an error message: "Unable to create shared memory segment". If the value of shmmax
|
||||
is shown as 20971520 then it is probable that you have download JTDX. WSJT-X and JTDX
|
||||
cannot both control the shmmax paramter. Contact me for advice.
|
||||
|
||||
You can now close the Terminal window. It will not be necessary to repeat this procedure
|
||||
again, even when you download an updated version of WSJT-X. It might be necessary if you
|
||||
upgrade macOS.
|
||||
|
||||
Drag the WSJT-X app to your preferred location, such as Applications.
|
||||
|
||||
You need to configure your sound card. Visit Applications > Utilities > Audio MIDI
|
||||
Setup and select your sound card and then set Format to be "48000Hz 2ch-16bit" for
|
||||
input and output.
|
||||
|
||||
Now double-click on the WSJT-X app and two windows will appear. Select Preferences
|
||||
under the WSJT-X Menu and fill in various station details on the General panel.
|
||||
I recommend checking the 4 boxes under the Display heading and the first 4 boxes under
|
||||
the Behaviour heading.
|
||||
|
||||
Depending on your macOS you might see a pop-up window suggesting that wsjtx wants to use the
|
||||
microphone. What this means is that audio input must be allowed. Agree.
|
||||
|
||||
Next visit the Audio panel and select the Audio Codec you use to communicate between
|
||||
WSJT-X and your rig. There are so many audio interfaces available that it is not
|
||||
possible to give detailed advice on selection. If you have difficulties contact me.
|
||||
Note the location of the Save Directory. Decoded wave forms are located here.
|
||||
|
||||
Look at the Reporting panel. If you check the "Prompt me" box, a logging panel will appear
|
||||
at the end of the QSO. Visit Section 11 of the User Guide for information about log files
|
||||
and how to access them.
|
||||
|
||||
Finally, visit the Radio panel. WSJT-X is most effective when operated with CAT
|
||||
control. You will need to install the relevant Mac device driver for your rig,
|
||||
and then re-launch WSJT-X. Return to the Radio panel in Preferences and in
|
||||
the "Serial port" panel select your driver from the list that is presented.
|
||||
|
||||
You may need a device driver for your Mac. The USB/UART Bridge chip inside the Icom,
|
||||
Yaesu and Kenwood radios is a Silicon Labs USB to UART Bridge Controller and the Mac
|
||||
drivers are available here:
|
||||
|
||||
https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
|
||||
|
||||
Visit the SiLabs site and download v6 for a Mac. Then in WSJT-X if you use the drop-down menu
|
||||
for Serial Port you should see something like /dev/tty.SLAB_USBtoUART if the driver has been
|
||||
installed correctly. Make sure you read the release notes that come with the driver.
|
||||
|
||||
WSJT-X needs the Mac clock to be accurate. Visit System Preferences > Date & Time
|
||||
and make sure that Date and Time are set automatically. The drop-down menu will
|
||||
normally offer you several time servers to choose from.
|
||||
|
||||
On the Help menu, have a look at the new Online User's Guide for operational hints
|
||||
and tips and possible solutions to any problem you might have.
|
||||
|
||||
Please email me if you have problems.
|
||||
|
||||
--- John G4KLA (g4kla@rmnjmn.co.uk)
|
||||
|
||||
Addendum: Information about com.wsjtx.sysctl.plist and multiple instances of WSJT-X.
|
||||
|
||||
WSJT-X makes use of a block of memory which is shared between different parts of
|
||||
the code. The normal allocation of shared memory on a Mac is insufficient and this
|
||||
has to be increased. The com.wsjtx.sysctl.plist file is used for this purpose. You can
|
||||
use a Mac editor to examine the file. (Do not use another editor - the file
|
||||
would probably be corrupted.)
|
||||
|
||||
It is possible to run two instances of WSJT-X simultaneously. See "Section 16.2
|
||||
Frequently asked Questions" in the User Guide. If you wish to run more than two instances
|
||||
simultaneously, the shmall parameter in the com.wsjtx.sysctl.plist file needs to be modified as follows.
|
||||
|
||||
The shmall parameter determines the amount of shared memory which is allocated in 4096 byte pages
|
||||
with 50MB (52428800) required for each instance. The shmall parameter is calculated as:
|
||||
(n * 52428800)/4096 where 'n' is the number of instances required to run simultaneously.
|
||||
Replace your new version of this file in /Library/LaunchDaemons and remember to reboot your
|
||||
Mac afterwards.
|
||||
|
||||
Note that the shmmax parameter remains unchanged. This is the maximum amount of shared memory that
|
||||
any one instance is allowed to request from the total shared memory allocation and should not
|
||||
be changed.
|
||||
|
||||
If two instances of WSJT-X are running, it is likely that you might need additional
|
||||
audio devices, from two rigs for example. Visit Audio MIDI Setup and create an Aggregate Device
|
||||
which will allow you to specify more than one interface. I recommend you consult Apple's guide
|
||||
on combining multiple audio interfaces which is at https://support.apple.com/en-us/HT202000.
|
||||
|
||||
2. Preventing WSJT-X from being put into 'sleep' mode (App Nap).
|
||||
|
||||
In normal circumstances an application which has not been directly accessed for a while can be
|
||||
subject to App Nap which means it is suspended until such time as its windows are accessed. If
|
||||
|
||||
|
@ -70,10 +70,9 @@ void Modulator::start (QString mode, unsigned symbolsLength, double framesPerSym
|
||||
m_bFastMode=fastMode;
|
||||
m_TRperiod=TRperiod;
|
||||
unsigned delay_ms=1000;
|
||||
if((mode=="FT8" and m_nsps==1920) or (mode=="FST4" and m_nsps==720)) delay_ms=500; //FT8, FST4-15
|
||||
if((mode=="FT8" and m_nsps==1024)) delay_ms=400; //SuperFox Qary Polar Code transmission
|
||||
if(mode=="Q65" and m_nsps<=3600) delay_ms=500; //Q65-15 and Q65-30
|
||||
if(mode=="FT4") delay_ms=300; //FT4
|
||||
if(mode=="FT8" or (mode=="FST4" and m_nsps==720)) delay_ms=500; //FT8, FST4-15
|
||||
if(mode=="Q65" and m_nsps<=3600) delay_ms=500; //Q65-15 and Q65-30
|
||||
if(mode=="FT4") delay_ms=300; //FT4
|
||||
|
||||
// noise generator parameters
|
||||
if (m_addNoise) {
|
||||
|
202
NEWS
202
NEWS
@ -11,206 +11,6 @@
|
||||
|
||||
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc7
|
||||
September 30, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 7 brings significant improvements for
|
||||
the new SuperFox mode. It introduces a new verification system which
|
||||
replaces the previous one, and works for both the SuperFox mode and
|
||||
for old-style Fox and Hound operation. All code for SuperFox
|
||||
operation is now open source.
|
||||
|
||||
IMPORTANT: OpenSSL v1.1.1 or higher is required for the real-time
|
||||
verification of Fox and SuperFox messages.
|
||||
|
||||
Enhancements to the SuperFox decoder:
|
||||
|
||||
- Performance of the SuperFox decoder has been further improved.
|
||||
|
||||
- You can now set individual FTol values and tune the decoder to
|
||||
the exact sync frequency of the SuperFox signal if it is not exactly
|
||||
750 Hz. Both result in a better decodability in certain situations.
|
||||
|
||||
- Important: The Rx frequency must be set close to the sync frequency
|
||||
+/- FTol, for example 750 +/- 50 Hz.
|
||||
|
||||
Introduction of a new Fox verification system:
|
||||
|
||||
- The new Fox verification system uses one time passwords (OTPs), and
|
||||
works for the SuperFox mode as well as for old-style Fox and Hound
|
||||
operation. It can be enabled by the new OTP checkbox on the Advanced
|
||||
tab of the Settings dialog.
|
||||
|
||||
- Fox or SuperFox stations send individual OTPs via radio. Hounds
|
||||
automatically check the validity of the received OTPs in real time
|
||||
from a server when there is an internet connection. Otherwise, the
|
||||
validity can also be queried manually later. OTP verifications can
|
||||
only be retrieved once the transmission has already taken place.
|
||||
|
||||
- You may optionally display the received OTP values by checking
|
||||
the box "Show OTP messages".
|
||||
|
||||
- If the Fox or SuperFox callsign is verified by receipt of the
|
||||
correct OTP, the background color of the Hound or Super Hound label
|
||||
switches to green.
|
||||
|
||||
- Theoretically, DXpeditions can set up their own OTP server, however,
|
||||
we recommend using the server at https://www.9dx.cc.
|
||||
|
||||
- Use of the new Fox verification system requires an OTP key. The
|
||||
system uses open source code and standard encryption
|
||||
technology. For testing purposes, non-verified SuperFox
|
||||
transmissions are now possible without a key.
|
||||
|
||||
Improvements to SuperFox/Hound operation:
|
||||
|
||||
- SuperHounds must now first decode the SuperFox before they can
|
||||
call, and a QSO must be started by double-clicking on a SuperFox
|
||||
decode. (Note that calling the Fox blindly not only leads to
|
||||
unnecessary band utilization, but can also significantly reduce the
|
||||
QSO rate due to unanswered (Super)Fox replies.)
|
||||
|
||||
- Switching to SuperHound mode automatically sets the Rx frequency to
|
||||
750 Hz. The previously selected frequency is saved and restored
|
||||
afterwards.
|
||||
|
||||
- Right-clicking on the H button now activates/deactivates SuperFox mode.
|
||||
|
||||
- A flaw resulting in sub-optimal SuperFox QSO rates has been
|
||||
corrected.
|
||||
|
||||
- SuperFox decoder now does a more thorough job of rejecting QRM from
|
||||
non-SuperFox signals.
|
||||
|
||||
- Fields in the SuperFox payload not otherwise used in a particular
|
||||
transmission are now set to known nonzero values. Do NOT use RC6 or
|
||||
earlier versions to decode SuperFox transmissions from RC7 or
|
||||
later.
|
||||
|
||||
- Old-style Fox stations can now transmit free text messages (up to
|
||||
13 characters) by using an available stream.
|
||||
|
||||
- Some enhancements useful for Fox operators: Active Station Window now
|
||||
shows band activity. Hound callsigns can be highlighted via UDP API, and
|
||||
assigned a score for sorting via UDP API. Fox Tx frequency is preserved
|
||||
when switching in/out of Fox mode.
|
||||
|
||||
- UDP Status Update messages now include information on how many callsigns
|
||||
have highlighting applied, and how many callsigns have a score assigned.
|
||||
|
||||
Other enhancements and fixes:
|
||||
|
||||
- In FT8 mode, the Settings dialog no longer resets the VFO frequency
|
||||
to band/mode default unless really needed.
|
||||
|
||||
- Several code improvements specifically for macOS.
|
||||
|
||||
- Updated CTY.DAT and Hamlib.
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc6
|
||||
July 19, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 6 is a bug-fix release primarily
|
||||
affecting the new SuperFox mode. The following bugs have been fixed:
|
||||
|
||||
- Strong signals from Superfox too frequently failed to decode.
|
||||
|
||||
- SuperFox sometimes sent incorrect signal reports and an invalid
|
||||
digital signature.
|
||||
|
||||
- A Fortran bounds error could sometimes occur in the SuperFox
|
||||
decoder.
|
||||
|
||||
- For SuperFox operator, the "age" displayed for Hound callers
|
||||
became garbled after the 0000 UTC date change.
|
||||
|
||||
- Decodes of SuperFox transmissions were not posted to PSK Reporter.
|
||||
|
||||
- Some SuperFox-related messages were posted incorrectly to ALL.TXT.
|
||||
|
||||
- Logic for turning the SuperHound label green was flawed in some
|
||||
circumstances.
|
||||
|
||||
Release Candidate 6 also includes updates to Hamlib and the Chinese
|
||||
user interface translation.
|
||||
|
||||
Release: WSJT-X 2.7.0-rc5
|
||||
July 1, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 5 introduces "SuperFox" mode, a
|
||||
powerful new tool designed to help DXpeditions make digital QSOs at
|
||||
very high rates. RC5 also brings several other improvements and bug
|
||||
fixes.
|
||||
|
||||
SuperFox mode:
|
||||
|
||||
- The SuperFox mode behaves operationally like the present Fox and
|
||||
Hounds mode but uses a constant envelope waveform for Fox's
|
||||
transmissions rather than sending concurrent streams of up to five
|
||||
normal FT8 signals. This approach means that up to 9 messages can
|
||||
be transmitted simultaneously with no signal-strength penalty,
|
||||
resulting in a system gain of about +10 dB compared to the
|
||||
conventional Fox/Hound operation with 5 slots.
|
||||
|
||||
- IMPORTANT: Older revisions of WSJT-X and derivative programs will
|
||||
not be able to decode SuperFox transmissions. Hounds must use
|
||||
WSJT-X 2.7.0-rc5 (or a later release, when available) to receive
|
||||
SuperFox messages.
|
||||
|
||||
- Hounds chasing the DX station will transmit normal FT8 signals, as
|
||||
in the old-style Fox and Hound mode. QSOs will be logged as FT8
|
||||
mode.
|
||||
|
||||
- When using SuperFox mode, Hound stations may call at any frequency
|
||||
in Fox's received passband, including the range 0 - 1000 Hz.
|
||||
Hounds do not QSY to a lower frequency for their final
|
||||
transmission.
|
||||
|
||||
- SuperFox Operation requires the Fox operator to use a valid digital
|
||||
key. Keys will be issued in advance to legitimate DXpeditions by
|
||||
the Northern California DX Foundation, and will be kept secret.
|
||||
|
||||
- Every SuperFox transmission includes a unique digital signature.
|
||||
Hounds receiving a SuperFox message will see a "<callsign> verified"
|
||||
flag if the transmitted signature is valid, and the on-screen
|
||||
"Super Hound" label will turn from red to green.
|
||||
|
||||
- Hound operation should begin by selecting "Special operating
|
||||
activity", "Hound", and "SuperFox mode" on the Settings -> Advanced
|
||||
tab. Alternatively, right-clicking on the FT8 button toggles
|
||||
SuperFox mode on/off for either Fox or Hound, allowing quick
|
||||
transitions between SuperFox and old-style Fox and Hound operation.
|
||||
|
||||
- SuperFox stations can send free text messages of up to 26 characters
|
||||
together with messages to as many as 4 Hounds.
|
||||
|
||||
Other enhancements:
|
||||
|
||||
- Corrected a flaw that caused "Log automatically" to not work for
|
||||
the ARRL Digi Contest.
|
||||
|
||||
- Control elements for special operating activities are now disabled
|
||||
(grayed out) if the respective function is not applicable.
|
||||
|
||||
- Corrected a longstanding flaw that caused "Start new period
|
||||
decodes at top" to stop working properly after some time.
|
||||
|
||||
- Right-click mouse press events are now less error-prone.
|
||||
|
||||
- Improved the readability of the first line when "Start new period
|
||||
decodes at top" is checked.
|
||||
|
||||
- 4-digit grids are now logged for certain contest modes to ensure that
|
||||
the log complies with contest rules.
|
||||
|
||||
- The Fox Tx frequency is now saved and restored separately.
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc4
|
||||
March 11, 2024
|
||||
-------------------------
|
||||
@ -253,8 +53,6 @@ WSJT-X:
|
||||
our recommendations) messages with short (10-bit) callsign hashes
|
||||
are used in standard FT4/FT8 sub-bands.
|
||||
|
||||
- Enhancements useful for Fox operators.
|
||||
|
||||
Release: WSJT-X 2.7.0-rc3
|
||||
January 1, 2024
|
||||
-------------------------
|
||||
|
@ -1,125 +0,0 @@
|
||||
#include "FoxVerifier.hpp"
|
||||
#include "Logger.hpp"
|
||||
|
||||
FoxVerifier::FoxVerifier(QString user_agent, QNetworkAccessManager *manager,QString base_url, QString callsign, QDateTime timestamp, QString code, unsigned int hz=750) : QObject(nullptr)
|
||||
{
|
||||
manager_ = manager;
|
||||
finished_ = false;
|
||||
errored_ = false;
|
||||
callsign_ = callsign;
|
||||
code_ = code;
|
||||
ts_ = timestamp;
|
||||
hz_ = hz;
|
||||
|
||||
// make sure we URLencode the callsign, for things like E51D/MM
|
||||
QString encodedCall = QString::fromUtf8(QUrl::toPercentEncoding(callsign));
|
||||
QString url = QString("%1/check/").arg(base_url) + encodedCall + QString("/%1/%2.text").arg(timestamp.toString(Qt::ISODate)).arg(code);
|
||||
LOG_INFO(QString("FoxVerifier: url %1").arg(url).toStdString());
|
||||
q_url_ = QUrl(url);
|
||||
if (manager_ == nullptr) {
|
||||
LOG_INFO("FoxVerifier: manager is null, creating new one");
|
||||
manager_ = new QNetworkAccessManager(this);
|
||||
manager_->deleteLater();
|
||||
}
|
||||
if (q_url_.isValid()) {
|
||||
request_ = QNetworkRequest(q_url_);
|
||||
request_.setRawHeader( "User-Agent" , user_agent.toUtf8());
|
||||
request_.setRawHeader( "Accept" , "*/*" );
|
||||
request_.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
request_.setTransferTimeout(FOXVERIFIER_DEFAULT_TIMEOUT_MSEC);
|
||||
#endif
|
||||
|
||||
reply_ = manager_->get(request_);
|
||||
connect(reply_, &QNetworkReply::finished, this, &FoxVerifier::httpFinished);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
connect(reply_, &QNetworkReply::errorOccurred, this, &FoxVerifier::errorOccurred);
|
||||
#endif
|
||||
connect(reply_, &QNetworkReply::redirected, this, &FoxVerifier::httpRedirected);
|
||||
connect(reply_, &QNetworkReply::encrypted, this, &FoxVerifier::httpEncrypted);
|
||||
#if QT_CONFIG(ssl)
|
||||
connect(reply_, &QNetworkReply::sslErrors, this, &FoxVerifier::sslErrors);
|
||||
#else
|
||||
LOG_INFO("FoxVerifier: ssl not supported");
|
||||
#endif
|
||||
|
||||
} else {
|
||||
LOG_INFO(QString("FoxVerifier: url invalid ! %1").arg(url).toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
FoxVerifier::~FoxVerifier() {
|
||||
}
|
||||
|
||||
bool FoxVerifier::finished() {
|
||||
return finished_;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
void FoxVerifier::errorOccurred(QNetworkReply::NetworkError code)
|
||||
{
|
||||
int status = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
QString reason = reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
errored_ = true;
|
||||
error_reason_ = reply_->errorString();
|
||||
if (reply_->error() != QNetworkReply::NoError) {
|
||||
|
||||
LOG_INFO(QString("FoxVerifier: errorOccurred status %1 error [%2][%3] isFinished %4 isrunning %5 code %6").arg(status).arg(
|
||||
reason).arg(error_reason_).arg(reply_->isFinished()).arg(reply_->isRunning()).arg(code).toStdString());
|
||||
return;
|
||||
}
|
||||
// TODO emit
|
||||
}
|
||||
#endif
|
||||
|
||||
void FoxVerifier::httpFinished()
|
||||
{
|
||||
int status = reply_->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
QString reason = reply_->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
if (reply_->error() != QNetworkReply::NoError) {
|
||||
LOG_INFO(QString("FoxVerifier: httpFinished error:[%1 - %2] msg:[%3]").arg(status).arg(reason).arg(reply_->errorString()).toStdString());
|
||||
reply_->abort();
|
||||
emit verifyError(status, ts_, callsign_, code_, hz_, reply_->errorString());
|
||||
}
|
||||
return_value = reply_->read(1024); // limit amount we get
|
||||
LOG_INFO(QString("FoxVerifier: httpFinished status:[%1 - %2] body:[%3] ").arg(status).arg(reason).arg(return_value).toStdString());
|
||||
finished_ = true;
|
||||
reply_->deleteLater();
|
||||
if (status >= 200 && status <= 299) {
|
||||
emit verifyComplete(status, ts_, callsign_, code_, hz_, return_value);
|
||||
}
|
||||
}
|
||||
|
||||
void FoxVerifier::sslErrors(const QList<QSslError> &)
|
||||
{
|
||||
LOG_INFO(QString("FoxVerifier: sslErrors").toStdString());
|
||||
reply_->ignoreSslErrors();
|
||||
}
|
||||
|
||||
void FoxVerifier::httpRedirected(const QUrl &url) {
|
||||
LOG_INFO(QString("FoxVerifier: redirected to %1").arg(url.toString()).toStdString());
|
||||
}
|
||||
|
||||
void FoxVerifier::httpEncrypted() {
|
||||
LOG_INFO("FoxVerifier: httpEncrypted");
|
||||
}
|
||||
|
||||
QString FoxVerifier::formatDecodeMessage(QDateTime ts, QString callsign, unsigned int hz_, QString const& verify_message) {
|
||||
//"172100 -00 0.0 750 ~ K8R VERIFIED"
|
||||
QTime rx_time = ts.time();
|
||||
QString hz=QString("%1").arg(hz_, 4, 10 ); // insert Hz
|
||||
if (verify_message.endsWith(" VERIFIED")) {
|
||||
return QString("%1 0 0.0 %2 ~ %3 verified").arg(rx_time.toString("hhmmss")).arg(hz).arg(callsign);
|
||||
} else
|
||||
if (verify_message.endsWith(" INVALID"))
|
||||
{
|
||||
return QString("%1 0 0.0 %2 ~ %3 invalid").arg(rx_time.toString("hhmmss")).arg(hz).arg(callsign);
|
||||
}
|
||||
else
|
||||
return QString{};
|
||||
}
|
||||
|
||||
QString FoxVerifier::default_url() {
|
||||
return QString(FOXVERIFIER_DEFAULT_BASE_URL);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
|
||||
#ifndef WSJTX2_FOXVERIFIER_HPP
|
||||
#define WSJTX2_FOXVERIFIER_HPP
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QPointer>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QMutex>
|
||||
|
||||
#define FOXVERIFIER_DEFAULT_TIMEOUT_MSEC 5000
|
||||
#define FOXVERIFIER_DEFAULT_BASE_URL "https://www.9dx.cc"
|
||||
|
||||
class FoxVerifier : public QObject {
|
||||
Q_OBJECT
|
||||
QMutex mutex_;
|
||||
|
||||
public:
|
||||
explicit FoxVerifier(QString user_agent, QNetworkAccessManager *manager, QString base_url, QString callsign, QDateTime timestamp, QString code, unsigned int);
|
||||
~FoxVerifier();
|
||||
|
||||
QString return_value;
|
||||
bool finished();
|
||||
static QString formatDecodeMessage(QDateTime ts, QString callsign, unsigned int hz, QString const& verify_message);
|
||||
static QString default_url();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager* manager_;
|
||||
QNetworkReply* reply_;
|
||||
QNetworkRequest request_;
|
||||
QUrl q_url_;
|
||||
bool finished_;
|
||||
bool errored_;
|
||||
unsigned int hz_;
|
||||
QString error_reason_;
|
||||
QDateTime ts_;
|
||||
QString callsign_;
|
||||
QString code_;
|
||||
|
||||
private slots:
|
||||
void httpFinished();
|
||||
void httpRedirected(const QUrl &url);
|
||||
void httpEncrypted();
|
||||
#ifndef QT_NO_SSL
|
||||
void sslErrors(const QList<QSslError> &);
|
||||
#endif
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||
void errorOccurred(QNetworkReply::NetworkError code);
|
||||
#endif
|
||||
//signals:
|
||||
//void results(QString verify_response);
|
||||
//void error(QString const& reason) const;
|
||||
|
||||
public slots:
|
||||
signals:
|
||||
void verifyComplete(int status, QDateTime ts, QString callsign, QString code, unsigned int hz, QString const& response);
|
||||
void verifyError(int status, QDateTime ts, QString callsign, QString code, unsigned int hz, QString const& response);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //WSJTX2_FOXVERIFIER_HPP
|
@ -392,22 +392,7 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case NetworkMessage::AnnotationInfo: {
|
||||
QByteArray dx_call;
|
||||
bool sort_order_provided{false};
|
||||
quint32 sort_order{std::numeric_limits<quint32>::max()};
|
||||
in >> dx_call >> sort_order_provided >> sort_order;
|
||||
TRACE_UDP ("External Callsign Info:" << dx_call << "sort_order_provided:" << sort_order_provided
|
||||
<< "sort_order:" << sort_order);
|
||||
if (sort_order > 50000) sort_order = 50000;
|
||||
if (check_status(in) != Fail) {
|
||||
Q_EMIT
|
||||
self_->annotation_info(QString::fromUtf8(dx_call), sort_order_provided, sort_order);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
// Ignore
|
||||
//
|
||||
// Note that although server heartbeat messages are not
|
||||
|
@ -123,10 +123,7 @@ public:
|
||||
, bool fast_mode, quint32 tr_period, quint32 rx_df, QString const& dx_call
|
||||
, QString const& dx_grid, bool generate_messages);
|
||||
|
||||
// this signal is emitted if the server has sent information about a callsign
|
||||
Q_SIGNAL void annotation_info (QString const& dx_call, bool sort_order_provided, quint32 sort_order);
|
||||
|
||||
// this signal is emitted when network errors occur or if a host
|
||||
// this signal is emitted when network errors occur or if a host
|
||||
// lookup fails
|
||||
Q_SIGNAL void error (QString const&) const;
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
SOURCES += \
|
||||
Network/FileDownload.cpp \
|
||||
Network/FoxVerifier.cpp \
|
||||
Network/LotWUsers.cpp \
|
||||
Network/MessageClient.cpp \
|
||||
Network/NetworkAccessManager.cpp \
|
||||
Network/NetworkMessage.cpp \
|
||||
Network/NetworkServerLookup.cpp \
|
||||
Network/PSKReporter.cpp \
|
||||
Network/wsprnet.cpp
|
||||
|
||||
HEADERS += \
|
||||
Network/FileDownload.hpp \
|
||||
Network/FoxVerifier.hpp \
|
||||
Network/LotWUsers.hpp \
|
||||
Network/MessageClient.hpp \
|
||||
Network/NetworkAccessManager.hpp \
|
||||
Network/NetworkMessage.hpp \
|
||||
Network/NetworkServerLookup.hpp \
|
||||
Network/PSKReporter.hpp \
|
||||
Network/wsprnet.h
|
@ -462,14 +462,6 @@
|
||||
* decoding may be impacted. A rough rule of thumb might be too
|
||||
* limit the number of active highlighting requests to no more
|
||||
* than 100.
|
||||
*
|
||||
* Using a callsign of "CLEARALL!" and anything for the
|
||||
* color values will clear the internal highlighting data. It will
|
||||
* NOT remove the highlighting on the screen, however. The exclamation
|
||||
* symbol is used to avoid accidental clearing of all highlighting
|
||||
* data via a decoded callsign, since an exclamation symbol is not
|
||||
* a valid character in a callsign.
|
||||
|
||||
*
|
||||
* The "Highlight last" field allows the sender to request that
|
||||
* all instances of "Callsign" in the last period only, instead
|
||||
@ -502,33 +494,7 @@
|
||||
* fields an empty value implies no change, for the quint32 Rx DF
|
||||
* and Frequency Tolerance fields the maximum quint32 value
|
||||
* implies no change. Invalid or unrecognized values will be
|
||||
* silently ignored. NOTE that if a mode/submode change occurs and
|
||||
* the current frequency is NOT in the frequency table for that
|
||||
* mode, a frequency change (to the default frequency for that band
|
||||
* and mode) may occur.
|
||||
*
|
||||
* AnnotationInfo In 16 quint32
|
||||
* Id (unique key) utf8
|
||||
* DX Call utf8
|
||||
* Sort Order Provided bool
|
||||
* Sort Order quint32
|
||||
*
|
||||
* The server may send this message at any time. Sort orders can be used
|
||||
* for sorting hound callers when in Fox mode. A typical usage is to
|
||||
* "score" callsigns based on number of bands and/or modes worked using
|
||||
* an external logging program during a DXpedition, to be able to give
|
||||
* preference to calls that have not been worked before on any other
|
||||
* band or mode. An external program can watch decodes from wsjt-x,
|
||||
* then use this message to annotate the calls with a sort order. The
|
||||
* hound queue can be displayed by that sort order. *
|
||||
*
|
||||
* If 'sort order provided' is true, the message also specifies a numeric
|
||||
* sort order for the DX call.
|
||||
*
|
||||
* Invalid or unrecognized values will be silently ignored. A sort-order of
|
||||
* ffffffff will remove the sort-order value from the internal table.
|
||||
* Callsigns without a sort order will be valued at zero for sorting purposes
|
||||
* in the hound display.
|
||||
* silently ignored.
|
||||
*/
|
||||
|
||||
#include <QDataStream>
|
||||
@ -560,7 +526,6 @@ namespace NetworkMessage
|
||||
HighlightCallsign,
|
||||
SwitchConfiguration,
|
||||
Configure,
|
||||
AnnotationInfo,
|
||||
maximum_message_type_ // ONLY add new message types
|
||||
// immediately before here
|
||||
};
|
||||
|
@ -11,206 +11,6 @@
|
||||
|
||||
Copyright 2001 - 2024 by Joe Taylor, K1JT, and the WSJT Development Team
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc7
|
||||
September 30, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 7 brings significant improvements for
|
||||
the new SuperFox mode. It introduces a new verification system which
|
||||
replaces the previous one, and works for both the SuperFox mode and
|
||||
for old-style Fox and Hound operation. All code for SuperFox
|
||||
operation is now open source.
|
||||
|
||||
IMPORTANT: OpenSSL v1.1.1 or higher is required for the real-time
|
||||
verification of Fox and SuperFox messages.
|
||||
|
||||
Enhancements to the SuperFox decoder:
|
||||
|
||||
- Performance of the SuperFox decoder has been further improved.
|
||||
|
||||
- You can now set individual FTol values and tune the decoder to
|
||||
the exact sync frequency of the SuperFox signal if it is not exactly
|
||||
750 Hz. Both result in a better decodability in certain situations.
|
||||
|
||||
- Important: The Rx frequency must be set close to the sync frequency
|
||||
+/- FTol, for example 750 +/- 50 Hz.
|
||||
|
||||
Introduction of a new Fox verification system:
|
||||
|
||||
- The new Fox verification system uses one time passwords (OTPs), and
|
||||
works for the SuperFox mode as well as for old-style Fox and Hound
|
||||
operation. It can be enabled by the new OTP checkbox on the Advanced
|
||||
tab of the Settings dialog.
|
||||
|
||||
- Fox or SuperFox stations send individual OTPs via radio. Hounds
|
||||
automatically check the validity of the received OTPs in real time
|
||||
from a server when there is an internet connection. Otherwise, the
|
||||
validity can also be queried manually later. OTP verifications can
|
||||
only be retrieved once the transmission has already taken place.
|
||||
|
||||
- You may optionally display the received OTP values by checking
|
||||
the box "Show OTP messages".
|
||||
|
||||
- If the Fox or SuperFox callsign is verified by receipt of the
|
||||
correct OTP, the background color of the Hound or Super Hound label
|
||||
switches to green.
|
||||
|
||||
- Theoretically, DXpeditions can set up their own OTP server, however,
|
||||
we recommend using the server at https://www.9dx.cc.
|
||||
|
||||
- Use of the new Fox verification system requires an OTP key. The
|
||||
system uses open source code and standard encryption
|
||||
technology. For testing purposes, non-verified SuperFox
|
||||
transmissions are now possible without a key.
|
||||
|
||||
Improvements to SuperFox/Hound operation:
|
||||
|
||||
- SuperHounds must now first decode the SuperFox before they can
|
||||
call, and a QSO must be started by double-clicking on a SuperFox
|
||||
decode. (Note that calling the Fox blindly not only leads to
|
||||
unnecessary band utilization, but can also significantly reduce the
|
||||
QSO rate due to unanswered (Super)Fox replies.)
|
||||
|
||||
- Switching to SuperHound mode automatically sets the Rx frequency to
|
||||
750 Hz. The previously selected frequency is saved and restored
|
||||
afterwards.
|
||||
|
||||
- Right-clicking on the H button now activates/deactivates SuperFox mode.
|
||||
|
||||
- A flaw resulting in sub-optimal SuperFox QSO rates has been
|
||||
corrected.
|
||||
|
||||
- SuperFox decoder now does a more thorough job of rejecting QRM from
|
||||
non-SuperFox signals.
|
||||
|
||||
- Fields in the SuperFox payload not otherwise used in a particular
|
||||
transmission are now set to known nonzero values. Do NOT use RC6 or
|
||||
earlier versions to decode SuperFox transmissions from RC7 or
|
||||
later.
|
||||
|
||||
- Old-style Fox stations can now transmit free text messages (up to
|
||||
13 characters) by using an available stream.
|
||||
|
||||
- Some enhancements useful for Fox operators: Active Station Window now
|
||||
shows band activity. Hound callsigns can be highlighted via UDP API, and
|
||||
assigned a score for sorting via UDP API. Fox Tx frequency is preserved
|
||||
when switching in/out of Fox mode.
|
||||
|
||||
- UDP Status Update messages now include information on how many callsigns
|
||||
have highlighting applied, and how many callsigns have a score assigned.
|
||||
|
||||
Other enhancements and fixes:
|
||||
|
||||
- In FT8 mode, the Settings dialog no longer resets the VFO frequency
|
||||
to band/mode default unless really needed.
|
||||
|
||||
- Several code improvements specifically for macOS.
|
||||
|
||||
- Updated CTY.DAT and Hamlib.
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc6
|
||||
July 19, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 6 is a bug-fix release primarily
|
||||
affecting the new SuperFox mode. The following bugs have been fixed:
|
||||
|
||||
- Strong signals from Superfox too frequently failed to decode.
|
||||
|
||||
- SuperFox sometimes sent incorrect signal reports and an invalid
|
||||
digital signature.
|
||||
|
||||
- A Fortran bounds error could sometimes occur in the SuperFox
|
||||
decoder.
|
||||
|
||||
- For SuperFox operator, the "age" displayed for Hound callers
|
||||
became garbled after the 0000 UTC date change.
|
||||
|
||||
- Decodes of SuperFox transmissions were not posted to PSK Reporter.
|
||||
|
||||
- Some SuperFox-related messages were posted incorrectly to ALL.TXT.
|
||||
|
||||
- Logic for turning the SuperHound label green was flawed in some
|
||||
circumstances.
|
||||
|
||||
Release Candidate 6 also includes updates to Hamlib and the Chinese
|
||||
user interface translation.
|
||||
|
||||
Release: WSJT-X 2.7.0-rc5
|
||||
July 1, 2024
|
||||
-------------------------
|
||||
|
||||
WSJT-X 2.7.0 Release Candidate 5 introduces "SuperFox" mode, a
|
||||
powerful new tool designed to help DXpeditions make digital QSOs at
|
||||
very high rates. RC5 also brings several other improvements and bug
|
||||
fixes.
|
||||
|
||||
SuperFox mode:
|
||||
|
||||
- The SuperFox mode behaves operationally like the present Fox and
|
||||
Hounds mode but uses a constant envelope waveform for Fox's
|
||||
transmissions rather than sending concurrent streams of up to five
|
||||
normal FT8 signals. This approach means that up to 9 messages can
|
||||
be transmitted simultaneously with no signal-strength penalty,
|
||||
resulting in a system gain of about +10 dB compared to the
|
||||
conventional Fox/Hound operation with 5 slots.
|
||||
|
||||
- IMPORTANT: Older revisions of WSJT-X and derivative programs will
|
||||
not be able to decode SuperFox transmissions. Hounds must use
|
||||
WSJT-X 2.7.0-rc5 (or a later release, when available) to receive
|
||||
SuperFox messages.
|
||||
|
||||
- Hounds chasing the DX station will transmit normal FT8 signals, as
|
||||
in the old-style Fox and Hound mode. QSOs will be logged as FT8
|
||||
mode.
|
||||
|
||||
- When using SuperFox mode, Hound stations may call at any frequency
|
||||
in Fox's received passband, including the range 0 - 1000 Hz.
|
||||
Hounds do not QSY to a lower frequency for their final
|
||||
transmission.
|
||||
|
||||
- SuperFox Operation requires the Fox operator to use a valid digital
|
||||
key. Keys will be issued in advance to legitimate DXpeditions by
|
||||
the Northern California DX Foundation, and will be kept secret.
|
||||
|
||||
- Every SuperFox transmission includes a unique digital signature.
|
||||
Hounds receiving a SuperFox message will see a "<callsign> verified"
|
||||
flag if the transmitted signature is valid, and the on-screen
|
||||
"Super Hound" label will turn from red to green.
|
||||
|
||||
- Hound operation should begin by selecting "Special operating
|
||||
activity", "Hound", and "SuperFox mode" on the Settings -> Advanced
|
||||
tab. Alternatively, right-clicking on the FT8 button toggles
|
||||
SuperFox mode on/off for either Fox or Hound, allowing quick
|
||||
transitions between SuperFox and old-style Fox and Hound operation.
|
||||
|
||||
- SuperFox stations can send free text messages of up to 26 characters
|
||||
together with messages to as many as 4 Hounds.
|
||||
|
||||
Other enhancements:
|
||||
|
||||
- Corrected a flaw that caused "Log automatically" to not work for
|
||||
the ARRL Digi Contest.
|
||||
|
||||
- Control elements for special operating activities are now disabled
|
||||
(grayed out) if the respective function is not applicable.
|
||||
|
||||
- Corrected a longstanding flaw that caused "Start new period
|
||||
decodes at top" to stop working properly after some time.
|
||||
|
||||
- Right-click mouse press events are now less error-prone.
|
||||
|
||||
- Improved the readability of the first line when "Start new period
|
||||
decodes at top" is checked.
|
||||
|
||||
- 4-digit grids are now logged for certain contest modes to ensure that
|
||||
the log complies with contest rules.
|
||||
|
||||
- The Fox Tx frequency is now saved and restored separately.
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc4
|
||||
March 11, 2024
|
||||
-------------------------
|
||||
@ -253,9 +53,6 @@ WSJT-X:
|
||||
our recommendations) messages with short (10-bit) callsign hashes
|
||||
are used in standard FT4/FT8 sub-bands.
|
||||
|
||||
- Enhancements useful for Fox operators.
|
||||
|
||||
|
||||
Release: WSJT-X 2.7.0-rc3
|
||||
January 1, 2024
|
||||
-------------------------
|
||||
|
@ -619,12 +619,6 @@ int HamlibTransceiver::do_start ()
|
||||
CAT_TRACE ("starting: " << rig_get_caps_cptr (m_->model_, RIG_CAPS_MFG_NAME_CPTR)
|
||||
<< ": " << rig_get_caps_cptr (m_->model_, RIG_CAPS_MODEL_NAME_CPTR));
|
||||
|
||||
token_t token = rig_token_lookup (m_->rig_.data (), "client");
|
||||
if (RIG_CONF_END != token) // only set if valid for rig model
|
||||
{
|
||||
rig_set_conf (m_->rig_.data (), token, "WSJTX");
|
||||
}
|
||||
|
||||
m_->error_check (rig_open (m_->rig_.data ()), tr ("opening connection to rig"));
|
||||
|
||||
// reset dynamic state
|
||||
|
@ -64,9 +64,6 @@ typedef struct dec_data {
|
||||
char mygrid[6];
|
||||
char hiscall[12];
|
||||
char hisgrid[6];
|
||||
bool b_even_seq;
|
||||
bool b_superfox;
|
||||
int yymmdd;
|
||||
} params;
|
||||
} dec_data_t;
|
||||
|
||||
@ -94,9 +91,6 @@ extern struct {
|
||||
int i3bit[5];
|
||||
char cmsg[5][40];
|
||||
char mycall[12];
|
||||
char textMsg[26];
|
||||
bool bMoreCQs;
|
||||
bool bSendMsg;
|
||||
} foxcom_;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -21,7 +21,6 @@ FT8 11101000010011100001000010011000100000
|
||||
FT8/VHF 11101000010011100001000010011000100000
|
||||
FT8/Fox 11101000010011100001000000000010000000
|
||||
FT8/Hound 11101000010011100001000000000011000000
|
||||
FT8/SupHou 11111000010011100001000000000011000000
|
||||
-------------------------------------------------
|
||||
1 2 3
|
||||
01234567890123456789012345678901234567
|
||||
|
@ -29,8 +29,8 @@ the following copyright notice prominently:
|
||||
*The algorithms, source code, look-and-feel of _{prog}_ and related
|
||||
programs, and protocol specifications for the modes FSK441, FST4,
|
||||
FST4W, FT4, FT8, JT4, JT6M, JT9, JT44, JT65, JTMS, Q65, QRA64, ISCAT,
|
||||
and MSK144 are Copyright (C) 2001-2024 by one or more of the following
|
||||
and MSK144 are Copyright (C) 2001-2021 by one or more of the following
|
||||
authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke,
|
||||
K9AN; Nico Palermo, IV3NWV; Uwe Risse, DG2YCB; Brian Moran, N9ADG;
|
||||
Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip
|
||||
Karn, KA9Q; and other members of the WSJT Development Group.*
|
||||
K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB;
|
||||
Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the
|
||||
WSJT Development Group.*
|
||||
|
@ -94,8 +94,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
|
||||
:sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
|
||||
:ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice]
|
||||
:win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages]
|
||||
:win32_openssl: https://sourceforge.net/projects/wsjt-x-improved/files/Additional%20Files/OpenSSL/Win32OpenSSL_Light-1_1_1a.msi/download[Win32 OpenSSL Light Package]
|
||||
:win64_openssl: https://sourceforge.net/projects/wsjt-x-improved/files/Additional%20Files/OpenSSL/Win64OpenSSL_Light-1_1_1a.msi[Win64 OpenSSL Light Package]
|
||||
:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1s.msi[Win32 OpenSSL Light Package]
|
||||
:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1s.msi[Win64 OpenSSL Light Package]
|
||||
:writelog: https://writelog.com/[Writelog]
|
||||
:wsjtx_group: https://groups.io/g/wsjtgroup[WSJT GROUP User Forum]
|
||||
:wsjtx_group2: https://groups.io/g/wsjtgroup/join[join the group]
|
||||
|
@ -4,10 +4,8 @@ Download and execute the package file {win32} (Windows 7 or later,
|
||||
32-bit) or {win64} (Windows 7 or later, 64-bit) following these
|
||||
instructions:
|
||||
|
||||
* Install _WSJT-X_ into its own directory, for example
|
||||
`C:\WSJTX` or `C:\WSJT\WSJTX`, rather than the conventional location
|
||||
`C:\Program Files ...\WSJTX`. Do not use a directory path that
|
||||
includes an embedded blank.
|
||||
* Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
|
||||
Files ...\WSJTX`.
|
||||
|
||||
* All program files relating to _WSJT-X_ are stored in the chosen
|
||||
installation directory and its subdirectories.
|
||||
|
@ -1,12 +1,11 @@
|
||||
[[NEW_FEATURES]]
|
||||
=== New in Version {VERSION_MAJOR}.{VERSION_MINOR}
|
||||
|
||||
_WSJT-X 2.7_ introduces a new program called *QMAP*, new Special
|
||||
Operating Activities *Q65 Pileup* and *SuperFox mode*, an option to
|
||||
*Update Hamlib* at the click of a button, and a number of other
|
||||
enhancements and bug fixes.
|
||||
_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.
|
||||
|
||||
- *QMAP* and *Q65 Pileup* mode are of particular interest to those engaged
|
||||
- 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
|
||||
@ -20,15 +19,6 @@ enhancements and bug fixes.
|
||||
Quick-Start guide posted here:
|
||||
https://wsjt.sourceforge.io/Quick_Start_WSJT-X_2.7_QMAP.pdf
|
||||
|
||||
- *SuperFox mode* behaves operationally like the old-style Fox and
|
||||
Hounds mode but uses a new constant envelope waveform for Fox's
|
||||
transmissions. Messages can be transmitted simultaneously to as many
|
||||
as 9 Hounds with no signal-strength penalty, resulting in a system
|
||||
gain of about +10 dB compared to the older Fox-and-Hound operation
|
||||
with 5 slots. Further details on SuperFox mode can be found in the
|
||||
Quick-Start guide posted here:
|
||||
https://wsjt.sourceforge.io/SuperFox_User_Guide.pdf
|
||||
|
||||
- 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
|
||||
|
@ -330,7 +330,7 @@ comparable to tone spacing.
|
||||
[width="100%",cols="h,5*^",frame=topbot,options="header"]
|
||||
|===
|
||||
|T/R Period (s) |A Spacing Width (Hz)|B Spacing Width (Hz)|C Spacing Width (Hz)|D Spacing Width (Hz)|E Spacing Width (Hz)
|
||||
|15|6.67     433|13.33     867|26.67     1733|N/A|N/A
|
||||
|15|6.67     4.33|13.33     867|26.67     1733|N/A|N/A
|
||||
|30|3.33     217|6.67     433|13.33     867| 26.67     1733| N/A
|
||||
|60|1.67     108|3.33     217|6.67     433|13.33     867|26.67     1733
|
||||
|120|0.75     49|1.50     98|3.00     195|6.00     390| 12.00     780
|
||||
|
235
lib/cwsim.f90
235
lib/cwsim.f90
@ -1,235 +0,0 @@
|
||||
program cwsim
|
||||
|
||||
! Generate simulated audio for a CW message sent repeatedly for 60 seconds
|
||||
|
||||
use wavhdr
|
||||
parameter (NMAX=60*12000)
|
||||
type(hdr) h !Header for the .wav file
|
||||
integer*2 iwave(NMAX) !Generated waveform (no noise)
|
||||
integer icw(500) !Encoded CW message bits
|
||||
complex cspread(0:NMAX-1) !Complex amplitude for Rayleigh fading
|
||||
complex cdat(0:NMAX-1) !Complex waveform
|
||||
real dat(NMAX) !Audio waveform
|
||||
real*4 xnoise(NMAX) !Generated random noise
|
||||
character*60 message
|
||||
character*12 arg
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.6) then
|
||||
print*,'Usage: cwsim "message" freq bw wpm fspread snr'
|
||||
print*,'Example: cwsim "CQ CQ CQ DE K1JT K1JT K1JT" 700 100 20 100 -10'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
call getarg(1,message)
|
||||
call getarg(2,arg)
|
||||
read(arg,*) ifreq !Audio frequency (Hz)
|
||||
call getarg(3,arg)
|
||||
read(arg,*) bw !Bandwidth (Hz)
|
||||
call getarg(4,arg)
|
||||
read(arg,*) wpm !CW speed, words per minute
|
||||
call getarg(5,arg)
|
||||
read(arg,*) fspread !Doppler spread in Hz
|
||||
call getarg(6,arg)
|
||||
read(arg,*) snrdb !S/N in dB (2500 hz reference BW)
|
||||
|
||||
rms=500.0
|
||||
bandwidth_ratio=2500.0/6000.0
|
||||
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snrdb)
|
||||
twopi=8.0*atan(1.0)
|
||||
|
||||
h=default_header(12000,NMAX)
|
||||
open(10,file='000000_0000.wav',access='stream',status='unknown')
|
||||
do i=1,NMAX !Generate gaussian noise
|
||||
xnoise(i)=gran()
|
||||
enddo
|
||||
|
||||
itone=0
|
||||
call morse(message,icw,ncw)
|
||||
call cwsig(icw,ncw,ifreq,wpm,sig,cdat)
|
||||
nfft=NMAX
|
||||
|
||||
if(fspread.ne.0) then !Apply specified Doppler spread
|
||||
nh=nfft/2
|
||||
df=12000.0/nfft
|
||||
cspread(0)=1.0
|
||||
cspread(nh)=0.
|
||||
b=6.0 !Use truncated Lorenzian shape for fspread
|
||||
do i=1,nh
|
||||
f=i*df
|
||||
x=b*f/fspread
|
||||
z=0.
|
||||
a=0.
|
||||
if(x.lt.3.0) then !Cutoff beyond x=3
|
||||
a=sqrt(1.111/(1.0+x*x)-0.1) !Lorentzian amplitude
|
||||
phi1=twopi*rran() !Random phase
|
||||
z=a*cmplx(cos(phi1),sin(phi1))
|
||||
endif
|
||||
cspread(i)=z
|
||||
z=0.
|
||||
if(x.lt.3.0) then !Same thing for negative freqs
|
||||
phi2=twopi*rran()
|
||||
z=a*cmplx(cos(phi2),sin(phi2))
|
||||
endif
|
||||
cspread(nfft-i)=z
|
||||
enddo
|
||||
|
||||
call four2a(cspread,nfft,1,1,1) !Transform to time domain
|
||||
sum=0.
|
||||
do i=0,nfft-1
|
||||
p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||
sum=sum+p
|
||||
enddo
|
||||
avep=sum/nfft
|
||||
fac=sqrt(1.0/avep)
|
||||
cspread=fac*cspread !Normalize to constant avg power
|
||||
cdat=cspread*cdat !Apply Rayleigh fading
|
||||
endif
|
||||
|
||||
dat=aimag(cdat) + xnoise
|
||||
|
||||
cdat=dat
|
||||
call four2a(cdat,nfft,1,-1,1) !c2c to frequency domain
|
||||
ia=max(250/df,(ifreq-0.5*bw)/df)
|
||||
ib=ia+bw/df
|
||||
cdat(0:ia)=0.
|
||||
cdat(ib:)=0.
|
||||
call four2a(cdat,nfft,1,+1,1) !c2c to time domain
|
||||
fac=sqrt(5000/bw)/nfft
|
||||
dat=fac*real(cdat)
|
||||
|
||||
iwave=nint(rms*dat)
|
||||
write(10) h,iwave
|
||||
close(10)
|
||||
|
||||
999 end program cwsim
|
||||
|
||||
subroutine cwsig(icw,ncw,ifreq,wpm,sig,cdat)
|
||||
|
||||
parameter(NMAX=60*12000)
|
||||
integer icw(ncw)
|
||||
complex cdat(NMAX)
|
||||
complex z(NMAX)
|
||||
real x(NMAX)
|
||||
real y(NMAX)
|
||||
real*8 dt,twopi,phi,dphi,fsample,tdit,t
|
||||
|
||||
nspd=nint(1.2*12000.0/wpm)
|
||||
fsample=12000.d0 !Sample rate (Hz)
|
||||
dt=1.d0/fsample !Sample interval (s)
|
||||
tdit=nspd*dt
|
||||
twopi=8.d0*atan(1.d0)
|
||||
dphi=twopi*ifreq*dt
|
||||
phi=0.
|
||||
k=12000 !Start audio at t = 1.0 s
|
||||
t=0.
|
||||
npts=59*12000
|
||||
x=0.
|
||||
do i=1,npts
|
||||
t=t+dt
|
||||
j=nint(t/tdit) + 1
|
||||
j=mod(j-1,ncw) + 1
|
||||
phi=phi + dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
xphi=phi
|
||||
k=k+1
|
||||
x(k)=icw(j)
|
||||
z(k)=cmplx(cos(xphi),sin(xphi))
|
||||
if(t.ge.59.5) exit
|
||||
enddo
|
||||
|
||||
nadd=0.004/dt
|
||||
call smo(x,npts,y,nadd)
|
||||
y=y/nadd
|
||||
cdat=sig*y*z
|
||||
|
||||
return
|
||||
end subroutine cwsig
|
||||
|
||||
subroutine morse(msg,idat,n)
|
||||
|
||||
! Convert ascii message to a Morse code bit string.
|
||||
! Dash = 3 dots
|
||||
! Space between dots, dashes = 1 dot
|
||||
! Space between letters = 3 dots
|
||||
! Space between words = 7 dots
|
||||
|
||||
character*(*) msg
|
||||
integer idat(500)
|
||||
integer*1 ic(21,38)
|
||||
data ic/ &
|
||||
1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,20, &
|
||||
1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,18, &
|
||||
1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,16, &
|
||||
1,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
|
||||
1,0,1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,1,1,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,1,1,0,1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,14, &
|
||||
1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,0,0,0,16, &
|
||||
1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,18, &
|
||||
1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
|
||||
1,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
|
||||
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2, &
|
||||
1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
|
||||
1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4, &
|
||||
1,0,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
|
||||
1,1,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
|
||||
1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
|
||||
1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,1,1,0,1,1,1,0,1,0,1,1,1,0,0,0,0,0,0,0,14, &
|
||||
1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
|
||||
1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 6, &
|
||||
1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4, &
|
||||
1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 8, &
|
||||
1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,10, &
|
||||
1,1,1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,14, &
|
||||
1,1,1,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,12, &
|
||||
1,1,1,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,14, &
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2/ !Incremental word space
|
||||
save
|
||||
|
||||
msglen=len(trim(msg))
|
||||
idat=0
|
||||
n=6
|
||||
do k=1,msglen
|
||||
jj=ichar(msg(k:k))
|
||||
if(jj.ge.97 .and. jj.le.122) jj=jj-32 !Convert lower to upper case
|
||||
if(jj.ge.48 .and. jj.le.57) j=jj-48 !Numbers
|
||||
if(jj.ge.65 .and. jj.le.90) j=jj-55 !Letters
|
||||
if(jj.eq.47) j=36 !Slash (/)
|
||||
if(jj.eq.32) j=37 !Word space
|
||||
j=j+1
|
||||
|
||||
! Insert this character
|
||||
nmax=ic(21,j)
|
||||
if (n + nmax + 4 .gt. size (idat)) exit
|
||||
do i=1,nmax
|
||||
n=n+1
|
||||
idat(n)=ic(i,j)
|
||||
enddo
|
||||
|
||||
! Insert character space of 2 dit lengths:
|
||||
n=n+1
|
||||
idat(n)=0
|
||||
n=n+1
|
||||
idat(n)=0
|
||||
enddo
|
||||
|
||||
! Insert word space at end of message
|
||||
do j=1,4
|
||||
n=n+1
|
||||
idat(n)=0
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine morse
|
@ -67,7 +67,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
ntr0=params%ntr
|
||||
rms=sqrt(dot_product(float(id2(1:180000)), &
|
||||
float(id2(1:180000)))/180000.0)
|
||||
if(rms.lt.0.5) go to 800
|
||||
if(rms.lt.3.0) go to 800
|
||||
|
||||
!cast C character arrays to Fortran character strings
|
||||
datetime=transfer(params%datetime, datetime)
|
||||
@ -124,7 +124,8 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
|
||||
if(params%nmode.eq.8) then
|
||||
! We're in FT8 mode
|
||||
if(ncontest.eq.6) then !Fox=6, Hound=7
|
||||
|
||||
if(ncontest.eq.6) then
|
||||
! Fox mode: initialize and open houndcallers.txt
|
||||
inquire(file=trim(temp_dir)//'/houndcallers.txt',exist=ex)
|
||||
if(.not.ex) then
|
||||
@ -139,36 +140,27 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
open(19,file=trim(temp_dir)//'/houndcallers.txt',status='unknown')
|
||||
endif
|
||||
|
||||
if(ncontest.eq.7 .and. params%b_superfox .and. params%b_even_seq) then
|
||||
if(params%nzhsym.lt.50) go to 800
|
||||
! Call the superFox decoder
|
||||
call sfrx_sub(params%yymmdd,params%nutc,params%nfqso,params%ntol,id2)
|
||||
else
|
||||
call timer('decft8 ',0)
|
||||
newdat=params%newdat
|
||||
if(params%emedelay.ne.0.0) then
|
||||
id2(1:156000)=id2(24001:180000) ! Drop the first 2 seconds of data
|
||||
id2(156001:180000)=0
|
||||
endif
|
||||
call my_ft8%decode(ft8_decoded,id2,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nzhsym,params%ndepth,params%emedelay,ncontest, &
|
||||
logical(params%nagain),logical(params%lft8apon), &
|
||||
logical(params%lapcqonly),params%napwid,mycall,hiscall, &
|
||||
params%ndiskdat)
|
||||
call timer('decft8 ',1)
|
||||
call timer('decft8 ',0)
|
||||
newdat=params%newdat
|
||||
if(params%emedelay.ne.0.0) then
|
||||
id2(1:156000)=id2(24001:180000) ! Drop the first 2 seconds of data
|
||||
id2(156001:180000)=0
|
||||
endif
|
||||
call my_ft8%decode(ft8_decoded,id2,params%nQSOProgress,params%nfqso, &
|
||||
params%nftx,newdat,params%nutc,params%nfa,params%nfb, &
|
||||
params%nzhsym,params%ndepth,params%emedelay,ncontest, &
|
||||
logical(params%nagain),logical(params%lft8apon), &
|
||||
logical(params%lapcqonly),params%napwid,mycall,hiscall, &
|
||||
params%ndiskdat)
|
||||
call timer('decft8 ',1)
|
||||
if(nfox.gt.0) then
|
||||
n30min=minval(n30fox(1:nfox))
|
||||
n30max=maxval(n30fox(1:nfox))
|
||||
endif
|
||||
j=0
|
||||
|
||||
if(ncontest.eq.6) then
|
||||
! Fox mode: save decoded Hound calls for possible selection by FoxOp
|
||||
|
||||
n=params%nutc
|
||||
n30=(3600*(n/10000) + 60*mod((n/100),100) + mod(n,100))/30
|
||||
if(n30.lt.n30z) nwrap=nwrap+2880 !New UTC day, handle the wrap
|
||||
n30z=n30
|
||||
n30=n30+nwrap
|
||||
|
||||
rewind 19
|
||||
if(nfox.eq.0) then
|
||||
endfile 19
|
||||
@ -176,23 +168,21 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
else
|
||||
do i=1,nfox
|
||||
n=n30fox(i)
|
||||
nage=min(99,mod(n30-n+288000,2880))
|
||||
if(nage.le.4) then
|
||||
if(n30max-n30fox(i).le.4) then
|
||||
j=j+1
|
||||
c2fox(j)=c2fox(i)
|
||||
g2fox(j)=g2fox(i)
|
||||
nsnrfox(j)=nsnrfox(i)
|
||||
nfreqfox(j)=nfreqfox(i)
|
||||
n30fox(j)=n
|
||||
! nage=min(99,mod(n30-n+288000,2880))
|
||||
m=n30max-n
|
||||
if(len(trim(g2fox(j))).eq.4) then
|
||||
call azdist(mygrid,g2fox(j)//' ',0.d0,nAz,nEl,nDmiles, &
|
||||
nDkm,nHotAz,nHotABetter)
|
||||
else
|
||||
nDkm=9999
|
||||
endif
|
||||
write(19,1004) c2fox(j),g2fox(j),nsnrfox(j),nfreqfox(j), &
|
||||
nDkm,nage
|
||||
write(19,1004) c2fox(j),g2fox(j),nsnrfox(j),nfreqfox(j),nDkm,m
|
||||
1004 format(a12,1x,a4,i5,i6,i7,i3)
|
||||
endif
|
||||
enddo
|
||||
@ -671,10 +661,10 @@ contains
|
||||
endif
|
||||
b1=i3-i2.eq.5 .and. isgrid4(g2)
|
||||
b2=i3-i2.eq.1
|
||||
if(b0 .and. (b1.or.b2) .and. (nint(freq).ge.1000 .or. params%b_superfox)) then
|
||||
if(b0 .and. (b1.or.b2) .and. nint(freq).ge.1000) then
|
||||
n=params%nutc
|
||||
n30=(3600*(n/10000) + 60*mod((n/100),100) + mod(n,100))/30
|
||||
if(n30.lt.n30z) nwrap=nwrap+2880 !New UTC day, handle the wrap
|
||||
if(n30.lt.n30z) nwrap=nwrap+5760 !New UTC day, handle the wrap
|
||||
n30z=n30
|
||||
n30=n30+nwrap
|
||||
if(nfox.lt.MAXFOX) nfox=nfox+1
|
||||
|
@ -26,8 +26,8 @@ program ft4code
|
||||
'LDPC(174,91) encoding,'
|
||||
print*,'bit and symbol ordering, and other details of the FT4 protocol.'
|
||||
print*
|
||||
print*,'Usage: ft4code "message" # Results for specified message'
|
||||
print*,' ft4code -t # Examples of all message types'
|
||||
print*,'Usage: ft4code [-c grid] "message" # Results for specified message'
|
||||
print*,' ft4code -t # Examples of all message types'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
subroutine foxgen(bSuperFox,fname)
|
||||
subroutine foxgen()
|
||||
|
||||
! Called from MainWindow::foxTxSequencer() to generate the Tx waveform in
|
||||
! FT8 Fox mode. The Tx message can contain up to 5 "slots", each carrying
|
||||
@ -15,12 +15,9 @@ subroutine foxgen(bSuperFox,fname)
|
||||
! 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)
|
||||
logical*1 bSuperFox,bMoreCQs,bSendMsg
|
||||
character*(*) fname
|
||||
character*40 cmsg,cmsg2
|
||||
character*26 textMsg
|
||||
character*40 cmsg
|
||||
character*37 msg,msgsent
|
||||
integer itone(79)
|
||||
integer*1 msgbits(77),msgbits2
|
||||
@ -28,26 +25,10 @@ subroutine foxgen(bSuperFox,fname)
|
||||
real x(NFFT)
|
||||
real*8 dt,twopi,f0,fstep,dfreq,phi,dphi
|
||||
complex cx(0:NH)
|
||||
common/foxcom/wave(NWAVE),nslots,nfreq,i3bit(5),cmsg(5),mycall(12), &
|
||||
textMsg,bMoreCQs,bSendMsg
|
||||
common/foxcom/wave(NWAVE),nslots,nfreq,i3bit(5),cmsg(5),mycall(12)
|
||||
common/foxcom2/itone2(NN),msgbits2(77)
|
||||
common/foxcom3/nslots2,cmsg2(5),itone3(151)
|
||||
equivalence (x,cx),(y,cy)
|
||||
|
||||
if(bSuperFox) then
|
||||
n=nslots
|
||||
if(bMoreCQs) cmsg(1)(40:40)='1' !Set flag to include a CQ
|
||||
if(bSendMsg) then
|
||||
n=min(nslots+1,3)
|
||||
cmsg(n)=textMsg
|
||||
cmsg(n)(39:39)='1' !Set flag for text message
|
||||
nslots=n
|
||||
endif
|
||||
nslots2=nslots
|
||||
cmsg2=cmsg
|
||||
go to 999
|
||||
endif
|
||||
|
||||
fstep=60.d0
|
||||
dfreq=6.25d0
|
||||
dt=1.d0/48000.d0
|
||||
@ -85,7 +66,7 @@ subroutine foxgen(bSuperFox,fname)
|
||||
peak3=maxval(abs(wave))
|
||||
wave=wave/peak3
|
||||
|
||||
999 return
|
||||
return
|
||||
end subroutine foxgen
|
||||
|
||||
! include 'plotspec.f90'
|
||||
|
@ -2,12 +2,12 @@ subroutine foxgen_wrap(msg40,msgbits,itone)
|
||||
|
||||
parameter (NN=79,ND=58,KK=77,NSPS=4*1920)
|
||||
parameter (NWAVE=(160+2)*134400*4) !the biggest waveform we generate (FST4-1800)
|
||||
logical*1 bMoreCQs
|
||||
|
||||
character*40 msg40,cmsg
|
||||
character*12 mycall12
|
||||
integer*1 msgbits(KK),msgbits2
|
||||
integer itone(NN)
|
||||
common/foxcom/wave(NWAVE),nslots,nfreq,i3bit(5),cmsg(5),mycall12,bMoreCQs
|
||||
common/foxcom/wave(NWAVE),nslots,nfreq,i3bit(5),cmsg(5),mycall12
|
||||
common/foxcom2/itone2(NN),msgbits2(KK)
|
||||
|
||||
nslots=1
|
||||
|
@ -1,6 +1,6 @@
|
||||
module ft8_a7
|
||||
|
||||
parameter(MAXDEC=200)
|
||||
parameter(MAXDEC=100)
|
||||
|
||||
! For the following three arrays
|
||||
! First index i=decode number in this sequence
|
||||
@ -43,7 +43,7 @@ subroutine ft8_a7_save(nutc,dt,f,msg)
|
||||
! Add this decode to current table for this sequence
|
||||
ndec(j,1)=ndec(j,1)+1 !Number of decodes in this sequence
|
||||
i=ndec(j,1) !i is index of a new table entry
|
||||
if(i.gt.MAXDEC) return !Prevent table overflow (indexes start at 1)
|
||||
if(i.ge.MAXDEC-1) return !Prevent table overflow
|
||||
|
||||
dt0(i,j,1)=dt !Save dt in table
|
||||
f0(i,j,1)=f !Save f in table
|
||||
|
@ -8,10 +8,10 @@ subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
logical newdat,first
|
||||
complex c1(0:NFFT2-1)
|
||||
complex cx(0:NFFT1/2)
|
||||
real dd(NMAX),x(NFFT1+2),taper(0:100)
|
||||
data first/.true./
|
||||
save x,cx,first,taper
|
||||
real dd(NMAX),x(NFFT1),taper(0:100)
|
||||
equivalence (x,cx)
|
||||
data first/.true./
|
||||
save cx,first,taper
|
||||
|
||||
if(first) then
|
||||
pi=4.0*atan(1.0)
|
||||
@ -23,10 +23,11 @@ subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
if(newdat) then
|
||||
! Data in dd have changed, recompute the long FFT
|
||||
x(1:NMAX)=dd
|
||||
x(NMAX+1:NFFT1+2)=0. !Zero-pad the x array
|
||||
x(NMAX+1:NFFT1)=0. !Zero-pad the x array
|
||||
call four2a(cx,NFFT1,1,-1,0) !r2c FFT to freq domain
|
||||
newdat=.false.
|
||||
endif
|
||||
|
||||
df=12000.0/NFFT1
|
||||
baud=12000.0/NSPS
|
||||
i0=nint(f0/df)
|
||||
|
@ -23,9 +23,9 @@ program ft8code
|
||||
'LDPC(174,91) encoding,'
|
||||
print*,'bit and symbol ordering, and other details of the FT8 protocol.'
|
||||
print*
|
||||
print*,'Usage: ft8code "message" # Results for specified message'
|
||||
print*,' ft8code -T # Examples of all message types'
|
||||
print*,' ft8code -t # Short format examples'
|
||||
print*,'Usage: ft8code [-c grid] "message" # Results for specified message'
|
||||
print*,' ft8code -T # Examples of all message types'
|
||||
print*,' ft8code -t # Short format examples'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
|
@ -42,7 +42,7 @@ program ft8d
|
||||
j2=index(infile,'.wav')
|
||||
read(infile(j2-6:j2-1),*) nutc
|
||||
datetime=infile(j2-13:j2-1)
|
||||
call sync8(iwave,NMAX,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
call sync8(iwave,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
syncmin=2.0
|
||||
dd=iwave
|
||||
do icand=1,ncand
|
||||
|
@ -101,24 +101,14 @@ program ft8sim_gfsk
|
||||
wave=imag(c)
|
||||
peak=maxval(abs(wave))
|
||||
nslots=1
|
||||
|
||||
psig=0.
|
||||
pnoise=0.
|
||||
|
||||
if(snrdb.lt.90) then
|
||||
do i=1,NMAX !Add gaussian noise at specified SNR
|
||||
xnoise=gran()
|
||||
if(i.ge.6001 .and. i.le.157692) then
|
||||
psig=psig + wave(i)*wave(i) !Signal power
|
||||
pnoise=pnoise + xnoise*xnoise !Noise power in signal interval
|
||||
endif
|
||||
wave(i)=wave(i) + xnoise
|
||||
enddo
|
||||
endif
|
||||
|
||||
! Noise power in signal interval and 2500 Hz bandwidth:
|
||||
pnoise=bandwidth_ratio*pnoise
|
||||
snr_2500=db(psig/pnoise) !SNR in 2500 Hz bandwidth
|
||||
|
||||
gain=100.0
|
||||
if(snrdb.lt.90.0) then
|
||||
wave=gain*wave
|
||||
@ -135,7 +125,7 @@ program ft8sim_gfsk
|
||||
open(10,file=fname,status='unknown',access='stream')
|
||||
write(10) h,iwave !Save to *.wav file
|
||||
close(10)
|
||||
write(*,1110) ifile,xdt,f0,snrdb,fname,snr_2500
|
||||
1110 format(i4,f7.2,f8.2,f7.1,2x,a17,f8.2)
|
||||
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
|
||||
enddo
|
||||
999 end program ft8sim_gfsk
|
||||
|
@ -1,4 +1,4 @@
|
||||
subroutine sync8(dd,npts,nfa,nfb,syncmin,nfqso,maxcand,candidate,ncand,sbase)
|
||||
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,candidate,ncand,sbase)
|
||||
|
||||
include 'ft8_params.f90'
|
||||
parameter (MAXPRECAND=1000)
|
||||
@ -9,13 +9,13 @@ subroutine sync8(dd,npts,nfa,nfb,syncmin,nfqso,maxcand,candidate,ncand,sbase)
|
||||
real s(NH1,NHSYM)
|
||||
real savg(NH1)
|
||||
real sbase(NH1)
|
||||
real x(NFFT1+2)
|
||||
real x(NFFT1)
|
||||
real sync2d(NH1,-JZ:JZ)
|
||||
real red(NH1)
|
||||
real red2(NH1)
|
||||
real candidate0(3,MAXPRECAND)
|
||||
real candidate(3,maxcand)
|
||||
real dd(npts)
|
||||
real dd(NMAX)
|
||||
integer jpeak(NH1)
|
||||
integer jpeak2(NH1)
|
||||
integer indx(NH1)
|
||||
|
@ -24,7 +24,7 @@ subroutine watterson(c,npts,nsig,fs,delay,fspread)
|
||||
do i=0,npts-1
|
||||
f=i*df
|
||||
if(i.gt.npts/2) f=(i-npts)*df
|
||||
x=(f/fspread)**2
|
||||
x=(f/(0.5*fspread))**2
|
||||
a=0.
|
||||
if(x.le.50.0) then
|
||||
a=exp(-x)
|
||||
|
@ -44,23 +44,23 @@ contains
|
||||
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
procedure(ft8_decode_callback) :: callback
|
||||
parameter (MAXCAND=600,MAX_EARLY=200,NPTS=15*12000)
|
||||
parameter (MAXCAND=600,MAX_EARLY=100)
|
||||
real*8 tsec,tseq
|
||||
real sbase(NH1)
|
||||
real candidate(3,MAXCAND)
|
||||
real dd(NPTS),dd1(NPTS)
|
||||
real dd(15*12000),dd1(15*12000)
|
||||
logical, intent(in) :: lft8apon,lapcqonly,nagain
|
||||
logical newdat,lsubtract,ldupe,lrefinedt
|
||||
logical*1 ldiskdat
|
||||
logical lsubtracted(MAX_EARLY)
|
||||
character*12 mycall12,hiscall12,call_1,call_2
|
||||
character*4 grid4
|
||||
integer*2 iwave(NPTS)
|
||||
integer*2 iwave(15*12000)
|
||||
integer apsym2(58),aph10(10)
|
||||
character datetime*13,msg37*37
|
||||
character*37 allmessages(MAX_EARLY)
|
||||
character*37 allmessages(200)
|
||||
character*12 ctime
|
||||
integer allsnrs(MAX_EARLY)
|
||||
integer allsnrs(200)
|
||||
integer itone(NN)
|
||||
integer itone_save(NN,MAX_EARLY)
|
||||
real f1_save(MAX_EARLY)
|
||||
@ -192,7 +192,7 @@ contains
|
||||
endif
|
||||
call timer('sync8 ',0)
|
||||
maxc=MAXCAND
|
||||
call sync8(dd,NPTS,ifa,ifb,syncmin,nfqso,maxc,candidate,ncand,sbase)
|
||||
call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,candidate,ncand,sbase)
|
||||
call timer('sync8 ',1)
|
||||
do icand=1,ncand
|
||||
sync=candidate(3,icand)
|
||||
@ -215,9 +215,6 @@ contains
|
||||
if(msg37.eq.allmessages(id)) ldupe=.true.
|
||||
enddo
|
||||
if(.not.ldupe) then
|
||||
if(ndecodes.ge.MAX_EARLY) then
|
||||
cycle
|
||||
endif
|
||||
ndecodes=ndecodes+1
|
||||
allmessages(ndecodes)=msg37
|
||||
allsnrs(ndecodes)=nsnr
|
||||
|
@ -19,10 +19,9 @@ subroutine hspec(id2,k,nutc0,ntrpdepth,nrxfreq,ntol,bmsk144, &
|
||||
! jh index of most recent data in green(), s()
|
||||
|
||||
parameter (JZ=703)
|
||||
character*(*) line1
|
||||
character*80 line0
|
||||
character*80 line1
|
||||
character*(*) datadir
|
||||
character*(*) mycall,hiscall
|
||||
character*12 mycall,hiscall
|
||||
integer*2 id2(0:120*12000-1)
|
||||
logical*1 bmsk144,bshmsg,btrain,bswl
|
||||
real green(0:JZ-1)
|
||||
@ -97,12 +96,7 @@ subroutine hspec(id2,k,nutc0,ntrpdepth,nrxfreq,ntol,bmsk144, &
|
||||
tt2=sum(float(abs(id2(k0:k0+3583))))
|
||||
if(tt1.ne.0.0 .and. tt2.ne.0) then
|
||||
call mskrtd(id2(k-7168+1:k),nutc0,tsec,ntol,nrxfreq,ndepth, &
|
||||
mycall,hiscall,bshmsg,btrain,pcoeffs,bswl,datadir,line0)
|
||||
if(line0(1:1).eq.char(0)) then
|
||||
line1(1:1)=char(0)
|
||||
else
|
||||
line1(1:62)=line0(1:62)
|
||||
endif
|
||||
mycall,hiscall,bshmsg,btrain,pcoeffs,bswl,datadir,line1)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -47,9 +47,6 @@
|
||||
character(kind=c_char) :: mygrid(6)
|
||||
character(kind=c_char) :: hiscall(12)
|
||||
character(kind=c_char) :: hisgrid(6)
|
||||
logical(c_bool) :: b_even_seq
|
||||
logical(c_bool) :: b_superfox
|
||||
integer(c_int) :: yymmdd
|
||||
end type params_block
|
||||
|
||||
type, bind(C) :: dec_data
|
||||
|
@ -16,8 +16,8 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,hiscall, &
|
||||
character*4 decsym !"&" for mskspd or "^" for long averages
|
||||
character*37 msgreceived !Decoded message
|
||||
character*37 msglast,msglastswl !Used for dupechecking
|
||||
character*(*) line !Formatted line with UTC dB T Freq Msg
|
||||
character*(*) mycall,hiscall
|
||||
character*80 line !Formatted line with UTC dB T Freq Msg
|
||||
character*12 mycall,hiscall
|
||||
character*37 recent_shmsgs(NSHMEM)
|
||||
character*(*) datadir
|
||||
|
||||
@ -70,19 +70,15 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,hiscall, &
|
||||
msglastswl=' '
|
||||
nsnrlast=-99
|
||||
nsnrlastswl=-99
|
||||
! mycall13=mycall//' '
|
||||
! dxcall13=hiscall//' '
|
||||
mycall13=' '
|
||||
dxcall13=' '
|
||||
mycall13(1:12)=mycall(1:12)
|
||||
dxcall13(1:12)=hiscall(1:12)
|
||||
mycall13=mycall//' '
|
||||
dxcall13=hiscall//' '
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
fc=nrxfreq
|
||||
|
||||
! Reset if mycall or dxcall changes
|
||||
if(mycall13(1:12).ne.mycall(1:12) .or. dxcall13(1:12).ne.hiscall(1:12)) first=.true.
|
||||
if(mycall13(1:12).ne.mycall .or. dxcall13(1:12).ne.hiscall) first=.true.
|
||||
|
||||
! Dupe checking setup
|
||||
if(nutc00.ne.nutc0 .or. tsec.lt.tsec0) then ! reset dupe checker
|
||||
@ -94,7 +90,7 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,hiscall, &
|
||||
endif
|
||||
|
||||
tframe=float(NSPM)/12000.0
|
||||
line(1:1)=char(0)
|
||||
line=char(0)
|
||||
msgreceived=' '
|
||||
max_iterations=10
|
||||
niterations=0
|
||||
|
@ -222,19 +222,13 @@ program q65sim
|
||||
fac=sqrt(1.0/avep)
|
||||
cspread=fac*cspread !Normalize to constant avg power
|
||||
cdat=cspread*cdat !Apply Rayleigh fading
|
||||
endif
|
||||
|
||||
! psig=0.
|
||||
! pnoise=0.
|
||||
! do i=1,npts
|
||||
! if(i.gt.12000 .and. i.lt.624000) then
|
||||
! psig=psig + aimag(cdat(i))**2
|
||||
! pnoise=pnoise + xnoise(i)*xnoise(i)
|
||||
! endif
|
||||
! enddo
|
||||
! pnoise=pnoise*bandwidth_ratio
|
||||
! snr_2500=db(psig/pnoise) !Calibration confirmation!
|
||||
! print*,'SNR_2500:',snr_2500
|
||||
! do i=0,nfft-1
|
||||
! p=real(cspread(i))**2 + aimag(cspread(i))**2
|
||||
! write(14,3010) i,p,cspread(i)
|
||||
!3010 format(i8,3f12.6)
|
||||
! enddo
|
||||
endif
|
||||
|
||||
dat=aimag(cdat) + xnoise !Add generated AWGN noise
|
||||
fac=32767.0
|
||||
|
@ -1,75 +0,0 @@
|
||||
subroutine foxgen2(nslots,cmsg,line,foxcall)
|
||||
|
||||
! Parse old-style Fox messages to extract the necessary pieces for a SuperFox
|
||||
! transmission.
|
||||
|
||||
use packjt77
|
||||
character*120 line
|
||||
character*40 cmsg(5) !Old-style Fox messages are here
|
||||
character*37 msg
|
||||
character*26 sfmsg
|
||||
character*13 mycall
|
||||
character*11 foxcall
|
||||
character*4 mygrid
|
||||
character*6 hiscall_1,hiscall_2
|
||||
character*4 rpt1,rpt2
|
||||
character*13 w(19)
|
||||
integer nw(19)
|
||||
integer ntype !Message type: 0 Free Text
|
||||
! 1 CQ MyCall MyGrid
|
||||
! 2 Call_1 MyCall RR73
|
||||
! 3 Call_1 MyCall rpt1
|
||||
! 4 Call_1 RR73; Call_2 <MyCall> rpt2
|
||||
|
||||
if(nslots.lt.1 .or. nslots.gt.5) return
|
||||
k=0
|
||||
do i=1,nslots
|
||||
hiscall_1=''
|
||||
hiscall_2=''
|
||||
mycall=''
|
||||
mygrid=''
|
||||
rpt1=''
|
||||
rpt2=''
|
||||
msg=cmsg(i)(1:37)
|
||||
call split77(msg,nwords,nw,w)
|
||||
ntype=0
|
||||
if(msg(1:3).eq.'CQ ') then
|
||||
ntype=1
|
||||
mycall=w(2)(1:12)
|
||||
mygrid=w(3)(1:4)
|
||||
else if(index(msg,';').gt.0) then
|
||||
ntype=4
|
||||
hiscall_1=w(1)(1:6)
|
||||
hiscall_2=w(3)(1:6)
|
||||
rpt1='RR73'
|
||||
rpt2=w(5)(1:4)
|
||||
mycall=w(4)(2:nw(4)-1)
|
||||
else if(index(msg,' RR73').gt.0) then
|
||||
ntype=2
|
||||
hiscall_1=w(1)(1:6)
|
||||
mycall=w(2)(1:12)
|
||||
rpt1='RR73'
|
||||
else if(nwords.eq.3 .and. nw(3).eq.3 .and. &
|
||||
(w(3)(1:1).eq.'-' .or. w(3)(1:1).eq.'+')) then
|
||||
ntype=3
|
||||
hiscall_1=w(1)(1:6)
|
||||
mycall=w(2)(1:12)
|
||||
rpt1=w(3)(1:4)
|
||||
endif
|
||||
|
||||
k=k+1
|
||||
if(ntype.le.3) call sfox_assemble(ntype,k,msg(1:26),mycall,mygrid,line)
|
||||
if(ntype.eq.4) then
|
||||
sfmsg=w(1)(1:nw(1))//' '//mycall(1:len(trim(mycall))+1)//'RR73'
|
||||
call sfox_assemble(2,k,sfmsg,mycall,mygrid,line)
|
||||
sfmsg=w(3)(1:nw(3))//' '//mycall(1:len(trim(mycall))+1)//w(5)(1:3)
|
||||
k=k+1
|
||||
call sfox_assemble(3,k,sfmsg,mycall,mygrid,line)
|
||||
endif
|
||||
enddo
|
||||
|
||||
call sfox_assemble(ntype,11,msg(1:26),mycall,mygrid,line) !k=11 to finish up
|
||||
foxcall=mycall(1:11)
|
||||
|
||||
return
|
||||
end subroutine foxgen2
|
@ -1,12 +0,0 @@
|
||||
! LDPC (174,91) code
|
||||
parameter (KK=91) !Information bits (77 + CRC14)
|
||||
parameter (ND=58) !Data symbols
|
||||
parameter (NS=21) !Sync symbols (3 @ Costas 7x7)
|
||||
parameter (NN=NS+ND) !Total channel symbols (79)
|
||||
parameter (NSPS=1920) !Samples per symbol at 12000 S/s
|
||||
parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680)
|
||||
parameter (NMAX=15*12000) !Samples in iwave (180,000)
|
||||
parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra
|
||||
parameter (NSTEP=NSPS/4) !Rough time-sync step size
|
||||
parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps)
|
||||
parameter (NDOWN=60) !Downsample factor
|
@ -1,3 +0,0 @@
|
||||
integer ntag
|
||||
data ntag/z"1234567"/
|
||||
!-----------------------------------------------------------------------
|
@ -1,39 +0,0 @@
|
||||
module julian
|
||||
|
||||
contains
|
||||
|
||||
integer*8 function itime8()
|
||||
|
||||
implicit integer (a-z)
|
||||
! 1 2 3 4 5 6 7
|
||||
integer it(8) !y m d nmin h m s
|
||||
integer*8 secday
|
||||
data secday/86400/
|
||||
|
||||
call date_and_time(values=it)
|
||||
iyr=it(1)
|
||||
imo=it(2)
|
||||
iday=it(3)
|
||||
days=JD(iyr,imo,iday) - 2440588 !Days since epoch Jan 1, 1970
|
||||
ih=it(5)
|
||||
im=it(6)-it(4) !it(4) corrects for time zone
|
||||
is=it(7)
|
||||
nsec=3600*ih + 60*im + is
|
||||
itime8=days*secday + nsec
|
||||
|
||||
return
|
||||
end function itime8
|
||||
|
||||
integer function JD(I,J,K)
|
||||
|
||||
! Return Julian Date for I=year, J=month, K=day
|
||||
! Reference: Fliegel and Van Flandern, Comm. ACM 11, 10, 1968
|
||||
|
||||
JD = K - 32075 + 1461*(I + 4800 + (J - 14)/12)/4 &
|
||||
+ 367*(J - 2 - (J - 14)/12*12)/12 - 3 &
|
||||
*((I + 4900 + (J - 14)/12)/100)/4
|
||||
|
||||
return
|
||||
end function JD
|
||||
|
||||
end module julian
|
@ -1,103 +0,0 @@
|
||||
!*******************************************************************************
|
||||
!>
|
||||
! A simple module for `popen`.
|
||||
|
||||
module popen_module
|
||||
|
||||
use,intrinsic :: iso_c_binding
|
||||
|
||||
implicit none
|
||||
|
||||
private
|
||||
|
||||
! interfaces to C functions
|
||||
interface
|
||||
|
||||
function popen(command, mode) bind(C,name='popen')
|
||||
!! initiate pipe streams to or from a process
|
||||
import :: c_char, c_ptr
|
||||
implicit none
|
||||
character(kind=c_char),dimension(*) :: command
|
||||
character(kind=c_char),dimension(*) :: mode
|
||||
type(c_ptr) :: popen
|
||||
end function popen
|
||||
|
||||
function fgets(s, siz, stream) bind(C,name='fgets')
|
||||
!! get a string from a stream
|
||||
import :: c_char, c_ptr, c_int
|
||||
implicit none
|
||||
type (c_ptr) :: fgets
|
||||
character(kind=c_char),dimension(*) :: s
|
||||
integer(kind=c_int),value :: siz
|
||||
type(c_ptr),value :: stream
|
||||
end function fgets
|
||||
|
||||
function pclose(stream) bind(C,name='pclose')
|
||||
!! close a pipe stream to or from a process
|
||||
import :: c_ptr, c_int
|
||||
implicit none
|
||||
integer(c_int) :: pclose
|
||||
type(c_ptr),value :: stream
|
||||
end function pclose
|
||||
|
||||
end interface
|
||||
|
||||
public :: c2f_string, get_command_as_string
|
||||
|
||||
contains
|
||||
|
||||
!*******************************************************************************
|
||||
!>
|
||||
! Convert a C string to a Fortran string.
|
||||
|
||||
function c2f_string(c) result(f)
|
||||
|
||||
character(len=*),intent(in) :: c !! C string
|
||||
character(len=:),allocatable :: f !! Fortran string
|
||||
|
||||
integer :: i
|
||||
|
||||
i = index(c,c_null_char)
|
||||
|
||||
if (i<=0) then
|
||||
f = c
|
||||
else if (i==1) then
|
||||
f = ''
|
||||
else if (i>1) then
|
||||
f = c(1:i-1)
|
||||
end if
|
||||
|
||||
end function c2f_string
|
||||
|
||||
!*******************************************************************************
|
||||
!>
|
||||
! Return the result of the command as a string.
|
||||
|
||||
function get_command_as_string(command) result(str)
|
||||
|
||||
character(len=*),intent(in) :: command !! the command to run
|
||||
character(len=:),allocatable :: str !! the result of that command
|
||||
|
||||
integer,parameter :: buffer_length = 1000 !! read stream in chunks of this size
|
||||
|
||||
type(c_ptr) :: h !! for `popen`
|
||||
integer(c_int) :: istat !! `pclose` status
|
||||
character(kind=c_char,len=buffer_length) :: line !! buffer to read from `fgets`
|
||||
|
||||
str = ''
|
||||
h = c_null_ptr
|
||||
h = popen(command//c_null_char,'r'//c_null_char)
|
||||
|
||||
if (c_associated(h)) then
|
||||
do while (c_associated(fgets(line,buffer_length,h)))
|
||||
str = str//c2f_string(line)
|
||||
end do
|
||||
istat = pclose(h)
|
||||
end if
|
||||
|
||||
end function get_command_as_string
|
||||
|
||||
!*******************************************************************************
|
||||
end module popen_module
|
||||
!*******************************************************************************
|
||||
|
@ -1,67 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// dbgprintf.c
|
||||
// Functions for printing debug information
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#include "dbgprintf.h"
|
||||
|
||||
// print functions for debug purposes
|
||||
void dbgprintf_vector_uchar(const char* name, const unsigned char* v, int vsize)
|
||||
{
|
||||
int k;
|
||||
|
||||
printf("%s=", name);
|
||||
for (k = 0; k < vsize; k++) {
|
||||
if ((k & 0x0F) == 0)
|
||||
printf("\n");
|
||||
printf("%02X ", v[k]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dbgprintf_vector_float(const char* name, const float* v, int vsize)
|
||||
{
|
||||
int k;
|
||||
|
||||
printf("%s=", name);
|
||||
for (k = 0; k < vsize; k++) {
|
||||
if ((k & 0x07) == 0)
|
||||
printf("\n");
|
||||
printf("%10.3f ", v[k]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dbgprintf_rows_float(const char* name, const float* v, int vsize, int nrows)
|
||||
{
|
||||
int k;
|
||||
int j;
|
||||
|
||||
printf("%s=\n", name);
|
||||
for (j = 0; j < nrows; j++) {
|
||||
printf("r%d:", j);
|
||||
for (k = 0; k < vsize; k++) {
|
||||
if ((k & 0x07) == 0)
|
||||
printf("\n");
|
||||
printf("%7.3f ", v[k]);
|
||||
}
|
||||
printf("\n");
|
||||
v += vsize;
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// dbgprintf.h
|
||||
// Functions for printing debug information
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _dbgprintf_h_
|
||||
#define _dbgprintf_h_
|
||||
|
||||
// Define DBGPRINTF_ANYWAY
|
||||
// in order to print debug information also
|
||||
// when _DEBUG is not defined
|
||||
|
||||
#define DBGPRINTF_ANYWAY
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DBG_PRINTF
|
||||
#else
|
||||
#ifdef DBGPRINTF_ANYWAY
|
||||
#define DBG_PRINTF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// print functions for debug purposes
|
||||
#ifdef DBG_PRINTF
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dbgprintf_vector_uchar(const char* name, const unsigned char* v, int vsize);
|
||||
void dbgprintf_vector_float(const char* name, const float* v, int vsize);
|
||||
void dbgprintf_rows_float(const char* name, const float* v, int vsize, int nrows);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define dbgprintf_vector_uchar(a,b)
|
||||
#define dbgprintf_vector_float(a,b)
|
||||
#define dbgprintf_rows_float(a, b, c, d)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _dbgprintf_h_
|
@ -1,383 +0,0 @@
|
||||
/*
|
||||
|
||||
File name: nhash2.c
|
||||
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* This file is part of the WSPR application, Weak Signal Propogation Reporter
|
||||
*
|
||||
* File Name: nhash.c
|
||||
* Description: Functions to produce 32-bit hashes for hash table lookup
|
||||
*
|
||||
* Copyright (C) 2008-2014 Joseph Taylor, K1JT
|
||||
* License: GNU GPL v3+
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
* Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Files: lookup3.c
|
||||
* Copyright: Copyright (C) 2006 Bob Jenkins <bob_jenkins@burtleburtle.net>
|
||||
* License: public-domain
|
||||
* You may use this code any way you wish, private, educational, or commercial.
|
||||
* It's free.
|
||||
*
|
||||
*-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
These are functions for producing 32-bit hashes for hash table lookup.
|
||||
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
are externally useful functions. Routines to test the hash are included
|
||||
if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
the public domain. It has no warranty.
|
||||
|
||||
You probably want to use hashlittle(). hashlittle() and hashbig()
|
||||
hash byte arrays. hashlittle() is is faster than hashbig() on
|
||||
little-endian machines. Intel and AMD are little-endian machines.
|
||||
On second thought, you probably want hashlittle2(), which is identical to
|
||||
hashlittle() except it returns two 32-bit hashes for the price of one.
|
||||
You could implement hashbig2() if you wanted but I haven't bothered here.
|
||||
|
||||
If you want to find a hash of, say, exactly 7 integers, do
|
||||
a = i1; b = i2; c = i3;
|
||||
mix(a,b,c);
|
||||
a += i4; b += i5; c += i6;
|
||||
mix(a,b,c);
|
||||
a += i7;
|
||||
final(a,b,c);
|
||||
then use c as the hash value. If you have a variable length array of
|
||||
4-byte integers to hash, use hashword(). If you have a byte array (like
|
||||
a character string), use hashlittle(). If you have several byte arrays, or
|
||||
a mix of things, see the comments above hashlittle().
|
||||
|
||||
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
|
||||
then mix those integers. This is fast (you can do a lot more thorough
|
||||
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
|
||||
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
|
||||
*/
|
||||
|
||||
#define SELF_TEST 1
|
||||
|
||||
#include <stdio.h> /* defines printf for tests */
|
||||
#include <time.h> /* defines time_t for timings in the test */
|
||||
#include "nhash2.h"
|
||||
//#include <sys/param.h> /* attempt to define endianness */
|
||||
//#ifdef linux
|
||||
//# include <endian.h> /* attempt to define endianness */
|
||||
//#endif
|
||||
|
||||
#define HASH_LITTLE_ENDIAN 1
|
||||
|
||||
#define hashsize(n) ((uint32_t)1<<(n))
|
||||
#define hashmask(n) (hashsize(n)-1)
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
mix -- mix 3 32-bit values reversibly.
|
||||
|
||||
This is reversible, so any information in (a,b,c) before mix() is
|
||||
still in (a,b,c) after mix().
|
||||
|
||||
If four pairs of (a,b,c) inputs are run through mix(), or through
|
||||
mix() in reverse, there are at least 32 bits of the output that
|
||||
are sometimes the same for one pair and different for another pair.
|
||||
This was tested for:
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
|
||||
satisfy this are
|
||||
4 6 8 16 19 4
|
||||
9 15 3 18 27 15
|
||||
14 9 3 7 17 3
|
||||
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
|
||||
for "differ" defined as + with a one-bit base and a two-bit delta. I
|
||||
used http://burtleburtle.net/bob/hash/avalanche.html to choose
|
||||
the operations, constants, and arrangements of the variables.
|
||||
|
||||
This does not achieve avalanche. There are input bits of (a,b,c)
|
||||
that fail to affect some output bits of (a,b,c), especially of a. The
|
||||
most thoroughly mixed value is c, but it doesn't really even achieve
|
||||
avalanche in c.
|
||||
|
||||
This allows some parallelism. Read-after-writes are good at doubling
|
||||
the number of bits affected, so the goal of mixing pulls in the opposite
|
||||
direction as the goal of parallelism. I did what I could. Rotates
|
||||
seem to cost as much as shifts on every machine I could lay my hands
|
||||
on, and rotates are much kinder to the top and bottom bits, so I used
|
||||
rotates.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define mix(a,b,c) \
|
||||
{ \
|
||||
a -= c; a ^= rot(c, 4); c += b; \
|
||||
b -= a; b ^= rot(a, 6); a += c; \
|
||||
c -= b; c ^= rot(b, 8); b += a; \
|
||||
a -= c; a ^= rot(c,16); c += b; \
|
||||
b -= a; b ^= rot(a,19); a += c; \
|
||||
c -= b; c ^= rot(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
final -- final mixing of 3 32-bit values (a,b,c) into c
|
||||
|
||||
Pairs of (a,b,c) values differing in only a few bits will usually
|
||||
produce values of c that look totally different. This was tested for
|
||||
* pairs that differed by one bit, by two bits, in any combination
|
||||
of top bits of (a,b,c), or in any combination of bottom bits of
|
||||
(a,b,c).
|
||||
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
|
||||
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
|
||||
is commonly produced by subtraction) look like a single 1-bit
|
||||
difference.
|
||||
* the base values were pseudorandom, all zero but one bit set, or
|
||||
all zero plus a counter that starts at zero.
|
||||
|
||||
These constants passed:
|
||||
14 11 25 16 4 14 24
|
||||
12 14 25 16 4 14 24
|
||||
and these came close:
|
||||
4 8 15 26 3 22 24
|
||||
10 8 15 26 3 22 24
|
||||
11 8 15 26 3 22 24
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define final(a,b,c) \
|
||||
{ \
|
||||
c ^= b; c -= rot(b,14); \
|
||||
a ^= c; a -= rot(c,11); \
|
||||
b ^= a; b -= rot(a,25); \
|
||||
c ^= b; c -= rot(b,16); \
|
||||
a ^= c; a -= rot(c,4); \
|
||||
b ^= a; b -= rot(a,14); \
|
||||
c ^= b; c -= rot(b,24); \
|
||||
}
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
hashlittle() -- hash a variable-length key into a 32-bit value
|
||||
k : the key (the unaligned variable-length array of bytes)
|
||||
length : the length of the key, counting by bytes
|
||||
initval : can be any 4-byte value
|
||||
Returns a 32-bit value. Every bit of the key affects every bit of
|
||||
the return value. Two keys differing by one or two bits will have
|
||||
totally different hash values.
|
||||
|
||||
The best hash table sizes are powers of 2. There is no need to do
|
||||
mod a prime (mod is sooo slow!). If you need less than 32 bits,
|
||||
use a bitmask. For example, if you need only 10 bits, do
|
||||
h = (h & hashmask(10));
|
||||
In which case, the hash table should have hashsize(10) elements.
|
||||
|
||||
If you are hashing n strings (uint8_t **)k, do it like this:
|
||||
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
|
||||
|
||||
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
|
||||
code any way you wish, private, educational, or commercial. It's free.
|
||||
|
||||
Use for hash table lookup, or anything where one collision in 2^^32 is
|
||||
acceptable. Do NOT use for cryptographic purposes.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
uint32_t nhash2( const void *key, uint64_t length, uint32_t initval)
|
||||
//int nhash( const char *key, int length, int initval)
|
||||
{
|
||||
uint32_t a,b,c; /* internal state */
|
||||
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
|
||||
|
||||
u.ptr = key;
|
||||
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
|
||||
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
|
||||
|
||||
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
// printf("AAA %x %d %x %d\n",c,c,c&32767,c&32767);
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
/*
|
||||
* "k[2]&0xffffff" actually reads beyond the end of the string, but
|
||||
* then masks off the part it's not allowed to read. Because the
|
||||
* string is aligned, the masked-off tail is in the same word as the
|
||||
* rest of the string. Every machine with memory protection I've seen
|
||||
* does it on word boundaries, so is OK with this. But VALGRIND will
|
||||
* still catch it and complain. The masking trick does make the hash
|
||||
* noticably faster for short strings (like English words).
|
||||
*/
|
||||
#ifndef VALGRIND
|
||||
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
|
||||
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
|
||||
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
|
||||
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
|
||||
case 5 : b+=k[1]&0xff; a+=k[0]; break;
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=k[0]&0xffffff; break;
|
||||
case 2 : a+=k[0]&0xffff; break;
|
||||
case 1 : a+=k[0]&0xff; break;
|
||||
case 0 : return c; /* zero length strings require no mixing */
|
||||
}
|
||||
|
||||
#else /* make valgrind happy */
|
||||
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[1]; a+=k[0]; break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]; break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
|
||||
case 1 : a+=k8[0]; break;
|
||||
case 0 : return c;
|
||||
}
|
||||
|
||||
#endif /* !valgrind */
|
||||
|
||||
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
|
||||
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
|
||||
const uint8_t *k8;
|
||||
|
||||
/*--------------- all but last block: aligned reads and different mixing */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0] + (((uint32_t)k[1])<<16);
|
||||
b += k[2] + (((uint32_t)k[3])<<16);
|
||||
c += k[4] + (((uint32_t)k[5])<<16);
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 6;
|
||||
}
|
||||
|
||||
/*----------------------------- handle the last (probably partial) block */
|
||||
k8 = (const uint8_t *)k;
|
||||
switch(length)
|
||||
{
|
||||
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
|
||||
case 10: c+=k[4];
|
||||
b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 9 : c+=k8[8]; /* fall through */
|
||||
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
|
||||
case 6 : b+=k[2];
|
||||
a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 5 : b+=k8[4]; /* fall through */
|
||||
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
|
||||
break;
|
||||
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
|
||||
case 2 : a+=k[0];
|
||||
break;
|
||||
case 1 : a+=k8[0];
|
||||
break;
|
||||
case 0 : return c; /* zero length requires no mixing */
|
||||
}
|
||||
|
||||
} else { /* need to read the key one byte at a time */
|
||||
const uint8_t *k = (const uint8_t *)key;
|
||||
|
||||
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12)
|
||||
{
|
||||
a += k[0];
|
||||
a += ((uint32_t)k[1])<<8;
|
||||
a += ((uint32_t)k[2])<<16;
|
||||
a += ((uint32_t)k[3])<<24;
|
||||
b += k[4];
|
||||
b += ((uint32_t)k[5])<<8;
|
||||
b += ((uint32_t)k[6])<<16;
|
||||
b += ((uint32_t)k[7])<<24;
|
||||
c += k[8];
|
||||
c += ((uint32_t)k[9])<<8;
|
||||
c += ((uint32_t)k[10])<<16;
|
||||
c += ((uint32_t)k[11])<<24;
|
||||
mix(a,b,c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
|
||||
/*-------------------------------- last block: affect all 32 bits of (c) */
|
||||
switch(length) /* all the case statements fall through */
|
||||
{
|
||||
case 12: c+=((uint32_t)k[11])<<24;
|
||||
/* fall through */
|
||||
case 11: c+=((uint32_t)k[10])<<16;
|
||||
/* fall through */
|
||||
case 10: c+=((uint32_t)k[9])<<8;
|
||||
/* fall through */
|
||||
case 9 : c+=k[8];
|
||||
/* fall through */
|
||||
case 8 : b+=((uint32_t)k[7])<<24;
|
||||
/* fall through */
|
||||
case 7 : b+=((uint32_t)k[6])<<16;
|
||||
/* fall through */
|
||||
case 6 : b+=((uint32_t)k[5])<<8;
|
||||
/* fall through */
|
||||
case 5 : b+=k[4];
|
||||
/* fall through */
|
||||
case 4 : a+=((uint32_t)k[3])<<24;
|
||||
/* fall through */
|
||||
case 3 : a+=((uint32_t)k[2])<<16;
|
||||
/* fall through */
|
||||
case 2 : a+=((uint32_t)k[1])<<8;
|
||||
/* fall through */
|
||||
case 1 : a+=k[0];
|
||||
break;
|
||||
case 0 : return c;
|
||||
}
|
||||
}
|
||||
|
||||
final(a,b,c);
|
||||
return c;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#ifndef NHASH_H_
|
||||
#define NHASH_H_
|
||||
|
||||
#ifdef Win32
|
||||
#include "win_stdint.h" /* defines uint32_t etc */
|
||||
#else
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> /* defines uint32_t etc */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t nhash( const void * key, uint64_t length, uint32_t initval);
|
||||
//int nhash(const char *key, int length, int initval);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,329 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// np_qpc.h
|
||||
// Q-Ary Polar Codes encoding/decoding functions
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "dbgprintf.h"
|
||||
#include "qpc_fwht.h"
|
||||
#include "np_qpc.h"
|
||||
|
||||
// static constant / functions
|
||||
|
||||
static const float knorm = 1.0f / QPC_Q;
|
||||
|
||||
static float* pdf_conv(float *dst, float* pdf1, float* pdf2)
|
||||
{
|
||||
// convolution between two pdf
|
||||
|
||||
float fwht_pdf1[QPC_Q];
|
||||
float fwht_pdf2[QPC_Q];
|
||||
int k;
|
||||
|
||||
qpc_fwht(fwht_pdf1, pdf1);
|
||||
qpc_fwht(fwht_pdf2, pdf2);
|
||||
|
||||
for (k = 0; k < QPC_Q; k++)
|
||||
fwht_pdf1[k] *= fwht_pdf2[k];
|
||||
|
||||
qpc_fwht(dst, fwht_pdf1);
|
||||
|
||||
for (k = 0; k < QPC_Q; k++)
|
||||
dst[k] *= knorm;
|
||||
|
||||
return dst;
|
||||
}
|
||||
static void pdfarray_conv(float* dstarray, float* pdf1array, float* pdf2array, int numrows)
|
||||
{
|
||||
int k;
|
||||
|
||||
// convolutions between rows of pdfs
|
||||
|
||||
for (k = 0; k < numrows; k++) {
|
||||
pdf_conv(dstarray, pdf1array, pdf2array);
|
||||
dstarray += QPC_Q;
|
||||
pdf1array += QPC_Q;
|
||||
pdf2array += QPC_Q;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static float _pdfuniform[QPC_Q];
|
||||
static const float* _pdf_uniform1();
|
||||
static const float* _pdf_uniform0();
|
||||
typedef const float*(*ptr_pdfuniform)(void);
|
||||
|
||||
static ptr_pdfuniform _ptr_pdf_uniform = _pdf_uniform0;
|
||||
|
||||
static const float* _pdf_uniform1()
|
||||
{
|
||||
return _pdfuniform;
|
||||
};
|
||||
static const float* _pdf_uniform0()
|
||||
{
|
||||
// compute uniform pdf once for all
|
||||
int k;
|
||||
for (k = 0; k < QPC_Q; k++)
|
||||
_pdfuniform[k] = knorm;
|
||||
|
||||
// next call to _qpc_pdfuniform
|
||||
// will be handled directly by _pqc_pdfuniform1
|
||||
_ptr_pdf_uniform = _pdf_uniform1;
|
||||
|
||||
return _pdfuniform;
|
||||
};
|
||||
static const float* pdf_uniform()
|
||||
{
|
||||
return _ptr_pdf_uniform();
|
||||
}
|
||||
|
||||
static float * pdf_mul(float *dst, float* pdf1, float* pdf2)
|
||||
{
|
||||
int k;
|
||||
float v;
|
||||
float norm = 0;
|
||||
for (k = 0; k < QPC_Q; k++) {
|
||||
v = pdf1[k] * pdf2[k];
|
||||
dst[k] = v;
|
||||
norm += v;
|
||||
}
|
||||
// if norm of the result is not positive
|
||||
// return in dst a uniform distribution
|
||||
if (norm <= 0)
|
||||
memcpy(dst, pdf_uniform(), QPC_Q * sizeof(float));
|
||||
else {
|
||||
norm = 1.0f / norm;
|
||||
for (k = 0; k < QPC_Q; k++)
|
||||
dst[k] = dst[k] * norm;
|
||||
}
|
||||
|
||||
|
||||
return dst;
|
||||
}
|
||||
static void pdfarray_mul(float* dstarray, float* pdf1array, float* pdf2array, int numrows)
|
||||
{
|
||||
int k;
|
||||
|
||||
// products between rows of pdfs
|
||||
|
||||
for (k = 0; k < numrows; k++) {
|
||||
pdf_mul(dstarray, pdf1array, pdf2array);
|
||||
dstarray += QPC_Q;
|
||||
pdf1array += QPC_Q;
|
||||
pdf2array += QPC_Q;
|
||||
}
|
||||
}
|
||||
|
||||
static float* pdf_convhard(float* dst, const float* pdf, unsigned char hd)
|
||||
{
|
||||
// convolution between a pdf and a hard-decision feedback
|
||||
|
||||
int k;
|
||||
for (k=0;k<QPC_Q;k++)
|
||||
dst[k] = pdf[k^hd];
|
||||
|
||||
return dst;
|
||||
}
|
||||
static void pdfarray_convhard(float* dstarray, const float* pdfarray, const unsigned char *hdarray, int numrows)
|
||||
{
|
||||
int k;
|
||||
|
||||
// hard convolutions between rows
|
||||
|
||||
for (k = 0; k < numrows; k++) {
|
||||
pdf_convhard(dstarray, pdfarray, hdarray[k]);
|
||||
dstarray += QPC_Q;
|
||||
pdfarray += QPC_Q;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char pdf_max(const float* pdf)
|
||||
{
|
||||
int k;
|
||||
|
||||
unsigned char imax = 0;
|
||||
float pdfmax = pdf[0];
|
||||
|
||||
for (k=1;k<QPC_Q;k++)
|
||||
if (pdf[k] > pdfmax) {
|
||||
pdfmax = pdf[k];
|
||||
imax = k;
|
||||
}
|
||||
|
||||
return imax;
|
||||
}
|
||||
|
||||
// local stack functions ---------------------------------------
|
||||
static float _qpc_stack[QPC_N * QPC_Q * 2];
|
||||
static float* _qpc_stack_base = _qpc_stack;
|
||||
|
||||
static float* _qpc_stack_push(int numfloats)
|
||||
{
|
||||
float* addr = _qpc_stack_base;
|
||||
_qpc_stack_base += numfloats;
|
||||
return addr;
|
||||
}
|
||||
static void _qpc_stack_pop(int numfloats)
|
||||
{
|
||||
_qpc_stack_base -= numfloats;
|
||||
}
|
||||
|
||||
// qpc encoder function (internal use) ----------------------------------------------------------
|
||||
unsigned char* _qpc_encode(unsigned char* y, unsigned char* x)
|
||||
{
|
||||
// Non recursive polar encoder
|
||||
// Same architecture of a fast fourier transform
|
||||
// in which the fft butteflies are replaced by the polar transform
|
||||
// butterflies
|
||||
|
||||
int k, j, m;
|
||||
int groups;
|
||||
int bfypergroup;
|
||||
int stepbfy;
|
||||
int stepgroup;
|
||||
int basegroup;
|
||||
int basebfy;
|
||||
|
||||
memcpy(y, x, QPC_N);
|
||||
|
||||
for (k = 0; k < QPC_LOG2N; k++) {
|
||||
groups = 1 << (QPC_LOG2N - 1 - k);
|
||||
stepbfy = bfypergroup = 1 << k;
|
||||
stepgroup = stepbfy << 1;
|
||||
basegroup = 0;
|
||||
for (j = 0; j < groups; j++) {
|
||||
basebfy = basegroup;
|
||||
for (m = 0; m < bfypergroup; m++) {
|
||||
// polar transform
|
||||
y[basebfy + stepbfy] = y[basebfy + stepbfy] ^ y[basebfy];
|
||||
basebfy = basebfy + 1;
|
||||
}
|
||||
basegroup = basegroup + stepgroup;
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
// qpc polar decoder (internal use )--------------------------------------------------
|
||||
void _qpc_decode(unsigned char* xdec, unsigned char* ydec, const float* py, const unsigned char* f, const unsigned char* fsize, const int numrows)
|
||||
{
|
||||
|
||||
if (numrows == 1) {
|
||||
if (fsize[0] == 0) {
|
||||
// dbgprintf_vector_float("py", py, QPC_Q);
|
||||
|
||||
// frozen symbol
|
||||
xdec[0] = pdf_max(py);
|
||||
ydec[0] = f[0];
|
||||
}
|
||||
else {
|
||||
// fsize = 1 => information symbol
|
||||
xdec[0] = pdf_max(py);
|
||||
ydec[0] = xdec[0];
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
int k;
|
||||
int nextrows = numrows >> 1;
|
||||
int size = nextrows << QPC_LOG2Q;
|
||||
|
||||
// upper block variables
|
||||
unsigned char* xdech = xdec + nextrows;
|
||||
unsigned char* ydech = ydec + nextrows;
|
||||
const unsigned char* fh = f + nextrows;
|
||||
const unsigned char* fsizeh = fsize + nextrows;
|
||||
|
||||
// Step 1.
|
||||
// stack and init variables used in the recursion
|
||||
|
||||
float* pyl = _qpc_stack_push(size);
|
||||
memcpy(pyl, py, size * sizeof(float));
|
||||
|
||||
float* pyh = _qpc_stack_push(size);
|
||||
memcpy(pyh, py + size, size * sizeof(float));
|
||||
|
||||
// Step 2. Recursion on upper block
|
||||
// Forward pdf convolutions for the upper block
|
||||
// (place in the lower part of py the convolution of lower and higher blocks)
|
||||
|
||||
// float* pyh = py + size;
|
||||
// pdfarray_conv(py, pyl, pyh, nextrows); // convolution overwriting the lower block of py which is not needed
|
||||
|
||||
pdfarray_conv(pyh, pyl, pyh, nextrows);
|
||||
_qpc_decode(xdech, ydech, pyh, fh, fsizeh, nextrows);
|
||||
|
||||
// Step 3. compute pdfs in the lower block
|
||||
pdfarray_convhard(pyh, py+size, ydech,nextrows); // dst ptr must be different form src ptr
|
||||
pdfarray_mul(pyl, pyl, pyh, nextrows);
|
||||
// we don't need pyh anymore
|
||||
_qpc_stack_pop(size);
|
||||
|
||||
// Step 4. Recursion on the lower block
|
||||
_qpc_decode(xdec, ydec, pyl, f, fsize, nextrows);
|
||||
// we don't need pyl anymore
|
||||
_qpc_stack_pop(size);
|
||||
|
||||
// Step 5. Update backward results
|
||||
// xdec is already ok, we need just to update ydech
|
||||
for (k = 0; k < nextrows; k++)
|
||||
ydech[k] = ydech[k] ^ ydec[k];
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Public encoding/decoding functions ------------------------------------------------
|
||||
void qpc_encode(unsigned char* y, const unsigned char* x)
|
||||
{
|
||||
|
||||
// map information symbols
|
||||
int kk, pos;
|
||||
for (kk = 0; kk < QPC_K; kk++) {
|
||||
pos = qpccode.xpos[kk];
|
||||
qpccode.f[pos] = x[kk];
|
||||
}
|
||||
// do polar encoding
|
||||
_qpc_encode(y, qpccode.f);
|
||||
}
|
||||
void qpc_decode(unsigned char* xdec, unsigned char* ydec, float* py)
|
||||
{
|
||||
int k;
|
||||
unsigned char x[QPC_N];
|
||||
|
||||
// set the first py row with know frozen (punctured) symbol
|
||||
if (qpccode.np < qpccode.n) {
|
||||
// assume that we punctured only the first output symbol
|
||||
memset(py, 0, QPC_Q * sizeof(float));
|
||||
py[qpccode.f[0]] = 1.0f;
|
||||
}
|
||||
|
||||
// decode
|
||||
_qpc_decode(x, ydec, py, qpccode.f, qpccode.fsize, QPC_N);
|
||||
|
||||
// demap information symbols
|
||||
for (k = 0; k < QPC_K; k++)
|
||||
xdec[k] = x[qpccode.xpos[k]];
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// np_qpc.h
|
||||
// Q-Ary Polar Codes encoding/decoding functions
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
#ifndef _np_qpc_h_
|
||||
#define _np_qpc_h_
|
||||
|
||||
#define QPC_LOG2N 7 // log2(codeword length) (not punctured)
|
||||
#define QPC_N (1<<QPC_LOG2N) // codeword length (not punctured)
|
||||
#define QPC_LOG2Q 7 // bits per symbol
|
||||
#define QPC_Q (1<<QPC_LOG2Q) // alphabet size
|
||||
#define QPC_K 50 // number of information symbols
|
||||
|
||||
|
||||
typedef struct {
|
||||
int n; // codeword length (unpunctured)
|
||||
int np; // codeword length (punctured)
|
||||
int k; // number of information symbols
|
||||
int q; // alphabet size
|
||||
int xpos[QPC_N]; // info symbols mapping/demapping tables
|
||||
unsigned char f[QPC_N]; // frozen symbols values
|
||||
unsigned char fsize[QPC_N]; // frozen symbol flag (fsize==0 => frozen)
|
||||
} qpccode_ds;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void qpc_encode(unsigned char* y, const unsigned char* x);
|
||||
void qpc_decode(unsigned char* xdec, unsigned char* ydec, float* py);
|
||||
|
||||
unsigned char* _qpc_encode(unsigned char* y, unsigned char* x);
|
||||
void _qpc_decode(unsigned char* xdec, unsigned char* ydec,
|
||||
const float* py, const unsigned char* f, const unsigned char* fsize,
|
||||
const int numrows);
|
||||
|
||||
extern qpccode_ds qpccode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _np_qpc_h_
|
@ -1,135 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// np_rnd.c
|
||||
// Functions to generate random numbers with uniform/gaussian probability distributions
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "np_rnd.h"
|
||||
|
||||
#if _WIN32 // note the underscore: without it, it's not msdn official!
|
||||
// Windows (x64 and x86)
|
||||
#include <windows.h> // required only for GetTickCount(...)
|
||||
#define K_RAND_MAX UINT_MAX
|
||||
#elif _SVID_SOURCE || _XOPEN_SOURCE || __unix__ || (defined (__APPLE__) && defined(__MACH__)) /* POSIX or Unix or Apple */
|
||||
#include <stdlib.h>
|
||||
#define rand_s(x) (*x)=(unsigned int)lrand48() // returns unsigned integers in the range 0..0x7FFFFFFF
|
||||
#define K_RAND_MAX 0x7FFFFFFF // that's the max number
|
||||
// generated by lrand48
|
||||
#else
|
||||
#error "No good quality PRNG found"
|
||||
#endif
|
||||
|
||||
|
||||
void np_normrnd_real(float *dst, int nitems, float mean, float stdev)
|
||||
{
|
||||
// for odd or even nitems
|
||||
|
||||
unsigned int r;
|
||||
float phi=0, u=0;
|
||||
int set = 0;
|
||||
float scalephi = (M_2PI / (1.0f + K_RAND_MAX));
|
||||
float scaleu = (1.0f / (1.0f + K_RAND_MAX));
|
||||
|
||||
|
||||
while (nitems--)
|
||||
if (set==1) {
|
||||
// generate a second normally distributed number
|
||||
*dst++ = sinf(phi)*u*stdev+mean;
|
||||
set = 0;
|
||||
}
|
||||
else {
|
||||
// generate a uniform distributed phase phi in the range [0,2*PI)
|
||||
rand_s((unsigned int*)&r); phi = scalephi * r;
|
||||
|
||||
// generate a uniform distributed random number u in the range (0,1]
|
||||
rand_s((unsigned int*)&r); u = scaleu * (1.0f + r);
|
||||
|
||||
// generate normally distributed number
|
||||
u = (float)sqrt(-2.0f * log(u));
|
||||
*dst++ = cosf(phi) * u * stdev + mean;
|
||||
|
||||
set=1;
|
||||
}
|
||||
}
|
||||
|
||||
void np_normrnd_cpx(float* dst, int nitems, float mean, float stdev)
|
||||
{
|
||||
// as qpc_normrnd_real, but generates always nitems complex numbers (2*nitems reals)
|
||||
|
||||
unsigned int r;
|
||||
float phi = 0, u = 0;
|
||||
// JHT int set = 0;
|
||||
float scalephi = (M_2PI / (1.0f + K_RAND_MAX));
|
||||
float scaleu = (1.0f / (1.0f + K_RAND_MAX));
|
||||
|
||||
while (nitems--) {
|
||||
// generate a uniform distributed phase phi in the range [0,2*PI)
|
||||
rand_s((unsigned int*)&r); phi = scalephi * r;
|
||||
|
||||
// generate a uniform distributed random number u in the range (0,1]
|
||||
rand_s((unsigned int*)&r); u = scaleu * (1.0f + r);
|
||||
|
||||
// generate normally distributed real and imaginary parts
|
||||
u = (float)sqrt(-2.0f * log(u));
|
||||
*dst++ = cosf(phi) * u * stdev + mean;
|
||||
*dst++ = sinf(phi) * u * stdev + mean;
|
||||
}
|
||||
}
|
||||
|
||||
void np_unidrnd(unsigned int* dst, int nitems, unsigned int nsetsize)
|
||||
{
|
||||
// generate uniform unsigned int random numbers in the range [0..nsetsize)
|
||||
|
||||
unsigned int r;
|
||||
float u;
|
||||
float scaleu = (1.0f / (1.0f + K_RAND_MAX));
|
||||
|
||||
while (nitems--) {
|
||||
rand_s((unsigned int*)&r); u = scaleu * nsetsize * r;
|
||||
*dst++ = (unsigned int)floorf(u);
|
||||
}
|
||||
|
||||
}
|
||||
void np_unidrnd_uc(unsigned char* dst, int nitems, unsigned char nsetsize)
|
||||
{
|
||||
// generate uniform unsigned char random numbers in the range [0..nsetsize)
|
||||
|
||||
unsigned int r;
|
||||
float u;
|
||||
float scaleu = (1.0f / (1.0f + K_RAND_MAX));
|
||||
|
||||
while (nitems--) {
|
||||
rand_s((unsigned int*)&r); u = scaleu * nsetsize * r;
|
||||
*dst++ = (unsigned char)floorf(u);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void np_unifrnd(float* dst, int nitems, float fmax)
|
||||
{
|
||||
// generate uniform float random numbers in the range [0..fmax)
|
||||
|
||||
unsigned int r;
|
||||
float u;
|
||||
float scaleu = (1.0f / (1.0f + K_RAND_MAX));
|
||||
|
||||
while (nitems--) {
|
||||
rand_s((unsigned int*)&r); u = scaleu * fmax * r;
|
||||
*dst++ = u;
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// np_rnd.h
|
||||
// Functions to generate random numbers with uniform/gaussian probability distributions
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _np_rnd_h_
|
||||
#define _np_rnd_h_
|
||||
|
||||
#define _CRT_RAND_S
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#define M_2PI (2.0f*(float)M_PI)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// generate a random array of real numbers with a gaussian distribution of given mean and stdev
|
||||
void np_normrnd_real(float *dst, int nitems, float mean, float stdev);
|
||||
|
||||
// generate a random array of nitems complex numbers with a gaussian distribution of given mean and stdev
|
||||
void np_normrnd_cpx(float* dst, int nitems, float mean, float stdev);
|
||||
|
||||
// generate a random array of nitems unsigned int numbers with uniform distribution
|
||||
// in the range [0 .. nsetsize)
|
||||
void np_unidrnd(unsigned int* dst, int nitems, unsigned int nsetsize);
|
||||
|
||||
// generate a random array of nitems unsigned chars numbers with uniform distribution
|
||||
// in the range [0 .. nsetsize)
|
||||
void np_unidrnd_uc(unsigned char* dst, int nitems, unsigned char nsetsize);
|
||||
|
||||
// generate a random array of nitems float numbers with uniform distribution
|
||||
// in the range [0 .. fmax)
|
||||
void np_unifrnd(float* dst, int nitems, float fmax);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _np_rnd_h_
|
||||
|
@ -1,233 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// qpc_fwht.c
|
||||
// Fast Walsh-Hadamard Transforms for q-ary polar codes
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "qpc_fwht.h"
|
||||
|
||||
static void _qpc_sumdiff8_16(float* y, float* t)
|
||||
{
|
||||
y[0] = t[0] + t[16];
|
||||
y[16] = t[0] - t[16];
|
||||
|
||||
y[1] = t[1] + t[17];
|
||||
y[17] = t[1] - t[17];
|
||||
|
||||
y[2] = t[2] + t[18];
|
||||
y[18] = t[2] - t[18];
|
||||
|
||||
y[3] = t[3] + t[19];
|
||||
y[19] = t[3] - t[19];
|
||||
|
||||
y[4] = t[4] + t[20];
|
||||
y[20] = t[4] - t[20];
|
||||
|
||||
y[5] = t[5] + t[21];
|
||||
y[21] = t[5] - t[21];
|
||||
|
||||
y[6] = t[6] + t[22];
|
||||
y[22] = t[6] - t[22];
|
||||
|
||||
y[7] = t[7] + t[23];
|
||||
y[23] = t[7] - t[23];
|
||||
|
||||
}
|
||||
static void _qpc_sumdiff8_32(float* y, float* t)
|
||||
{
|
||||
y[0] = t[0] + t[32];
|
||||
y[32] = t[0] - t[32];
|
||||
|
||||
y[1] = t[1] + t[33];
|
||||
y[33] = t[1] - t[33];
|
||||
|
||||
y[2] = t[2] + t[34];
|
||||
y[34] = t[2] - t[34];
|
||||
|
||||
y[3] = t[3] + t[35];
|
||||
y[35] = t[3] - t[35];
|
||||
|
||||
y[4] = t[4] + t[36];
|
||||
y[36] = t[4] - t[36];
|
||||
|
||||
y[5] = t[5] + t[37];
|
||||
y[37] = t[5] - t[37];
|
||||
|
||||
y[6] = t[6] + t[38];
|
||||
y[38] = t[6] - t[38];
|
||||
|
||||
y[7] = t[7] + t[39];
|
||||
y[39] = t[7] - t[39];
|
||||
|
||||
}
|
||||
static void _qpc_sumdiff8_64(float* y, float* t)
|
||||
{
|
||||
y[0] = t[0] + t[64];
|
||||
y[64] = t[0] - t[64];
|
||||
|
||||
y[1] = t[1] + t[65];
|
||||
y[65] = t[1] - t[65];
|
||||
|
||||
y[2] = t[2] + t[66];
|
||||
y[66] = t[2] - t[66];
|
||||
|
||||
y[3] = t[3] + t[67];
|
||||
y[67] = t[3] - t[67];
|
||||
|
||||
y[4] = t[4] + t[68];
|
||||
y[68] = t[4] - t[68];
|
||||
|
||||
y[5] = t[5] + t[69];
|
||||
y[69] = t[5] - t[69];
|
||||
|
||||
y[6] = t[6] + t[70];
|
||||
y[70] = t[6] - t[70];
|
||||
|
||||
y[7] = t[7] + t[71];
|
||||
y[71] = t[7] - t[71];
|
||||
|
||||
}
|
||||
|
||||
float* qpc_fwht8(float* y, float* x)
|
||||
{
|
||||
float t[8];
|
||||
|
||||
// first stage
|
||||
y[0] = x[0] + x[1];
|
||||
y[1] = x[0] - x[1];
|
||||
|
||||
y[2] = x[2] + x[3];
|
||||
y[3] = x[2] - x[3];
|
||||
|
||||
y[4] = x[4] + x[5];
|
||||
y[5] = x[4] - x[5];
|
||||
|
||||
y[6] = x[6] + x[7];
|
||||
y[7] = x[6] - x[7];
|
||||
|
||||
// second stage
|
||||
t[0] = y[0] + y[2];
|
||||
t[2] = y[0] - y[2];
|
||||
|
||||
t[1] = y[1] + y[3];
|
||||
t[3] = y[1] - y[3];
|
||||
|
||||
t[4] = y[4] + y[6];
|
||||
t[6] = y[4] - y[6];
|
||||
|
||||
t[5] = y[5] + y[7];
|
||||
t[7] = y[5] - y[7];
|
||||
|
||||
// third stage
|
||||
y[0] = t[0] + t[4];
|
||||
y[4] = t[0] - t[4];
|
||||
|
||||
y[1] = t[1] + t[5];
|
||||
y[5] = t[1] - t[5];
|
||||
|
||||
y[2] = t[2] + t[6];
|
||||
y[6] = t[2] - t[6];
|
||||
|
||||
y[3] = t[3] + t[7];
|
||||
y[7] = t[3] - t[7];
|
||||
|
||||
return y;
|
||||
}
|
||||
float* qpc_fwht16(float* y, float* x)
|
||||
{
|
||||
float t[16];
|
||||
|
||||
qpc_fwht8(t, x);
|
||||
qpc_fwht8(t + 8, x + 8);
|
||||
|
||||
y[0] = t[0] + t[8];
|
||||
y[8] = t[0] - t[8];
|
||||
|
||||
y[1] = t[1] + t[9];
|
||||
y[9] = t[1] - t[9];
|
||||
|
||||
y[2] = t[2] + t[10];
|
||||
y[10] = t[2] - t[10];
|
||||
|
||||
y[3] = t[3] + t[11];
|
||||
y[11] = t[3] - t[11];
|
||||
|
||||
y[4] = t[4] + t[12];
|
||||
y[12] = t[4] - t[12];
|
||||
|
||||
y[5] = t[5] + t[13];
|
||||
y[13] = t[5] - t[13];
|
||||
|
||||
y[6] = t[6] + t[14];
|
||||
y[14] = t[6] - t[14];
|
||||
|
||||
y[7] = t[7] + t[15];
|
||||
y[15] = t[7] - t[15];
|
||||
|
||||
return y;
|
||||
|
||||
}
|
||||
float* qpc_fwht32(float* y, float* x)
|
||||
{
|
||||
float t[32];
|
||||
|
||||
qpc_fwht16(t, x);
|
||||
qpc_fwht16(t + 16, x + 16);
|
||||
|
||||
_qpc_sumdiff8_16(y, t);
|
||||
_qpc_sumdiff8_16(y + 8, t + 8);
|
||||
|
||||
return y;
|
||||
}
|
||||
float* qpc_fwht64(float* y, float* x)
|
||||
{
|
||||
float t[64];
|
||||
|
||||
qpc_fwht32(t, x);
|
||||
qpc_fwht32(t + 32, x + 32);
|
||||
|
||||
_qpc_sumdiff8_32(y, t);
|
||||
_qpc_sumdiff8_32(y + 8, t + 8);
|
||||
_qpc_sumdiff8_32(y + 16, t + 16);
|
||||
_qpc_sumdiff8_32(y + 24, t + 24);
|
||||
|
||||
return y;
|
||||
}
|
||||
float* qpc_fwht128(float* y, float* x)
|
||||
{
|
||||
float t[128];
|
||||
|
||||
qpc_fwht64(t, x);
|
||||
qpc_fwht64(t + 64, x + 64);
|
||||
|
||||
_qpc_sumdiff8_64(y, t);
|
||||
_qpc_sumdiff8_64(y + 8, t + 8);
|
||||
_qpc_sumdiff8_64(y + 16, t + 16);
|
||||
_qpc_sumdiff8_64(y + 24, t + 24);
|
||||
_qpc_sumdiff8_64(y + 32, t + 32);
|
||||
_qpc_sumdiff8_64(y + 40, t + 40);
|
||||
_qpc_sumdiff8_64(y + 48, t + 48);
|
||||
_qpc_sumdiff8_64(y + 56, t + 56);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
// functions over pdfs used by the decoder -----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
@ -1,57 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// qpc_fwht.h
|
||||
// Fast Walsh-Hadamard Transforms for q-ary polar codes
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// This source is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
// This file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this source distribution.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef _qpc_fwht_h_
|
||||
#define _qpc_fwht_h_
|
||||
|
||||
#include "np_qpc.h"
|
||||
|
||||
#if QPC_LOG2Q==7
|
||||
#define qpc_fwht(a,b) qpc_fwht128(a,b)
|
||||
#endif
|
||||
#if QPC_LOG2Q==6
|
||||
#define qpc_fwht(a,b) qpc_fwht64(a,b)
|
||||
#endif
|
||||
#if QPC_LOG2Q==5
|
||||
#define qpc_fwht(a,b) qpc_fwht32(a,b)
|
||||
#endif
|
||||
#if QPC_LOG2Q==4
|
||||
#define qpc_fwht(a,b) qpc_fwht16(a,b)
|
||||
#endif
|
||||
// Note that it makes no sense to use fast convolutions
|
||||
// for transforms that are less than 16 symbols in size.
|
||||
// For such cases direct convolutions are faster.
|
||||
#if QPC_LOG2Q==3
|
||||
#define qpc_fwht(a,b) qpc_fwht8(a,b)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
float* qpc_fwht8(float* y, float* x);
|
||||
float* qpc_fwht16(float* y, float* x);
|
||||
float* qpc_fwht32(float* y, float* x);
|
||||
float* qpc_fwht64(float* y, float* x);
|
||||
float* qpc_fwht128(float* y, float* x);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _qpc_fwht_h_
|
@ -1,198 +0,0 @@
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// qpc_main.cpp
|
||||
//
|
||||
// Test the WER performance of the QPC (127,50) Q=128 code
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "dbgprintf.h"
|
||||
#include "qpc_fwht.h"
|
||||
#include "np_qpc.h"
|
||||
|
||||
// for random numbers generation and NCFSK Rayleigh channel simulation
|
||||
#include "np_rnd.h"
|
||||
void qpc_channel(float* yout, unsigned char* y, float EsNo)
|
||||
{
|
||||
// compute channel outputs amplitudes
|
||||
|
||||
int k;
|
||||
|
||||
// generate noise samples -----------------------------------------
|
||||
float sigman = 1.0f / sqrtf(2.0f);
|
||||
np_normrnd_cpx(yout, QPC_N * QPC_Q, 0, sigman);
|
||||
|
||||
// dbgprintf_rows_float("yout", yout, QPC_Q*2, QPC_N);
|
||||
|
||||
// generate rayleigh distributed signal amplitudes -----------------
|
||||
float symamps[QPC_N * 2];
|
||||
np_normrnd_cpx(symamps, QPC_N, 0, sigman);
|
||||
|
||||
// dbgprintf_vector_float("symamps", symamps, QPC_N*2);
|
||||
|
||||
// normalize signal amps to unity ----------------------------------
|
||||
float pwr = 0.0f;
|
||||
float* psymamps = symamps;
|
||||
// compute sig power
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
pwr += psymamps[0] * psymamps[0] + psymamps[1] * psymamps[1];
|
||||
psymamps += 2;
|
||||
}
|
||||
pwr = pwr / QPC_N;
|
||||
|
||||
// normalize to avg EsNo
|
||||
float norm = sqrtf(EsNo/pwr);
|
||||
psymamps = symamps;
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
psymamps[0] *= norm;
|
||||
psymamps[1] *= norm;
|
||||
psymamps += 2;
|
||||
}
|
||||
// dbgprintf_vector_float("symamps norm", symamps, QPC_N * 2);
|
||||
|
||||
// add signal amplitudes to noise -----------------------------------
|
||||
float *pyout = yout;
|
||||
psymamps= symamps;
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
pyout[y[k]<<1] += psymamps[0];
|
||||
pyout[(y[k]<<1)+1] += psymamps[1];
|
||||
pyout += (QPC_Q*2);
|
||||
psymamps += 2;
|
||||
}
|
||||
|
||||
// dbgprintf_rows_float("s+n out", yout, QPC_Q * 2, QPC_N);
|
||||
|
||||
return;
|
||||
}
|
||||
void qpc_likelihoods(float* py, float* yout, float EsNo, float No)
|
||||
{
|
||||
// compute symbols likelihoods
|
||||
// (rayleigh channel)
|
||||
|
||||
int k, j;
|
||||
|
||||
float norm = EsNo / (EsNo + 1) / No;
|
||||
|
||||
// compute likelihoods from energies ----------------------------
|
||||
float* pybase;
|
||||
float* ppyout = yout;
|
||||
float normpwr;
|
||||
float normpwrmax;
|
||||
float pynorm;
|
||||
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
|
||||
// compute loglikelihoods and largest one from energies
|
||||
pybase = py + k * QPC_Q;
|
||||
normpwrmax = 0.0f;
|
||||
for (j = 0; j < QPC_Q; j++) {
|
||||
normpwr = norm * (ppyout[0] * ppyout[0] + ppyout[1] * ppyout[1]);
|
||||
pybase[j] = normpwr;
|
||||
if (normpwr > normpwrmax)
|
||||
normpwrmax = normpwr;
|
||||
ppyout += 2;
|
||||
}
|
||||
// subtract largest exponent
|
||||
pynorm = 0.0f;
|
||||
for (j = 0; j < QPC_Q; j++) {
|
||||
pybase[j] = expf(pybase[j] - normpwrmax);
|
||||
pynorm += pybase[j];
|
||||
}
|
||||
// normalize to probabilities
|
||||
pynorm = 1.0f / pynorm;
|
||||
for (j = 0; j < QPC_Q; j++)
|
||||
pybase[j] = pybase[j] * pynorm;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int k;
|
||||
|
||||
int NT = 20000; // number of transmissions to simultate
|
||||
float EbNodB = 3.7f; // Eb/No to simulate
|
||||
|
||||
|
||||
int kc = qpccode.k;
|
||||
int np = qpccode.np;
|
||||
float Rc = 1.0f * kc / np;
|
||||
float Tm = 10.0f; // message duration
|
||||
float Rb = 1.0f / Tm * (QPC_K - 2) * QPC_LOG2Q; // Bit rate assuming two symbols for CRC
|
||||
|
||||
float EsNodB = EbNodB + 10.0f * log10f(Rc * QPC_LOG2Q);
|
||||
|
||||
static unsigned char xin[QPC_K]; // input information symbols
|
||||
static unsigned char xdec[QPC_K]; // decoded information symbols
|
||||
static unsigned char y[QPC_N]; // encoded codeword
|
||||
static unsigned char ydec[QPC_N]; // decoded codeword
|
||||
|
||||
static float yout[QPC_N * QPC_Q * 2]; // channel complex amplitutes output
|
||||
static float py[QPC_N * QPC_Q]; // channel output probabilities
|
||||
|
||||
float EsNo = powf(10.0f, EsNodB / 10.0f);
|
||||
float No = 1.0f;
|
||||
|
||||
//JHT static float we;
|
||||
static float wer;
|
||||
|
||||
int kk;
|
||||
|
||||
printf("QPC Word Error Rate Test\n");
|
||||
printf("Polar Code (%d,%d) Q=%d for the Rayleigh channel\n", qpccode.np, qpccode.k, qpccode.q);
|
||||
printf("Eb/No = %.1f dB\n", EbNodB);
|
||||
printf("Es/No = %.1f dB\n", EsNodB);
|
||||
printf("Tmsg = %.1f s\n", Tm);
|
||||
printf("Bit Rate = %.1f bit/s\n", Rb);
|
||||
printf("SNR(2500) = %.1f dB\n\n", EbNodB + 10.0f * log10f(Rb/ 2500));
|
||||
|
||||
|
||||
for (k = 0; k < NT; k++) {
|
||||
|
||||
np_unidrnd_uc(xin, QPC_K, QPC_Q); // generate random information symbols
|
||||
|
||||
qpc_encode(y, xin); // encode
|
||||
|
||||
// compute channel outputs and probabilities
|
||||
|
||||
// Note that if the code is punctured (i.e. N=127)
|
||||
// the first codeword symbol must not be transmitted over the channel
|
||||
// Here, in order to avoid useless copies,
|
||||
// the vector of likelihoods py continues to be a QPC_N*QPC_Q vector of floats.
|
||||
// The first received symbol likelihoods should start always at offset QPC_Q.
|
||||
// The first QPC_Q positions of py will be ignored (and set) by the decoder.
|
||||
qpc_channel(yout, y, EsNo);
|
||||
|
||||
// The decoder can't estimate the EsNo easily
|
||||
// so we assume that in any case it is 5 dB
|
||||
float EsNoDec = 3.16;
|
||||
qpc_likelihoods(py, yout, EsNoDec, No);
|
||||
|
||||
qpc_decode(xdec, ydec, py); // decode
|
||||
|
||||
// count words in errors
|
||||
for (kk = 0; kk < QPC_K; kk++)
|
||||
if (xin[kk] ^ xdec[kk]) {
|
||||
wer += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// show the decoder performance every 200 codewords transmissions
|
||||
if ((k % 200) == 0 && k>0) {
|
||||
printf("k=%6d/%6d wer = %8.2E\n", k, NT, wer / k);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
}
|
||||
// show the final result
|
||||
printf("k=%6d/%6d wer = %8.2E\n", k, NT, wer / k);
|
||||
printf("\nAll done.\n");
|
||||
return 0;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
module qpc_mod
|
||||
interface
|
||||
integer(c_int32_t) function nhash2 (xin, length, initval) bind(C, &
|
||||
name="nhash2")
|
||||
use iso_c_binding, only: c_signed_char, c_int64_t, c_int32_t
|
||||
integer(c_int64_t), intent(in), value :: length
|
||||
integer(c_signed_char), intent(in) :: xin(length)
|
||||
integer(c_int32_t), intent(in), value :: initval
|
||||
end function nhash2
|
||||
end interface
|
||||
|
||||
interface
|
||||
subroutine qpc_encode(y, xin) bind(C,name="qpc_encode")
|
||||
use iso_c_binding, only: c_ptr, c_signed_char
|
||||
integer(c_signed_char), intent(out) :: y(127)
|
||||
integer(c_signed_char), intent(in) :: xin(50)
|
||||
end subroutine qpc_encode
|
||||
end interface
|
||||
|
||||
interface
|
||||
subroutine qpc_channel(yout, y, EsNo) bind(C,name="qpc_channel")
|
||||
use iso_c_binding, only: c_float_complex, c_float, c_signed_char
|
||||
complex(c_float_complex), intent(out) :: yout(128,128)
|
||||
integer(c_signed_char), intent(out) :: y(127)
|
||||
real(c_float), intent(in), value :: EsNo
|
||||
end subroutine qpc_channel
|
||||
end interface
|
||||
|
||||
interface
|
||||
subroutine qpc_decode(xdec, ydec, py) bind(C,name="qpc_decode")
|
||||
use iso_c_binding, only: c_float, c_signed_char
|
||||
real(c_float), intent(in) :: py(128,128)
|
||||
integer(c_signed_char), intent(out) :: ydec(127)
|
||||
integer(c_signed_char), intent(out) :: xdec(50)
|
||||
end subroutine qpc_decode
|
||||
end interface
|
||||
|
||||
end module qpc_mod
|
@ -1,60 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// qpc_n127k50q128.c
|
||||
//
|
||||
// Defines the parameters of the q-ary polar code (127,50) Q=128
|
||||
// for WSJT-X
|
||||
// ------------------------------------------------------------------------------
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
// WARNING:
|
||||
// This source is NOT free software and it is licensed only for use with WSJT-X.
|
||||
// No derived work is authorized to use this code without the written
|
||||
// permission of his author (Nico Palermo / IV3NWV) who owns all the rights
|
||||
// of this IP (intellectual property).
|
||||
//
|
||||
// This file is distributed ONLY for the purpose of documenting and making of
|
||||
// public domain the encoding scheme used in WSJT-X so that the transmitted
|
||||
// messages can be decoded by anybody.
|
||||
// Anyway this does not imply that one could use the following tables in a
|
||||
// derived work without an explicit and written authorization from his author.
|
||||
// Any unauthorized use, as for any intellectual property, is simply
|
||||
// illegal.
|
||||
// -------------------------------------------------------------------------------
|
||||
#include "np_qpc.h"
|
||||
qpccode_ds qpccode = {
|
||||
128, //n
|
||||
127, //np
|
||||
50, //k
|
||||
128, //q
|
||||
{
|
||||
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 16, 32, 17, 18, 64, 20,
|
||||
33, 34, 24, 7, 11, 36, 13, 19, 14, 65, 40, 21, 66, 22, 35, 68,
|
||||
25, 48, 37, 26, 72, 15, 38, 28, 41, 67, 23, 80, 42, 69, 49, 96,
|
||||
44, 27, 70, 50, 73, 39, 29, 52, 74, 30, 56, 81, 76, 43, 82, 84,
|
||||
97, 45, 71, 88, 98, 46, 100, 51, 104, 53, 75, 112, 54, 57, 99, 119,
|
||||
92, 77, 58, 117, 59, 83, 106, 31, 85, 108, 115, 116, 122, 125, 124, 91,
|
||||
61, 90, 89, 111, 78, 93, 94, 126, 86, 107, 110, 118, 121, 62, 120, 87,
|
||||
105, 55, 114, 60, 127, 63, 103, 101, 123, 95, 102, 47, 109, 79, 113, 0
|
||||
},
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
},
|
||||
{
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}
|
||||
};
|
@ -1,115 +0,0 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// qpc_test.cpp
|
||||
//
|
||||
// Test the WER performance of the QPC (127,50) Q=128 code
|
||||
//
|
||||
// (c) 2024 - Nico Palermo, IV3NWV - Microtelecom Srl, Italy
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "dbgprintf.h"
|
||||
#include "qpc_fwht.h"
|
||||
#include "np_qpc.h"
|
||||
|
||||
#include "nhash2.h"
|
||||
|
||||
// for random numbers generation and NCFSK Rayleigh channel simulation
|
||||
#include "np_rnd.h"
|
||||
void qpc_channel(float* yout, unsigned char* y, float EsNo)
|
||||
{
|
||||
// compute channel outputs amplitudes
|
||||
|
||||
int k;
|
||||
|
||||
// generate noise samples -----------------------------------------
|
||||
float sigman = 1.0f / sqrtf(2.0f);
|
||||
np_normrnd_cpx(yout, QPC_N * QPC_Q, 0, sigman);
|
||||
|
||||
// dbgprintf_rows_float("yout", yout, QPC_Q*2, QPC_N);
|
||||
|
||||
// generate rayleigh distributed signal amplitudes -----------------
|
||||
float symamps[QPC_N * 2];
|
||||
np_normrnd_cpx(symamps, QPC_N, 0, sigman);
|
||||
|
||||
// dbgprintf_vector_float("symamps", symamps, QPC_N*2);
|
||||
|
||||
// normalize signal amps to unity ----------------------------------
|
||||
float pwr = 0.0f;
|
||||
float* psymamps = symamps;
|
||||
// compute sig power
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
pwr += psymamps[0] * psymamps[0] + psymamps[1] * psymamps[1];
|
||||
psymamps += 2;
|
||||
}
|
||||
pwr = pwr / QPC_N;
|
||||
|
||||
// normalize to avg EsNo
|
||||
float norm = sqrtf(EsNo/pwr);
|
||||
psymamps = symamps;
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
psymamps[0] *= norm;
|
||||
psymamps[1] *= norm;
|
||||
psymamps += 2;
|
||||
}
|
||||
// dbgprintf_vector_float("symamps norm", symamps, QPC_N * 2);
|
||||
|
||||
// add signal amplitudes to noise -----------------------------------
|
||||
float *pyout = yout;
|
||||
psymamps= symamps;
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
pyout[y[k]<<1] += psymamps[0];
|
||||
pyout[(y[k]<<1)+1] += psymamps[1];
|
||||
pyout += (QPC_Q*2);
|
||||
psymamps += 2;
|
||||
}
|
||||
|
||||
// dbgprintf_rows_float("s+n out", yout, QPC_Q * 2, QPC_N);
|
||||
|
||||
return;
|
||||
}
|
||||
void qpc_likelihoods(float* py, float* yout, float EsNo, float No)
|
||||
{
|
||||
// compute symbols likelihoods
|
||||
// (rayleigh channel)
|
||||
|
||||
int k, j;
|
||||
|
||||
float norm = EsNo / (EsNo + 1) / No;
|
||||
|
||||
// compute likelihoods from energies ----------------------------
|
||||
float* pybase;
|
||||
float* ppyout = yout;
|
||||
float normpwr;
|
||||
float normpwrmax;
|
||||
float pynorm;
|
||||
|
||||
for (k = 0; k < QPC_N; k++) {
|
||||
|
||||
// compute loglikelihoods and largest one from energies
|
||||
pybase = py + k * QPC_Q;
|
||||
normpwrmax = 0.0f;
|
||||
for (j = 0; j < QPC_Q; j++) {
|
||||
normpwr = norm * (ppyout[0] * ppyout[0] + ppyout[1] * ppyout[1]);
|
||||
pybase[j] = normpwr;
|
||||
if (normpwr > normpwrmax)
|
||||
normpwrmax = normpwr;
|
||||
ppyout += 2;
|
||||
}
|
||||
// subtract largest exponent
|
||||
pynorm = 0.0f;
|
||||
for (j = 0; j < QPC_Q; j++) {
|
||||
pybase[j] = expf(pybase[j] - normpwrmax);
|
||||
pynorm += pybase[j];
|
||||
}
|
||||
// normalize to probabilities
|
||||
pynorm = 1.0f / pynorm;
|
||||
for (j = 0; j < QPC_Q; j++)
|
||||
pybase[j] = pybase[j] * pynorm;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
subroutine qpc_decode2(c0,fsync,ftol,xdec,ndepth,dth,damp,crc_ok, &
|
||||
snrsync,fbest,tbest,snr)
|
||||
|
||||
use qpc_mod
|
||||
|
||||
parameter(NMAX=15*12000,NFT=365,NZ=100)
|
||||
complex c0(NMAX) !Signal as received
|
||||
complex c(NMAX) !Signal as received
|
||||
real py(0:127,0:127) !Probabilities for received synbol values
|
||||
real py0(0:127,0:127) !Probabilities for strong signal
|
||||
real pyd(0:127,0:127) !Dithered values for py
|
||||
real s2(0:127,0:151) !Symbol spectra, including sync
|
||||
real s3(0:127,0:127) !Synchronized symbol spectra
|
||||
real No
|
||||
integer crc_chk,crc_sent
|
||||
integer*8 n47
|
||||
integer idf(NZ),idt(NZ)
|
||||
integer nseed(33)
|
||||
integer*1 xdec(0:49) !Decoded message
|
||||
integer*1 ydec(0:127) !Decoded symbols
|
||||
logical crc_ok
|
||||
integer maxdither(8)
|
||||
integer isync(24) !Symbol numbers for sync tones
|
||||
data isync/1,2,4,7,11,16,22,29,37,39,42,43,45,48,52,57,63,70,78,80,83, &
|
||||
84,86,89/
|
||||
data n47/47/,maxdither/20,50,100,200,500,1000,2000,5000/
|
||||
data nseed/ &
|
||||
321278106, -658879006, 1239150429, -941466001, -698554454, &
|
||||
1136210962, 1633585627, 1261915021, -1134191465, -487888229, &
|
||||
2131958895, -1429290834, -1802468092, 1801346659, 1966248904, &
|
||||
402671397, -1961400750, -1567227835, 1895670987, -286583128, &
|
||||
-595933665, -1699285543, 1518291336, 1338407128, 838354404, &
|
||||
-2081343776, -1449416716, 1236537391, -133197638, 337355509, &
|
||||
-460640480, 1592689606, 0/
|
||||
|
||||
data idf/0, 0, -1, 0, -1, 1, 0, -1, 1, -2, 0, -1, 1, -2, 2, &
|
||||
0, -1, 1, -2, 2, -3, 0, -1, 1, -2, 2, -3, 3, 0, -1, &
|
||||
1, -2, 2, -3, 3, -4, 0, -1, 1, -2, 2, -3, 3, -4, 4, &
|
||||
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, -1, 1, -2, 2, -3, &
|
||||
3, -4, 4, -5, 1, -2, 2, -3, 3, -4, 4, -5, -2, 2, -3, &
|
||||
3, -4, 4, -5, 2, -3, 3, -4, 4, -5, -3, 3, -4, 4, -5, &
|
||||
3, -4, 4, -5, -4, 4, -5, 4, -5, -5/
|
||||
data idt/0 , -1, 0, 1, -1, 0, -2, 1, -1, 0, 2, -2, 1, -1, 0, &
|
||||
-3, 2, -2, 1, -1, 0, 3, -3, 2, -2, 1, -1, 0, -4, 3, &
|
||||
-3, 2, -2, 1, -1, 0, 4, -4, 3, -3, 2, -2, 1, -1, 0, &
|
||||
-5, 4, -4, 3, -3, 2, -2, 1, -1, 0, -5, 4, -4, 3, -3, &
|
||||
2, -2, 1, -1, -5, 4, -4, 3, -3, 2, -2, 1, -5, 4, -4, &
|
||||
3, -3, 2, -2, -5, 4, -4, 3, -3, 2, -5, 4, -4, 3, -3, &
|
||||
-5, 4, -4, 3, -5, 4, -4, -5, 4, -5/
|
||||
|
||||
|
||||
fsample=12000.0
|
||||
baud=12000.0/1024.0
|
||||
nstype=1
|
||||
n47=47
|
||||
mask21=2**21 - 1
|
||||
crc_ok=.false.
|
||||
|
||||
call qpc_sync(c0,fsample,isync,fsync,ftol,f2,t2,snrsync)
|
||||
f00=1500.0 + f2
|
||||
t00=t2
|
||||
fbest=f00
|
||||
tbest=t00
|
||||
maxd=1
|
||||
if(ndepth.gt.0) maxd=maxdither(ndepth)
|
||||
maxft=NZ
|
||||
if(snrsync.lt.4.0 .or. ndepth.le.0) maxft=1
|
||||
do idith=1,maxft
|
||||
if(idith.ge.2) maxd=1
|
||||
deltaf=idf(idith)*0.5
|
||||
deltat=idt(idith)*8.0/1024.0
|
||||
f=f00+deltaf
|
||||
t=t00+deltat
|
||||
fshift=1500.0 - (f+baud) !Shift frequencies down by f + 1 bin
|
||||
call twkfreq2(c0,c,NMAX,fsample,fshift)
|
||||
a=1.0
|
||||
b=0.0
|
||||
do kk=1,4
|
||||
if(kk.eq.2) b=0.4
|
||||
if(kk.eq.3) b=0.5
|
||||
if(kk.eq.4) b=0.6
|
||||
call sfox_demod(c,1500.0,t,isync,s2,s3) !Compute s2 and s3
|
||||
|
||||
if(b.gt.0.0) then
|
||||
do j=0,127
|
||||
call smo121a(s3(:,j),128,a,b)
|
||||
enddo
|
||||
endif
|
||||
call pctile(s3,128*128,50,base3)
|
||||
s3=s3/base3
|
||||
|
||||
EsNoDec=3.16
|
||||
No=1.
|
||||
py0=s3
|
||||
call qpc_likelihoods2(py,s3,EsNoDec,No) !For weak signals
|
||||
|
||||
call random_seed(put=nseed)
|
||||
do kkk=1,maxd
|
||||
if(kkk.eq.1) then
|
||||
pyd=py0
|
||||
else
|
||||
pyd=0.
|
||||
if(kkk.gt.2) then
|
||||
call random_number(pyd)
|
||||
pyd=2.0*(pyd-0.5)
|
||||
endif
|
||||
where(py.gt.dth) pyd=0. !Don't perturb large likelihoods
|
||||
pyd=py*(1.0 + damp*pyd) !Compute dithered likelihood
|
||||
endif
|
||||
do j=0,127
|
||||
ss=sum(pyd(:,j))
|
||||
if(ss.gt.0.0) then
|
||||
pyd(:,j)=pyd(:,j)/ss
|
||||
else
|
||||
pyd(:,j)=0.0
|
||||
endif
|
||||
enddo
|
||||
|
||||
call qpc_decode(xdec,ydec,pyd)
|
||||
xdec=xdec(49:0:-1)
|
||||
crc_chk=iand(nhash2(xdec,n47,571),mask21) !Compute crc_chk
|
||||
crc_sent=128*128*xdec(47) + 128*xdec(48) + xdec(49)
|
||||
crc_ok=crc_chk.eq.crc_sent
|
||||
|
||||
if(crc_ok) then
|
||||
call qpc_snr(s3,ydec,snr)
|
||||
if(snr.lt.-16.5) crc_ok=.false.
|
||||
! write(61,3061) idith,kk,kkk,idf(idith),idt(idith),a,b
|
||||
!3061 format(5i5,2f8.3)
|
||||
return
|
||||
endif
|
||||
enddo !kk: dither of smoothing weights
|
||||
enddo !kkk: dither of probabilities
|
||||
enddo !idith: dither of frequency and time
|
||||
return
|
||||
end subroutine qpc_decode2
|
||||
|
||||
subroutine smo121a(x,nz,a,b)
|
||||
|
||||
real x(nz)
|
||||
fac=1.0/(a+2*b)
|
||||
x0=x(1)
|
||||
do i=2,nz-1
|
||||
x1=x(i)
|
||||
x(i)=fac*(a*x(i) + b*(x0+x(i+1)))
|
||||
x0=x1
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine smo121a
|
@ -1,28 +0,0 @@
|
||||
subroutine qpc_likelihoods2(py,s3,EsNo,No)
|
||||
|
||||
integer QQ,QN
|
||||
parameter(QQ=128,QN=128)
|
||||
real py(0:QQ-1,0:QN-1)
|
||||
real s3(0:QQ-1,0:QN-1)
|
||||
real No,norm,normpwr,normpwrmax
|
||||
|
||||
norm=(EsNo/(EsNo+1.0))/No
|
||||
|
||||
! Compute likelihoods for symbol values, from the symbol power spectra
|
||||
do k=0,QN-1
|
||||
normpwrmax=0.
|
||||
do j=0,QQ-1
|
||||
normpwr=norm*s3(j,k)
|
||||
py(j,k)=normpwr
|
||||
normpwrmax=max(normpwr,normpwrmax)
|
||||
enddo
|
||||
pynorm=0.
|
||||
do j=0,QQ-1
|
||||
py(j,k)=exp(py(j,k)-normpwrmax)
|
||||
pynorm=pynorm + py(j,k)
|
||||
enddo
|
||||
py(0:QQ-1,k)=py(0:QQ-1,k)/pynorm !Normalize to probabilities
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine qpc_likelihoods2
|
@ -1,17 +0,0 @@
|
||||
subroutine qpc_snr(s3,y,snr)
|
||||
|
||||
use qpc_mod
|
||||
! real s2(0:NQ-1,0:151) !Symbol spectra, including sync
|
||||
real s3(0:127,0:127) !Synchronized symbol spectra
|
||||
integer*1 y(0:127) !Encoded symbols
|
||||
! integer isync(24)
|
||||
|
||||
p=0.
|
||||
do j=1,127
|
||||
i=y(j)
|
||||
p=p + s3(i,j)
|
||||
enddo
|
||||
snr=db(p/127.0) - db(127.0) - 4.0
|
||||
|
||||
return
|
||||
end subroutine qpc_snr
|
@ -1,101 +0,0 @@
|
||||
subroutine qpc_sync(crcvd0,fsample,isync,fsync,ftol,f2,t2,snrsync)
|
||||
|
||||
parameter(N9SEC=9*12000,NMAX=15*12000,NDOWN=16,NZ=N9SEC/NDOWN)
|
||||
complex crcvd0(NMAX) !Signal as received
|
||||
complex c0(0:N9SEC-1) !For long FFT
|
||||
complex c1(0:NZ-1)
|
||||
complex c1sum(0:NZ-1)
|
||||
complex z
|
||||
real s(N9SEC/4)
|
||||
real p(-1125:1125)
|
||||
integer ipk(1)
|
||||
integer isync(24)
|
||||
|
||||
baud=12000.0/1024.0
|
||||
df2=fsample/N9SEC
|
||||
fac=1.0/N9SEC
|
||||
c0=fac*crcvd0(1:N9SEC)
|
||||
call four2a(c0,N9SEC,1,-1,1) !Forward c2c FFT
|
||||
iz=N9SEC/4
|
||||
do i=1,iz
|
||||
s(i)=real(c0(i))**2 + aimag(c0(i))**2
|
||||
enddo
|
||||
|
||||
do i=1,4 !Smooth the spectrum a bit
|
||||
call smo121(s,iz)
|
||||
enddo
|
||||
|
||||
ia=nint((fsync-ftol)/df2)
|
||||
ib=nint((fsync+ftol)/df2)
|
||||
ipk=maxloc(s(ia:ib))
|
||||
i0=ipk(1) + ia - 1
|
||||
f2=df2*i0-750.0 ! f2 is the offset from nominal 750 Hz.
|
||||
ia=nint(i0-baud/df2)
|
||||
ib=nint(i0+baud/df2)
|
||||
s1=0.0
|
||||
s0=0.0
|
||||
do i=ia,ib
|
||||
s0=s0+s(i)
|
||||
s1=s1+(i-i0)*s(i)
|
||||
enddo
|
||||
delta=s1/s0
|
||||
i0=nint(i0+delta)
|
||||
f2=i0*df2-750.0
|
||||
|
||||
c1=0.
|
||||
ia=nint(i0-baud/df2)
|
||||
ib=nint(i0+baud/df2)
|
||||
do i=ia,ib
|
||||
j=i-i0
|
||||
if(j.ge.0) c1(j)=c0(i)
|
||||
if(j.lt.0) c1(j+NZ)=c0(i)
|
||||
enddo
|
||||
call four2a(c1,NZ,1,1,1) !Reverse c2c FFT: back to time domain
|
||||
|
||||
c1sum(0)=c1(0)
|
||||
do i=1,NZ-1
|
||||
c1sum(i)=c1sum(i-1) + c1(i)
|
||||
enddo
|
||||
|
||||
nspsd=1024/NDOWN
|
||||
dt=NDOWN/12000.0
|
||||
lagmax=1.5/dt
|
||||
i0=nint(0.5*fsample/NDOWN) !Nominal start time is 0.5 s
|
||||
pmax=0.
|
||||
lagpk=0
|
||||
do lag=-lagmax,lagmax
|
||||
sp=0.
|
||||
do j=1,24
|
||||
i1=i0 + (isync(j)-1)*nspsd + lag
|
||||
i2=i1 + nspsd
|
||||
if(i1.lt.0 .or. i1.gt.NZ-1) cycle
|
||||
if(i2.lt.0 .or. i2.gt.NZ-1) cycle
|
||||
z=c1sum(i2)-c1sum(i1)
|
||||
sp=sp + real(z)**2 + aimag(z)**2
|
||||
enddo
|
||||
if(sp.gt.pmax) then
|
||||
pmax=sp
|
||||
lagpk=lag
|
||||
endif
|
||||
p(lag)=sp
|
||||
enddo
|
||||
|
||||
t2=lagpk*dt
|
||||
snrsync=0.
|
||||
sp=0.
|
||||
sq=0.
|
||||
nsum=0
|
||||
tsym=1024/12000.0
|
||||
do lag=-lagmax,lagmax
|
||||
t=(lag-lagpk)*dt
|
||||
if(abs(t).lt.tsym) cycle
|
||||
nsum=nsum+1
|
||||
sp=sp + p(lag)
|
||||
sq=sq + p(lag)*p(lag)
|
||||
enddo
|
||||
ave=sp/nsum
|
||||
rms=sqrt(sq/nsum-ave*ave)
|
||||
snrsync=(pmax-ave)/rms
|
||||
|
||||
return
|
||||
end subroutine qpc_sync
|
@ -1,28 +0,0 @@
|
||||
FUNCTION ran1(idum)
|
||||
INTEGER idum,IA,IM,IQ,IR,NTAB,NDIV
|
||||
REAL ran1,AM,EPS,RNMX
|
||||
PARAMETER (IA=16807,IM=2147483647,AM=1./IM,IQ=127773,IR=2836, &
|
||||
NTAB=32,NDIV=1+(IM-1)/NTAB,EPS=1.2e-7,RNMX=1.-EPS)
|
||||
INTEGER j,k,iv(NTAB),iy
|
||||
SAVE iv,iy
|
||||
DATA iv /NTAB*0/, iy /0/
|
||||
if (idum.le.0.or.iy.eq.0) then
|
||||
idum=max(-idum,1)
|
||||
do j=NTAB+8,1,-1
|
||||
k=idum/IQ
|
||||
idum=IA*(idum-k*IQ)-IR*k
|
||||
if (idum.lt.0) idum=idum+IM
|
||||
if (j.le.NTAB) iv(j)=idum
|
||||
enddo
|
||||
iy=iv(1)
|
||||
endif
|
||||
k=idum/IQ
|
||||
idum=IA*(idum-k*IQ)-IR*k
|
||||
if (idum.lt.0) idum=idum+IM
|
||||
j=1+iy/NDIV
|
||||
iy=iv(j)
|
||||
iv(j)=idum
|
||||
ran1=min(AM*iy,RNMX)
|
||||
|
||||
return
|
||||
END FUNCTION ran1
|
@ -1,17 +0,0 @@
|
||||
subroutine sfox_ana(dd,npts,c0,npts2)
|
||||
|
||||
real dd(npts) !Raw data at 12000 Hz
|
||||
complex c0(0:npts2-1) !Complex data at 12000 Hz
|
||||
save
|
||||
|
||||
nfft1=npts
|
||||
nfft2=nfft1
|
||||
fac=2.0/(32767.0*nfft1)
|
||||
c0(0:npts-1)=fac*dd(1:npts)
|
||||
call four2a(c0,nfft1,1,-1,1) !Forward c2c FFT
|
||||
c0(nfft2/2+1:nfft2-1)=0. !Remove negative frequencies
|
||||
c0(0)=0.5*c0(0) !Scale the DC term to 1/2
|
||||
call four2a(c0,nfft2,1,1,1) !Inverse c2c FFT; c0 is analytic sig
|
||||
|
||||
return
|
||||
end subroutine sfox_ana
|
@ -1,92 +0,0 @@
|
||||
subroutine sfox_assemble(ntype,k,msg,mycall0,mygrid0,line)
|
||||
|
||||
! In subsequent calls, assemble all necessary information for a SuperFox
|
||||
! transmission.
|
||||
|
||||
character*120 line
|
||||
character*26 msg
|
||||
character*26 msg0,msg1,msg2(5),msg3(5)
|
||||
character*4 rpt2(5)
|
||||
character*6 hiscall(10)
|
||||
character*13 mycall0,mycall
|
||||
character*4 mygrid0,mygrid
|
||||
integer ntype !Message type: 0 Free Text
|
||||
! 1 CQ MyCall MyGrid
|
||||
! 2 Call_1 MyCall RR73
|
||||
! 3 Call_1 MyCall rpt
|
||||
integer nmsg(0:3) !Number of messages of type ntype
|
||||
data nmsg/0,0,0,0/,nbits/0/,ntx/0/,nb_mycall/0/
|
||||
save
|
||||
|
||||
if(mycall0(1:1).ne.' ') mycall=mycall0
|
||||
if(mygrid0(1:1).ne.' ') mygrid=mygrid0
|
||||
if(ntype.ge.1) nb_mycall=28 !### Allow for nonstandard MyCall ###
|
||||
if(sum(nmsg).eq.0) then
|
||||
hiscall=' '
|
||||
rpt2=' '
|
||||
endif
|
||||
|
||||
if(k.le.10) then
|
||||
if(ntype.eq.0) then
|
||||
if(nbits+nb_mycall.le.191) then !Enough room for a free text message?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+142
|
||||
msg0=msg
|
||||
endif
|
||||
else if(ntype.eq.1) then
|
||||
if(nbits+nb_mycall.le.318) then !Enough room for a CQ ?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+15
|
||||
msg1=msg
|
||||
endif
|
||||
else if(ntype.eq.2) then
|
||||
if(nbits+nb_mycall.le.305) then !Enough room for a RR73 message?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+28
|
||||
j=nmsg(ntype)
|
||||
msg2(j)=msg
|
||||
i1=index(msg,' ')
|
||||
hiscall(j+5)=msg(1:i1-1)
|
||||
endif
|
||||
else if(ntype.eq.3) then
|
||||
if(nbits+nb_mycall.le.300) then !Enough room for a message with report?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+33
|
||||
j=nmsg(ntype)
|
||||
msg3(j)=msg
|
||||
i1=index(msg,' ')
|
||||
hiscall(j)=msg(1:i1-1)
|
||||
i1=max(index(msg,'-'),index(msg,'+'))
|
||||
rpt2(j)=msg(i1:i1+3)
|
||||
endif
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
if(k.ge.11) then
|
||||
! All pieces are now available. Put them into a command line for external
|
||||
! program sfox_tx.
|
||||
ntx=ntx+1 !Transmission number
|
||||
nbits=nbits+nb_mycall !Add bits for MyCall
|
||||
|
||||
if(nmsg(1).ge.1) then
|
||||
line=msg1
|
||||
else
|
||||
line=trim(mycall)
|
||||
do i=1,nmsg(3)
|
||||
line=trim(line)//' '//trim(hiscall(i))//' '//rpt2(i)
|
||||
enddo
|
||||
do i=1,nmsg(2)
|
||||
line=trim(line)//' '//trim(hiscall(i+5))
|
||||
enddo
|
||||
endif
|
||||
|
||||
nmsg=0
|
||||
nbits=0
|
||||
nb_mycall=0
|
||||
hiscall=' '
|
||||
rpt2=' '
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine sfox_assemble
|
@ -1,79 +0,0 @@
|
||||
subroutine sfox_demod(crcvd,f,t,isync,s2,s3)
|
||||
|
||||
use sfox_mod
|
||||
complex crcvd(NMAX) !Signal as received
|
||||
complex c(0:NSPS-1) !Work array, one symbol long
|
||||
real s2(0:NQ-1,0:151) !Symbol spectra, including sync
|
||||
real s3(0:NQ-1,0:NN) !Synchronized symbol spectra
|
||||
integer isync(24)
|
||||
integer ipk(1)
|
||||
integer hist1(0:NQ-1),hist2(0:NQ-1)
|
||||
|
||||
j0=nint(12000.0*(t+0.5))
|
||||
df=12000.0/NSPS
|
||||
i0=nint(f/df)-NQ/2
|
||||
k2=0
|
||||
s2(:,0)=0. !The punctured symbol
|
||||
s3(:,0)=0. !The punctured symbol
|
||||
|
||||
do n=1,NDS !Loop over all symbols
|
||||
jb=n*NSPS + j0
|
||||
ja=jb-NSPS+1
|
||||
k2=k2+1
|
||||
if(ja.lt.1 .or. jb.gt.NMAX) cycle
|
||||
c=crcvd(ja:jb)
|
||||
call four2a(c,NSPS,1,-1,1) !Compute symbol spectrum
|
||||
do i=0,NQ-1
|
||||
s2(i,k2)=real(c(i0+i))**2 + aimag(c(i0+i))**2
|
||||
enddo
|
||||
enddo
|
||||
|
||||
|
||||
call pctile(s2,NQ*151,50,base2)
|
||||
s2=s2/base2
|
||||
|
||||
hist1=0
|
||||
hist2=0
|
||||
do j=0,151
|
||||
ipk=maxloc(s2(1:NQ-1,j)) !Find the spectral peak
|
||||
i=ipk(1)-1
|
||||
hist1(i)=hist1(i)+1
|
||||
enddo
|
||||
|
||||
hist1(0)=0 !Don't treat sync tone as a birdie
|
||||
do i=0,123
|
||||
hist2(i)=sum(hist1(i:i+3))
|
||||
enddo
|
||||
|
||||
ipk=maxloc(hist1)
|
||||
i1=ipk(1)-1
|
||||
m1=maxval(hist1)
|
||||
ipk=maxloc(hist2)
|
||||
i2=ipk(1)-1
|
||||
m2=maxval(hist2)
|
||||
if(m1.gt.12) then
|
||||
do i=0,127
|
||||
if(hist1(i).gt.12) then
|
||||
s2(i,:)=1.0
|
||||
endif
|
||||
enddo
|
||||
endif
|
||||
|
||||
if(m2.gt.20) then
|
||||
if(i2.ge.1) i2=i2-1
|
||||
if(i2.gt.120) i2=120
|
||||
s2(i2:i2+7,:)=1.0
|
||||
endif
|
||||
|
||||
k3=0
|
||||
do n=1,NDS !Copy symbol spectra from s2 into s3
|
||||
if(any(isync(1:NS).eq.n)) cycle !Skip the sync symbols
|
||||
k3=k3+1
|
||||
s3(:,k3)=s2(:,n)
|
||||
enddo
|
||||
|
||||
call pctile(s3,NQ*NN,50,base3)
|
||||
s3=s3/base3
|
||||
|
||||
return
|
||||
end subroutine sfox_demod
|
@ -1,86 +0,0 @@
|
||||
subroutine sfox_gen_gfsk(idat,f0,isync,itone,cdat)
|
||||
|
||||
parameter (NSPS=1024)
|
||||
parameter (NDS=151)
|
||||
parameter (NN=127) !NN = number of code symbols
|
||||
parameter (NS=24) !NS = number of sync symbols
|
||||
parameter (NMAX=15*12000)
|
||||
parameter (NPTS=(NDS+2)*NSPS) !# of samples in waveform at 12000 samples/sec
|
||||
parameter (BT=8) !GFSK time-bandwidth product
|
||||
|
||||
complex cdat(NMAX)
|
||||
complex w, wstep
|
||||
integer idat(NN)
|
||||
integer isync(NS)
|
||||
integer itone(NDS)
|
||||
real*8 dt,twopi,phi,dphi_peak
|
||||
real*8 dphi(0:NPTS-1)
|
||||
real pulse(3*NSPS)
|
||||
logical first/.true./
|
||||
|
||||
save first,twopi,dt,hmod,dphi_peak,pulse
|
||||
|
||||
if(first) then
|
||||
twopi=8.d0*atan(1.0)
|
||||
fsample=12000.0
|
||||
dt=1.0/fsample
|
||||
hmod=1.0
|
||||
dphi_peak=twopi*hmod/real(NSPS)
|
||||
do i=1,3*NSPS
|
||||
tt=(i-1.5*NSPS)/real(NSPS)
|
||||
pulse(i)=gfsk_pulse(BT,tt)
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
wave=0.
|
||||
|
||||
! Create the itone sequence: data symbols and interspersed sync symbols
|
||||
j=1
|
||||
k=0
|
||||
do i=1,NDS
|
||||
if(j.le.NS .and. i.eq.isync(j)) then
|
||||
if(j.lt.NS) j=j+1 !Index for next sync symbol
|
||||
itone(i)=0 !Insert sync symbol at tone 0
|
||||
else
|
||||
k=k+1
|
||||
itone(i)=idat(k) + 1 !Symbol value 0 is transmitted at tone 1, etc.
|
||||
endif
|
||||
enddo
|
||||
|
||||
! Generate the SuperFox waveform.
|
||||
|
||||
dphi=0.d0
|
||||
do j=1,NDS
|
||||
ib=(j-1)*NSPS
|
||||
ie=ib+3*NSPS-1
|
||||
dphi(ib:ie)=dphi(ib:ie)+dphi_peak*pulse(1:3*NSPS)*itone(j)
|
||||
enddo
|
||||
dphi(0:2*NSPS-1)=dphi(0:2*NSPS-1)+dphi_peak*itone(1)*pulse(NSPS+1:3*NSPS)
|
||||
dphi(NDS*NSPS:(NDS+2)*NSPS-1)=dphi(NDS*NSPS:(NDS+2)*NSPS-1)+dphi_peak*itone(NDS)*pulse(1:2*NSPS)
|
||||
|
||||
phi=0.d0
|
||||
dphi=dphi+twopi*f0*dt
|
||||
k=0
|
||||
do j=1,NSPS*(NDS+2)-1
|
||||
k=k+1
|
||||
cdat(k)=cmplx(cos(phi),sin(phi))
|
||||
phi=phi+dphi(j)
|
||||
enddo
|
||||
|
||||
! Add raised cosine ramps at the beginning and end of the waveform.
|
||||
! Since the modulator expects an integral number of symbols, dummy
|
||||
! symbols are added to the beginning and end of the waveform to
|
||||
! hold the ramps. All but nramp of the samples in each dummy
|
||||
! symbol will be zero.
|
||||
|
||||
nramp=NSPS/BT
|
||||
cdat(1:NSPS-nramp)=cmplx(0.0,0.0)
|
||||
cdat(NSPS-nramp+1:NSPS)=cdat(NSPS-nramp+1:NSPS) * &
|
||||
(1.0-cos(twopi*(/(i,i=0,nramp-1)/)/(2.0*nramp)))/2.0
|
||||
k1=(NDS+1)*NSPS+1
|
||||
cdat(k1:k1+nramp-1)=cdat(k1:k1+nramp-1) * &
|
||||
(1.0+cos(twopi*(/(i,i=0,nramp-1)/)/(2.0*nramp)))/2.0
|
||||
cdat(k1+nramp:NPTS)=0.0
|
||||
|
||||
return
|
||||
end subroutine sfox_gen_gfsk
|
@ -1,73 +0,0 @@
|
||||
module sfox_mod
|
||||
|
||||
parameter (NMAX=15*12000) !Samples in iwave (180,000)
|
||||
integer MM,NQ,NN,KK,NS,NDS,NFZ,NSPS,NSYNC,NZ,NFFT1
|
||||
real baud,tsym,bw
|
||||
|
||||
contains
|
||||
subroutine sfox_init(mm0,nn0,kk0,itu,fspread,delay,fsample,ns0)
|
||||
|
||||
character*2 itu
|
||||
integer isps(54)
|
||||
integer iloc(1)
|
||||
data isps/ 896, 960, 972, 980,1000,1008,1024,1029,1050,1080, &
|
||||
1120,1125,1134,1152,1176,1200,1215,1225,1250,1260, &
|
||||
1280,1296,1323,1344,1350,1372,1400,1440,1458,1470, &
|
||||
1500,1512,1536,1568,1575,1600,1620,1680,1701,1715, &
|
||||
1728,1750,1764,1792,1800,1875,1890,1920,1944,1960, &
|
||||
2000,2016,2025,2048/
|
||||
|
||||
MM=mm0 !Bits per symbol
|
||||
NQ=2**MM !Q, number of MFSK tones
|
||||
NN=nn0 !Codeword length
|
||||
KK=kk0 !Number of information symbols
|
||||
NS=ns0 !Number of sync symbols
|
||||
NDS=NN+NS !Total number of channel symbols
|
||||
NFZ=3 !First zero
|
||||
|
||||
jsps=nint(12.8*fsample/NDS)
|
||||
iloc=minloc(abs(isps-jsps))
|
||||
NSPS=isps(iloc(1)) !Samples per symbol
|
||||
NSYNC=NS*NSPS !Samples in sync waveform
|
||||
NZ=NSPS*NDS !Samples in full Tx waveform
|
||||
NFFT1=2*NSPS !Length of FFTs for symbol spectra
|
||||
|
||||
baud=fsample/NSPS
|
||||
tsym=1.0/baud
|
||||
bw=NQ*baud
|
||||
|
||||
fspread=0.0
|
||||
delay=0.0
|
||||
if(itu.eq.'LQ') then
|
||||
fspread=0.5
|
||||
delay=0.5
|
||||
else if(itu.eq.'LM') then
|
||||
fspread=1.5
|
||||
delay=2.0
|
||||
else if(itu.eq.'LD') then
|
||||
fspread=10.0
|
||||
delay=6.0
|
||||
else if(itu.eq.'MQ') then
|
||||
fspread=0.1
|
||||
delay=0.5
|
||||
else if(itu.eq.'MM') then
|
||||
fspread=0.5
|
||||
delay=1.0
|
||||
else if(itu.eq.'MD') then
|
||||
fspread=1.0
|
||||
delay=2.0
|
||||
else if(itu.eq.'HQ') then
|
||||
fspread=0.5
|
||||
delay=1.0
|
||||
else if(itu.eq.'HM') then
|
||||
fspread=10.0
|
||||
delay=3.0
|
||||
else if(itu.eq.'HD') then
|
||||
fspread=30.0
|
||||
delay=7.0
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine sfox_init
|
||||
|
||||
end module sfox_mod
|
@ -1,178 +0,0 @@
|
||||
subroutine sfox_pack(line,ckey,bMoreCQs,bSendMsg,freeTextMsg,xin)
|
||||
|
||||
use qpc_mod
|
||||
use packjt
|
||||
use packjt77
|
||||
use julian
|
||||
parameter (NQU1RKS=203514677)
|
||||
integer*8 n47,n58,now
|
||||
integer*1 xin(0:49) !Packed message as 7-bit symbols
|
||||
logical*1 bMoreCQs,bSendMsg
|
||||
logical text,allz
|
||||
character*120 line !SuperFox message pieces
|
||||
character*10 ckey
|
||||
character*26 freeTextMsg
|
||||
character*13 w(16)
|
||||
character*11 c11
|
||||
character*329 msgbits !Packed message as bits
|
||||
character*38 c
|
||||
data c/' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/'/
|
||||
|
||||
i0=index(line,'/')
|
||||
i3=0 !Default to i3=0, standard message
|
||||
nh1=0 !Number of Hound calls with RR73
|
||||
nh2=0 !Number of Hound calls with report
|
||||
|
||||
! Split the command line into words
|
||||
w=' '
|
||||
i1=1
|
||||
do j=1,16
|
||||
do i=i1,min(i1+12,120)
|
||||
if(line(i:i).eq.' ') exit
|
||||
enddo
|
||||
i2=i-1
|
||||
w(j)=line(i1:i2)
|
||||
do i=i2+1,120
|
||||
if(line(i:i).ne.' ') exit
|
||||
enddo
|
||||
i1=i
|
||||
if(i1.ge.120) exit
|
||||
enddo
|
||||
nwords=j
|
||||
|
||||
do i=1,nwords
|
||||
if(w(i)(1:1).eq.' ') then
|
||||
nwords=i-1
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
|
||||
do i=1,329 !Set all msgbits to '0'
|
||||
msgbits(i:i)='0'
|
||||
enddo
|
||||
|
||||
now=itime8()/30
|
||||
now=30*now
|
||||
read(ckey(5:10),*) notp
|
||||
|
||||
write(msgbits(307:326),'(b20.20)') notp !Insert the digital signature
|
||||
|
||||
if(w(1)(1:3).eq.'CQ ') then
|
||||
i3=3
|
||||
c11=w(2)(1:11)
|
||||
n58=0
|
||||
do i=1,11
|
||||
n58=n58*38 + index(c,c11(i:i)) - 1
|
||||
enddo
|
||||
write(msgbits(1:58),'(b58.58)') n58
|
||||
call packgrid(w(3)(1:4),n15,text)
|
||||
write(msgbits(59:73),'(b15.15)') n15
|
||||
write(msgbits(327:329),'(b3.3)') i3 !Message type i3=3
|
||||
go to 800
|
||||
endif
|
||||
|
||||
call pack28(w(1),n28) !Fox call
|
||||
write(msgbits(1:28),'(b28.28)') n28
|
||||
|
||||
! Default report is RR73 if we're also sending a free text message.
|
||||
if(bSendMsg) msgbits(141:160)='11111111111111111111'
|
||||
|
||||
j=29
|
||||
|
||||
! Process callsigns with RR73
|
||||
do i=2,nwords
|
||||
if(w(i)(1:1).eq.'+' .or. w(i)(1:1).eq.'-') cycle !Skip report words
|
||||
i1=min(i+1,nwords)
|
||||
if(w(i1)(1:1) .eq.'+' .or. w(i1)(1:1).eq.'-') cycle !Skip if i+1 is report
|
||||
call pack28(w(i),n28)
|
||||
write(msgbits(j:j+27),1002) n28 !Insert this call for RR73 message
|
||||
1002 format(b28.28)
|
||||
j=j+28
|
||||
nh1=nh1+1
|
||||
if(nh1.ge.5) exit !At most 5 RR73 callsigns
|
||||
enddo
|
||||
|
||||
! Process callsigns with a report
|
||||
j=169
|
||||
j2=281
|
||||
if(bSendMsg) then
|
||||
i3=2
|
||||
j=29 + 28*nh1
|
||||
j2=141 + 5*nh1
|
||||
endif
|
||||
|
||||
do i=2,nwords
|
||||
i1=min(i+1,nwords)
|
||||
if(w(i1)(1:1).eq.'+' .or. w(i1)(1:1).eq.'-') then
|
||||
call pack28(w(i),n28)
|
||||
write(msgbits(j:j+27),1002) n28 !Insert this call
|
||||
read(w(i1),*) n !Valid reports are -18 to +12, plus RR73
|
||||
if(n.lt.-18) n=-18 !... Even numbers only ...
|
||||
if(n.gt.12) n=12
|
||||
write(msgbits(j2:j2+4),1000) n+18
|
||||
1000 format(b5.5)
|
||||
w(i1)=""
|
||||
nh2=nh2+1
|
||||
! print*,'C',i3,i,j,n,w(i)
|
||||
if( nh2.ge.4 .or. (nh1+nh2).ge.9 ) exit ! At most 4 callsigns w/reports
|
||||
j=j+28
|
||||
j2=j2+5
|
||||
endif
|
||||
enddo
|
||||
|
||||
800 if(bSendMsg) then
|
||||
i1=26
|
||||
do i=1,26
|
||||
if(freeTextMsg(i:i).ne.' ') i1=i
|
||||
enddo
|
||||
do i=i1+1,26
|
||||
freeTextMsg(i:i)='.'
|
||||
enddo
|
||||
if(i3.eq.3) then
|
||||
call packtext77(freeTextMsg(1:13),msgbits(74:144))
|
||||
call packtext77(freeTextMsg(14:26),msgbits(145:215))
|
||||
elseif(i3.eq.2) then
|
||||
call packtext77(freeTextMsg(1:13),msgbits(161:231))
|
||||
call packtext77(freeTextMsg(14:26),msgbits(232:302))
|
||||
endif
|
||||
write(msgbits(327:329),'(b3.3)') i3 !Message type i3=2
|
||||
endif
|
||||
if(bMoreCQs) msgbits(306:306)='1'
|
||||
|
||||
read(msgbits(327:329),'(b3)') i3
|
||||
if(i3.eq.0) then
|
||||
do i=1,9
|
||||
i0=i*28 + 1
|
||||
read(msgbits(i0:i0+27),'(b28)') n28
|
||||
if(n28.eq.0) write(msgbits(i0:i0+27),'(b28.28)') NQU1RKS
|
||||
enddo
|
||||
else if(i3.eq.3) then
|
||||
allz=.true.
|
||||
do i=0,6
|
||||
i0=i*32 + 74
|
||||
read(msgbits(i0:i0+31),'(b32)') n32
|
||||
if(n32.ne.0) allz=.false.
|
||||
enddo
|
||||
if(allz) then
|
||||
do i=0,6
|
||||
i0=i*32 + 74
|
||||
write(msgbits(i0:i0+31),'(b32.32)') NQU1RKS
|
||||
enddo
|
||||
endif
|
||||
endif
|
||||
|
||||
read(msgbits,1004) xin(0:46)
|
||||
1004 format(47b7)
|
||||
|
||||
mask21=2**21 - 1
|
||||
n47=47
|
||||
ncrc21=iand(nhash2(xin,n47,571),mask21) !Compute 21-bit CRC
|
||||
xin(47)=ncrc21/16384 !First 7 of 21 bits
|
||||
xin(48)=iand(ncrc21/128,127) !Next 7 bits
|
||||
xin(49)=iand(ncrc21,127) !Last 7 bits
|
||||
|
||||
xin=xin(49:0:-1) !Reverse the symbol order
|
||||
! NB: CRC is now in first three symbols, fox call in the last four.
|
||||
|
||||
return
|
||||
end subroutine sfox_pack
|
@ -1,55 +0,0 @@
|
||||
subroutine sfox_prob(s3,rxdat,rxprob,rxdat2,rxprob2)
|
||||
|
||||
! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
|
||||
|
||||
! Parameters
|
||||
! rxdat most reliable symbol value
|
||||
! rxdat2 second most likely symbol value
|
||||
! rxprob probability that rxdat was the transmitted value
|
||||
! rxprob2 probability that rxdat2 was the transmitted value
|
||||
|
||||
use sfox_mod
|
||||
implicit real*8 (a-h,o-z)
|
||||
real*4 s3(0:NQ-1,0:NN-1)
|
||||
integer rxdat(0:NN-1),rxprob(0:NN-1),rxdat2(0:NN-1),rxprob2(0:NN-1)
|
||||
|
||||
afac=1.1
|
||||
! scale=255.999
|
||||
scale=2047.999
|
||||
|
||||
! Compute average spectral value
|
||||
ave=sum(s3)/(NQ*ND)
|
||||
i1=1 !Silence warning
|
||||
i2=1
|
||||
|
||||
! Compute probabilities for most reliable symbol values
|
||||
do j=0,NN-1 !Loop over all symbols
|
||||
s1=-1.e30
|
||||
psum=0.
|
||||
do i=0,NQ-1 !Loop over frequency bins
|
||||
x=min(afac*s3(i,j)/ave,50.d0)
|
||||
psum=psum+s3(i,j)
|
||||
if(s3(i,j).gt.s1) then
|
||||
s1=s3(i,j) !Find max signal+noise power
|
||||
i1=i !Find most reliable symbol value
|
||||
endif
|
||||
enddo
|
||||
if(psum.eq.0.0) psum=1.e-6 !Guard against zero signal+noise
|
||||
|
||||
s2=-1.e30
|
||||
do i=0,NQ-1
|
||||
if(i.ne.i1 .and. s3(i,j).gt.s2) then
|
||||
s2=s3(i,j) !Second largest signal+noise power
|
||||
i2=i !Bin number for second largest power
|
||||
endif
|
||||
enddo
|
||||
p1=s1/psum !p1, p2 are symbol metrics for ftrsd
|
||||
p2=s2/psum
|
||||
rxdat(j)=i1
|
||||
rxdat2(j)=i2
|
||||
rxprob(j)=scale*p1 !Scaled probabilities, 0 - 255
|
||||
rxprob2(j)=scale*p2
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine sfox_prob
|
@ -1,213 +0,0 @@
|
||||
subroutine sfox_remove_ft8(dd,npts)
|
||||
use packjt77
|
||||
include 'ft8_params.f90'
|
||||
parameter (MAXCAND=100)
|
||||
parameter (NP2=2812)
|
||||
integer itone(NN)
|
||||
integer iloc(1), ip(1)
|
||||
integer icos7(0:6)
|
||||
integer graymap(0:7)
|
||||
integer*1 cw(174),apmask(174)
|
||||
integer*1 message91(91)
|
||||
integer*1 message77(77)
|
||||
|
||||
character*77 c77
|
||||
character*37 msg37
|
||||
|
||||
real s8(0:7,NN)
|
||||
real s2(0:7)
|
||||
real ss(9)
|
||||
real candidate(3,MAXCAND)
|
||||
real sbase(NH1)
|
||||
real dd(npts)
|
||||
real bmeta(174),bmetd(174)
|
||||
real llra(174),llrd(174)
|
||||
complex cd0(0:3199)
|
||||
complex csymb(32)
|
||||
complex ctwk(32)
|
||||
complex cs(0:7,NN)
|
||||
data icos7/3,1,4,0,6,5,2/
|
||||
logical first,newdat
|
||||
logical one(0:7,0:2)
|
||||
logical unpk77_success
|
||||
data first/.true./
|
||||
data graymap/0,1,3,2,5,6,4,7/
|
||||
save one,first,twopi
|
||||
|
||||
if(first) then
|
||||
one=.false.
|
||||
do i=0,7
|
||||
do j=0,2
|
||||
if(iand(i,2**j).ne.0) one(i,j)=.true.
|
||||
enddo
|
||||
enddo
|
||||
first=.false.
|
||||
twopi=8.0*atan(1.0)
|
||||
endif
|
||||
|
||||
fs2=12000.0/NDOWN
|
||||
dt2=1.0/fs2
|
||||
nfa=500
|
||||
nfb=2500
|
||||
syncmin=1.5
|
||||
nfqso=750
|
||||
call sync8(dd,npts,nfa,nfb,syncmin,nfqso,MAXCAND,candidate,ncand,sbase)
|
||||
newdat=.true.
|
||||
do icand=1,ncand
|
||||
f1=candidate(1,icand)
|
||||
xdt=candidate(2,icand)
|
||||
xbase=10.0**(0.1*(sbase(nint(f1/3.125))-40.0))
|
||||
call ft8_downsample(dd,newdat,f1,cd0)
|
||||
newdat=.false.
|
||||
i0=nint((xdt+0.5)*fs2)
|
||||
smax=0.0
|
||||
do idt=i0-10,i0+10
|
||||
call sync8d(cd0,idt,ctwk,0,sync)
|
||||
if(sync.gt.smax) then
|
||||
smax=sync
|
||||
ibest=idt
|
||||
endif
|
||||
enddo
|
||||
|
||||
smax=0.0
|
||||
delfbest=0.0
|
||||
do ifr=-5,5 !Search over +/- 2.5 Hz
|
||||
delf=ifr*0.5
|
||||
dphi=twopi*delf*dt2
|
||||
phi=0.0
|
||||
do i=1,32
|
||||
ctwk(i)=cmplx(cos(phi),sin(phi))
|
||||
phi=mod(phi+dphi,twopi)
|
||||
enddo
|
||||
call sync8d(cd0,ibest,ctwk,1,sync)
|
||||
if( sync .gt. smax ) then
|
||||
smax=sync
|
||||
delfbest=delf
|
||||
endif
|
||||
enddo
|
||||
|
||||
f1=f1+delfbest !Improved estimate of DF
|
||||
|
||||
call ft8_downsample(dd,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||
|
||||
smax=0.0
|
||||
do idt=-4,4 !Search over +/- one quarter symbol
|
||||
call sync8d(cd0,ibest+idt,ctwk,0,sync)
|
||||
ss(idt+5)=sync
|
||||
enddo
|
||||
smax=maxval(ss)
|
||||
iloc=maxloc(ss)
|
||||
ibest=iloc(1)-5+ibest
|
||||
xdt=(ibest-1)*dt2
|
||||
sync=smax
|
||||
|
||||
do k=1,NN
|
||||
i1=ibest+(k-1)*32
|
||||
csymb=cmplx(0.0,0.0)
|
||||
if( i1.ge.0 .and. i1+31 .le. NP2-1 ) csymb=cd0(i1:i1+31)
|
||||
call four2a(csymb,32,1,-1,1)
|
||||
cs(0:7,k)=csymb(1:8)/1e3
|
||||
s8(0:7,k)=abs(csymb(1:8))
|
||||
enddo
|
||||
|
||||
! sync quality check
|
||||
is1=0
|
||||
is2=0
|
||||
is3=0
|
||||
do k=1,7
|
||||
ip=maxloc(s8(:,k))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||
ip=maxloc(s8(:,k+36))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||
ip=maxloc(s8(:,k+72))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||
enddo
|
||||
! hard sync sum - max is 21
|
||||
nsync=is1+is2+is3
|
||||
if(nsync .le. 6) then ! bail out
|
||||
nbadcrc=1
|
||||
cycle
|
||||
endif
|
||||
|
||||
nsym=1
|
||||
nt=2**(3*nsym)
|
||||
do ihalf=1,2
|
||||
do k=1,29,nsym
|
||||
if(ihalf.eq.1) ks=k+7
|
||||
if(ihalf.eq.2) ks=k+43
|
||||
amax=-1.0
|
||||
do i=0,nt-1
|
||||
i3=iand(i,7)
|
||||
s2(i)=abs(cs(graymap(i3),ks))
|
||||
enddo
|
||||
i32=1+(k-1)*3+(ihalf-1)*87
|
||||
ibmax=2
|
||||
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
|
||||
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
|
||||
enddo
|
||||
enddo
|
||||
enddo
|
||||
|
||||
call normalizebmet(bmeta,174)
|
||||
call normalizebmet(bmetd,174)
|
||||
|
||||
scalefac=2.83
|
||||
llra=scalefac*bmeta
|
||||
llrd=scalefac*bmetd
|
||||
|
||||
cw=0
|
||||
dmin=0
|
||||
norder=2
|
||||
maxosd=-1
|
||||
Keff=91
|
||||
apmask=0
|
||||
message91=0
|
||||
cw=0
|
||||
call decode174_91(llra,Keff,maxosd,norder,apmask,message91,cw, &
|
||||
ntype,nharderrors,dmin)
|
||||
|
||||
if(nharderrors.ge.0) then
|
||||
message77=message91(1:77)
|
||||
else
|
||||
cycle
|
||||
endif
|
||||
|
||||
if(count(cw.eq.0).eq.174) cycle
|
||||
|
||||
write(c77,'(77i1)') message77
|
||||
read(c77(72:74),'(b3)') n3
|
||||
read(c77(75:77),'(b3)') i3
|
||||
if(i3.gt.5 .or. (i3.eq.0.and.n3.gt.6)) cycle
|
||||
if(i3.eq.0 .and. n3.eq.2) cycle
|
||||
|
||||
call unpack77(c77,1,msg37,unpk77_success)
|
||||
! write(77,*) 'FT8 interference: ',msg37
|
||||
if(.not.unpk77_success) cycle
|
||||
! Message structure: S7 D29 S7 D29 S7
|
||||
itone(1:7)=icos7
|
||||
itone(36+1:36+7)=icos7
|
||||
itone(NN-6:NN)=icos7
|
||||
k=7
|
||||
do j=1,ND
|
||||
i=3*j -2
|
||||
k=k+1
|
||||
if(j.eq.30) k=k+7
|
||||
indx=cw(i)*4 + cw(i+1)*2 + cw(i+2)
|
||||
itone(k)=graymap(indx)
|
||||
enddo
|
||||
call subtractft8(dd,itone,f1,xdt,.true.)
|
||||
! return
|
||||
enddo
|
||||
return
|
||||
end subroutine sfox_remove_ft8
|
@ -1,95 +0,0 @@
|
||||
subroutine sfox_remove_tone(c0,fsync)
|
||||
|
||||
parameter (NMAX=15*12000)
|
||||
parameter (NFILT=8000)
|
||||
complex c0(NMAX)
|
||||
complex cwindow(15*12000)
|
||||
complex cref(NMAX)
|
||||
complex cfilt(NMAX)
|
||||
real window(-NFILT/2:NFILT/2)
|
||||
! real endcorrection(NFILT/2+1)
|
||||
real s(NMAX/4)
|
||||
integer ipk(1)
|
||||
logical first
|
||||
data first/.true./
|
||||
save cwindow,first,pi
|
||||
|
||||
if(first) then
|
||||
pi=4.0*atan(1.0)
|
||||
fac=1.0/float(NMAX)
|
||||
sumw=0.0
|
||||
do j=-NFILT/2,NFILT/2
|
||||
window(j)=cos(pi*j/NFILT)**2
|
||||
sumw=sumw+window(j)
|
||||
enddo
|
||||
cwindow=0.
|
||||
cwindow(1:NFILT+1)=window/sumw
|
||||
cwindow=cshift(cwindow,NFILT/2+1)
|
||||
call four2a(cwindow,NMAX,1,-1,1)
|
||||
cwindow=cwindow*fac ! frequency domain smoothing filter
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
fsample=12000.0
|
||||
baud=fsample/1024.0
|
||||
df=fsample/NMAX
|
||||
fac=1.0/NMAX
|
||||
|
||||
do it=1,1 ! Remove 1 tone, if present
|
||||
cfilt=fac*c0
|
||||
call four2a(cfilt,NMAX,1,-1,1) ! fourier transform of input data
|
||||
iz=NMAX/4
|
||||
do i=1,iz
|
||||
s(i)=real(cfilt(i))**2 + aimag(cfilt(i))**2
|
||||
enddo
|
||||
|
||||
ia=nint((fsync-50.0)/df)
|
||||
ib=nint((fsync+1500.0+50.0)/df)
|
||||
ipk=maxloc(s(ia:ib))
|
||||
i0=ipk(1) + ia - 1
|
||||
|
||||
nbaud=nint(baud/df)
|
||||
ia=i0-nbaud
|
||||
ib=i0+nbaud
|
||||
s0=0.0
|
||||
s1=0.0
|
||||
s2=0.0
|
||||
do i=ia,ib
|
||||
s0=s0+s(i)
|
||||
s1=s1+(i-i0)*s(i)
|
||||
enddo
|
||||
delta=s1/s0
|
||||
i0=nint(i0+delta)
|
||||
f2=i0*df
|
||||
|
||||
ia=i0-nbaud
|
||||
ib=i0+nbaud
|
||||
do i=ia,ib
|
||||
s2=s2 + s(i)*(i-i0)**2
|
||||
enddo
|
||||
sigma=sqrt(s2/s0)*df
|
||||
|
||||
! write(*,*) 'frequency, spectral width ',f2,sigma
|
||||
if(sigma .gt. 2.5) exit
|
||||
! write(*,*) 'remove_tone - frequency: ',f2
|
||||
|
||||
dt=1.0/fsample
|
||||
do i=1, NMAX
|
||||
arg=2*pi*f2*i*dt
|
||||
cref(i)=cmplx(cos(arg),sin(arg))
|
||||
enddo
|
||||
cfilt=c0*conjg(cref) ! baseband to be filtered
|
||||
call four2a(cfilt,NMAX,1,-1,1)
|
||||
cfilt=cfilt*cwindow
|
||||
call four2a(cfilt,NMAX,1,1,1)
|
||||
|
||||
nframe=50*3456
|
||||
do i=1,nframe
|
||||
cref(i)=cfilt(i)*cref(i)
|
||||
c0(i)=c0(i)-cref(i)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
return
|
||||
|
||||
end subroutine sfox_remove_tone
|
@ -1,119 +0,0 @@
|
||||
subroutine sfox_unpack(nutc,x,nsnr,f0,dt0,foxcall,notp)
|
||||
|
||||
use packjt77
|
||||
parameter (NQU1RKS=203514677)
|
||||
integer*1 x(0:49)
|
||||
integer*8 n58
|
||||
logical success
|
||||
character*336 msgbits
|
||||
character*22 msg(10) !### only msg(1) is used ??? ###
|
||||
character*13 foxcall,c13
|
||||
character*10 ssignature
|
||||
character*4 crpt(5),grid4
|
||||
character*26 freeTextMsg
|
||||
character*38 c
|
||||
logical use_otp
|
||||
data c/' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/'/
|
||||
|
||||
ncq=0
|
||||
if (notp.eq.0) then
|
||||
use_otp = .FALSE.
|
||||
else
|
||||
use_otp = .TRUE.
|
||||
endif
|
||||
write(msgbits,1000) x(0:46)
|
||||
1000 format(47b7.7)
|
||||
read(msgbits(327:329),'(b6)') i3 !Message type
|
||||
read(msgbits(1:28),'(b28)') n28 !Standard Fox call
|
||||
call unpack28(n28,foxcall,success)
|
||||
|
||||
if(i3.eq.1) then !Compound Fox callsign
|
||||
! read(msgbits(87:101),'(b15)') n15
|
||||
! call unpackgrid(n15,grid4)
|
||||
! msg(1)='CQ '//trim(foxcall)//' '//grid4
|
||||
! write(*,1100) nutc,nsnr,dt0,nint(f0),trim(msg(1))
|
||||
! go to 100
|
||||
else if(i3.eq.2) then !Up to 4 Hound calls and free text
|
||||
call unpacktext77(msgbits(161:231),freeTextMsg(1:13))
|
||||
call unpacktext77(msgbits(232:302),freeTextMsg(14:26))
|
||||
do i=26,1,-1
|
||||
if(freeTextMsg(i:i).ne.'.') exit
|
||||
freeTextMsg(i:i)=' '
|
||||
enddo
|
||||
write(*,1100) nutc,nsnr,dt0,nint(f0),freeTextMsg
|
||||
1100 format(i6.6,i4,f5.1,i5,1x,"~",2x,a)
|
||||
else if(i3.eq.3) then !CQ FoxCall Grid
|
||||
read(msgbits(1:58),'(b58)') n58 !FoxCall
|
||||
do i=11,1,-1
|
||||
j=mod(n58,38)+1
|
||||
foxcall(i:i)=c(j:j)
|
||||
n58=n58/38
|
||||
enddo
|
||||
foxcall(12:13)=' '
|
||||
read(msgbits(59:73),'(b15)') n15
|
||||
call unpackgrid(n15,grid4)
|
||||
msg(1)='CQ '//trim(foxcall)//' '//grid4
|
||||
write(*,1100) nutc,nsnr,dt0,nint(f0),trim(msg(1))
|
||||
read(msgbits(74:105),'(b32)') n32
|
||||
if(n32.eq.NQU1RKS) go to 100
|
||||
call unpacktext77(msgbits(74:144),freeTextMsg(1:13))
|
||||
call unpacktext77(msgbits(145:215),freeTextMsg(14:26))
|
||||
do i=26,1,-1
|
||||
if(freeTextMsg(i:i).ne.'.') exit
|
||||
freeTextMsg(i:i)=' '
|
||||
enddo
|
||||
if(len(trim(freeTextMsg)).gt.0) write(*,1100) nutc,nsnr,dt0,&
|
||||
nint(f0),freeTextMsg
|
||||
go to 100
|
||||
endif
|
||||
|
||||
j=281
|
||||
iz=4 !Max number of reports
|
||||
if(i3.eq.2) j=141
|
||||
do i=1,iz !Extract the reports
|
||||
read(msgbits(j:j+4),'(b5)') n
|
||||
if(n.eq.31) then
|
||||
crpt(i)='RR73'
|
||||
else
|
||||
write(crpt(i),1006) n-18
|
||||
1006 format(i3.2)
|
||||
if(crpt(i)(1:1).eq.' ') crpt(i)(1:1)='+'
|
||||
endif
|
||||
j=j+5
|
||||
enddo
|
||||
|
||||
! Unpack Hound callsigns and format user-level messages:
|
||||
iz=9 !Max number of hound calls
|
||||
if(i3.eq.2 .or. i3.eq.3) iz=4
|
||||
do i=1,iz
|
||||
j=28*i + 1
|
||||
read(msgbits(j:j+27),'(b28)') n28
|
||||
call unpack28(n28,c13,success)
|
||||
if(n28.eq.0 .or. n28.eq.NQU1RKS) cycle
|
||||
msg(i)=trim(c13)//' '//trim(foxcall)
|
||||
if(msg(i)(1:3).eq.'CQ ') then
|
||||
ncq=ncq+1
|
||||
else
|
||||
if(i3.eq.2) then
|
||||
msg(i)=trim(msg(i))//' '//crpt(i)
|
||||
else
|
||||
if(i.le.5) msg(i)=trim(msg(i))//' RR73'
|
||||
if(i.gt.5) msg(i)=trim(msg(i))//' '//crpt(i-5)
|
||||
endif
|
||||
endif
|
||||
if(ncq.le.1 .or. msg(i)(1:3).ne.'CQ ') then
|
||||
write(*,1100) nutc,nsnr,dt0,nint(f0),trim(msg(i))
|
||||
endif
|
||||
enddo
|
||||
|
||||
if(msgbits(306:306).eq.'1' .and. ncq.lt.1) then
|
||||
write(*,1100) nutc,nsnr,dt0,nint(f0),'CQ '//foxcall
|
||||
endif
|
||||
|
||||
100 read(msgbits(307:326),'(b20)') notp
|
||||
if (use_otp) then
|
||||
write(ssignature,'(I6.6)') notp
|
||||
write(*,1100) nutc,nsnr,dt0,nint(f0),'$VERIFY$ '//trim(foxcall)//' '//trim(ssignature)
|
||||
endif
|
||||
return
|
||||
end subroutine sfox_unpack
|
@ -1,40 +0,0 @@
|
||||
subroutine sfox_wave(fname)
|
||||
|
||||
! Called by WSJT-X when it's time for SuperFox to transmit. Reads array
|
||||
! itone(1:151) from disk file 'sfox_2.dat' in the writable data directory.
|
||||
|
||||
parameter (NWAVE=(160+2)*134400*4) !Max WSJT-X waveform (FST4-1800 at 48kHz)
|
||||
parameter (NN=151,NSPS=1024)
|
||||
character*(*) fname
|
||||
integer itone(151)
|
||||
real*8 dt,twopi,f0,baud,phi,dphi
|
||||
|
||||
common/foxcom/wave(NWAVE)
|
||||
|
||||
wave=0.
|
||||
open(25,file=trim(fname),status='unknown',err=999)
|
||||
read(25,'(20i4)',err=999,end=999) itone
|
||||
close(25)
|
||||
if(itone(1).lt.0 .or. itone(1).gt.128) go to 999
|
||||
|
||||
! Generate the SuperFox waveform.
|
||||
|
||||
dt=1.d0/48000.d0
|
||||
twopi=8.d0*atan(1.d0)
|
||||
f0=750.0d0
|
||||
phi=0.d0
|
||||
baud=12000.d0/NSPS
|
||||
k=0
|
||||
do j=1,NN
|
||||
f=f0 + baud*mod(itone(j),128)
|
||||
dphi=twopi*f*dt
|
||||
do ii=1,4*NSPS
|
||||
k=k+1
|
||||
phi=phi+dphi
|
||||
xphi=phi
|
||||
wave(k)=sin(xphi)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
999 return
|
||||
end subroutine sfox_wave
|
@ -1,77 +0,0 @@
|
||||
subroutine sfox_wave_gfsk()
|
||||
|
||||
! Called by WSJT-X when it's time for SuperFox to transmit. Reads array
|
||||
! itone(1:151) from disk file 'sfox_2.dat' in the writable data directory.
|
||||
! Generates a GFSK waveform with short ramp-up and ramp-down symbols of
|
||||
! duration NSPS/BT at the beginning and end of the waveform.
|
||||
|
||||
parameter (NWAVE=(160+2)*134400*4) !Max WSJT-X waveform (FST4-1800 at 48kHz)
|
||||
parameter (NSYM=151,NSPS=1024*4)
|
||||
parameter (NPTS=(NSYM+2)*NSPS)
|
||||
parameter (BT=8)
|
||||
character*40 cmsg2
|
||||
integer itone(151)
|
||||
real*8 dt,twopi,f0,phi,dphi_peak
|
||||
real*8 dphi(0:NPTS-1)
|
||||
real*8 pulse(3*NSPS)
|
||||
logical first/.true./
|
||||
|
||||
common/foxcom/wave(NWAVE)
|
||||
common/foxcom3/nslots2,cmsg2(5),itone3(151)
|
||||
save first,twopi,dt,hmod,dphi_peak,pulse
|
||||
|
||||
if(first) then
|
||||
fsample=48000.0
|
||||
twopi=8.d0*atan(1.d0)
|
||||
dt=1.d0/fsample
|
||||
hmod=1.0
|
||||
dphi_peak=twopi*hmod/real(NSPS)
|
||||
do i=1,3*NSPS
|
||||
tt=(i-1.5*NSPS)/real(NSPS)
|
||||
pulse(i)=gfsk_pulse(BT,tt)
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
wave=0.
|
||||
|
||||
itone=itone3
|
||||
if(itone(1).lt.0 .or. itone(1).gt.128) go to 999
|
||||
|
||||
! Generate the SuperFox waveform.
|
||||
|
||||
dphi=0.d0
|
||||
do j=1,NSYM
|
||||
ib=(j-1)*NSPS
|
||||
ie=ib+3*NSPS-1
|
||||
dphi(ib:ie)=dphi(ib:ie)+dphi_peak*pulse(1:3*NSPS)*itone(j)
|
||||
enddo
|
||||
dphi(0:2*NSPS-1)=dphi(0:2*NSPS-1)+dphi_peak*itone(1)*pulse(NSPS+1:3*NSPS)
|
||||
dphi(NSYM*NSPS:(NSYM+2)*NSPS-1)=dphi(NSYM*NSPS:(NSYM+2)*NSPS-1)+dphi_peak*itone(NSYM)*pulse(1:2*NSPS)
|
||||
|
||||
phi=0.d0
|
||||
f0=750.0d0
|
||||
dphi=dphi+twopi*f0*dt
|
||||
k=0
|
||||
do j=1,NSPS*(NSYM+2)-1
|
||||
k=k+1
|
||||
wave(k)=sin(phi)
|
||||
phi=phi+dphi(j)
|
||||
enddo
|
||||
|
||||
! Add raised cosine ramps at the beginning and end of the waveform.
|
||||
! Since the modulator expects an integral number of symbols, dummy
|
||||
! symbols are added to the beginning and end of the waveform to
|
||||
! hold the ramps. All but nramp of the samples in each dummy
|
||||
! symbol will be zero.
|
||||
|
||||
nramp=NSPS/BT
|
||||
wave(1:NSPS-nramp)=0.0
|
||||
wave(NSPS-nramp+1:NSPS)=wave(NSPS-nramp+1:NSPS) * &
|
||||
(1.0-cos(twopi*(/(i,i=0,nramp-1)/)/(2.0*nramp)))/2.0
|
||||
k1=(NSYM+1)*NSPS+1
|
||||
wave(k1:k1+nramp-1)=wave(k1:k1+nramp-1) * &
|
||||
(1.0+cos(twopi*(/(i,i=0,nramp-1)/)/(2.0*nramp)))/2.0
|
||||
wave(k1+nramp:NPTS)=0.0
|
||||
|
||||
999 return
|
||||
end subroutine sfox_wave_gfsk
|
@ -1,164 +0,0 @@
|
||||
program sfoxsim
|
||||
|
||||
! - Generate complex-valued SuperFox waveform, cdat.
|
||||
! - Pass cdat through Watterson channel simulator
|
||||
! - Add noise to the imaginary part of cdat and write to wav file.
|
||||
|
||||
use wavhdr
|
||||
use qpc_mod
|
||||
use sfox_mod
|
||||
|
||||
type(hdr) h !Header for .wav file
|
||||
logical*1 bMoreCQs !Include a CQ when space available?
|
||||
logical*1 bSendMsg !Send a Free text message
|
||||
integer*2 iwave(NMAX) !Generated i*2 waveform
|
||||
integer isync(24) !Indices of sync symbols
|
||||
integer itone(151) !Symbol values, data and sync
|
||||
integer*1 xin(0:49)
|
||||
integer*1 y(0:127)
|
||||
real*4 xnoise(NMAX) !Random noise
|
||||
real*4 dat(NMAX) !Generated real data
|
||||
complex cdat(NMAX) !Generated complex waveform
|
||||
complex crcvd(NMAX) !Signal as received
|
||||
real, allocatable :: s3(:,:) !Symbol spectra: will be s3(NQ,NN)
|
||||
integer, allocatable :: msg0(:) !Information symbols
|
||||
integer, allocatable :: chansym(:) !Encoded data, 7-bit integers
|
||||
character fname*17,arg*12,channel*2,foxcall*11
|
||||
character*10 ckey
|
||||
character*26 text_msg
|
||||
character*120 line !SuperFox message pieces
|
||||
character*40 cmsg(5)
|
||||
data ckey/'0000000000'/
|
||||
data cmsg/'W0AAA RR73; W5FFF <K1JT> -18', &
|
||||
'W1BBB RR73; W6GGG <K1JT> -15', &
|
||||
'W2CCC RR73; W7HHH <K1JT> -12', &
|
||||
'W3DDD RR73; W8III <K1JT> -09', &
|
||||
'W4EEE RR73; W9JJJ <K1JT> -06'/
|
||||
data text_msg/'0123456789ABCDEFGHIJKLMNOP'/
|
||||
data isync/1,2,4,7,11,16,22,29,37,39,42,43,45,48,52,57,63,70,78,80, &
|
||||
83,84,86,89/
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.10) then
|
||||
print*,'Usage: sfoxsim f0 DT Chan FoxC H1 H2 CQ FT nfiles snr'
|
||||
print*,'Example: sfoxsim 750 0.0 MM K1JT 5 1 0 0 10 -15'
|
||||
print*,' f0=0 to dither f0 and DT'
|
||||
print*,' Chan Channel type AW LQ LM LD MQ MM MD HQ HM HD'
|
||||
print*,' FoxC Fox callsign'
|
||||
print*,' key'
|
||||
print*,' H1 number of Hound calls with RR73'
|
||||
print*,' H2 number of Hound calls with reports'
|
||||
print*,' CQ=1 to include a CQ message'
|
||||
print*,' FT=1 to include a Free Text message'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,arg)
|
||||
read(arg,*) f0
|
||||
call getarg(2,arg)
|
||||
read(arg,*) xdt
|
||||
call getarg(3,channel)
|
||||
call getarg(4,foxcall)
|
||||
call getarg(5,arg)
|
||||
read(arg,*) nh1
|
||||
call getarg(6,arg)
|
||||
read(arg,*) nh2
|
||||
call getarg(7,arg)
|
||||
read(arg,*) ncq
|
||||
bMoreCQs=ncq.ne.0
|
||||
call getarg(8,arg)
|
||||
read(arg,*) nft
|
||||
bSendMsg=nft.ne.0
|
||||
call getarg(9,arg)
|
||||
read(arg,*) nfiles
|
||||
call getarg(10,arg)
|
||||
read(arg,*) snr
|
||||
|
||||
fspread=0.0
|
||||
delay=0.0
|
||||
fsample=12000.0 !Sample rate (Hz)
|
||||
call sfox_init(7,127,50,channel,fspread,delay,fsample,24)
|
||||
txt=(NN+NS)*NSPS/fsample
|
||||
write(*,1000) f0,xdt,channel,snr
|
||||
1000 format('sfoxsim: f0= ',f5.1,' dt= ',f4.2,' Channel: ',a2,' snr: ',f5.1,' dB')
|
||||
|
||||
! Allocate storage for arrays that depend on code parameters.
|
||||
allocate(s3(0:NQ-1,0:NN-1))
|
||||
allocate(msg0(1:KK))
|
||||
allocate(chansym(0:NN-1))
|
||||
|
||||
if(nft.ne.0) then
|
||||
open(10,file='text_msg.txt',status='old',err=2)
|
||||
read(10,*) text_msg
|
||||
endif
|
||||
|
||||
2 idum=-1
|
||||
rms=100.
|
||||
baud=fsample/nsps !Keying rate, 11.719 baud for nsps=1024
|
||||
bandwidth_ratio=2500.0/fsample
|
||||
do i=1,5
|
||||
cmsg(i)=cmsg(i)(1:19)//trim(foxcall)//cmsg(i)(24:28)
|
||||
if(i.gt.nh1 .and. i.gt.nh2) then
|
||||
cmsg(i)=''
|
||||
elseif(i.gt.nh1) then
|
||||
cmsg(i)=cmsg(i)(13:18)//trim(foxcall)//cmsg(i)(25:28)
|
||||
elseif(i.gt.nh2) then
|
||||
cmsg(i)=cmsg(i)(1:6)//trim(foxcall)//' RR73'
|
||||
endif
|
||||
! write(*,*) 'Debug ',cmsg(i)
|
||||
enddo
|
||||
|
||||
if((nh1+nh2).eq.0 .and. bMoreCQs) cmsg(1)='CQ '//trim(foxcall)//' FN20'
|
||||
|
||||
! Generate a SuperFox message
|
||||
nslots=5
|
||||
call foxgen2(nslots,cmsg,line,foxcall) !Parse old-style Fox messages
|
||||
call sfox_pack(line,ckey,bMoreCQs,bSendMsg,text_msg,xin)
|
||||
call qpc_encode(y,xin)
|
||||
|
||||
y=cshift(y,1)
|
||||
y(127)=0
|
||||
chansym=y(0:126)
|
||||
|
||||
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snr)
|
||||
sigr=sqrt(2.)*sig
|
||||
if(snr.gt.90.0) sig=1.0
|
||||
|
||||
do ifile=1,nfiles
|
||||
xnoise=0.
|
||||
if(snr.lt.90) then
|
||||
do i=1,NMAX
|
||||
xnoise(i)=gran() !Gaussian noise
|
||||
enddo
|
||||
endif
|
||||
|
||||
f1=f0
|
||||
if(f0.eq.0.0) then
|
||||
f1=750 + 20.0*(ran1(idum)-0.5)
|
||||
xdt=ran1(idum)-0.5
|
||||
endif
|
||||
! Generate cdat, the SuperFox waveform
|
||||
call sfox_gen_gfsk(chansym,f1,isync,itone,cdat)
|
||||
|
||||
crcvd=0.
|
||||
crcvd(1:NMAX)=cshift(cdat(1:NMAX),-nint((0.5+xdt)*fsample))
|
||||
if(fspread.ne.0 .or. delay.ne.0) call watterson(crcvd,NMAX,NZ,fsample,&
|
||||
delay,fspread)
|
||||
|
||||
dat=aimag(sigr*crcvd(1:NMAX)) + xnoise !Add generated AWGN noise
|
||||
fac=32767.0
|
||||
if(snr.ge.90.0) iwave(1:NMAX)=nint(fac*dat(1:NMAX))
|
||||
if(snr.lt.90.0) iwave(1:NMAX)=nint(rms*dat(1:NMAX))
|
||||
|
||||
h=default_header(12000,NMAX)
|
||||
fname='000000_000001.wav'
|
||||
nsec=(ifile-1)*30
|
||||
nhr=nsec/3600
|
||||
nmin=(nsec-nhr*3600)/60
|
||||
nsec=mod(nsec,60)
|
||||
write(fname(8:13),'(3i2.2)') nhr,nmin,nsec
|
||||
open(10,file=trim(fname),access='stream',status='unknown')
|
||||
write(10) h,iwave(1:NMAX) !Save the .wav file
|
||||
close(10)
|
||||
enddo ! ifile
|
||||
|
||||
999 end program sfoxsim
|
@ -1,59 +0,0 @@
|
||||
program sfrx
|
||||
|
||||
! Command-line SuperFox decoder
|
||||
|
||||
use sfox_mod
|
||||
use julian
|
||||
|
||||
integer*2 iwave(NMAX)
|
||||
integer ihdr(11)
|
||||
character*120 fname
|
||||
include 'gtag.f90'
|
||||
|
||||
narg=iargc()
|
||||
|
||||
if(narg.lt.1) then
|
||||
print*,'Usage: sfrx fsync ftol infile [...]'
|
||||
print*,' sfrx 775 10 240811_102400.wav'
|
||||
print*,'Reads one or more .wav files and calls SuperFox decoder on each.'
|
||||
print '(" Git tag: ",z9)',ntag
|
||||
go to 999
|
||||
endif
|
||||
|
||||
call getarg(1,fname)
|
||||
read(fname,*,err=1) fsync
|
||||
call getarg(2,fname)
|
||||
read(fname,*,err=1) ftol
|
||||
|
||||
nfqso=nint(fsync)
|
||||
ntol=nint(ftol)
|
||||
|
||||
1 nf=0
|
||||
nd=0
|
||||
nv=0
|
||||
|
||||
do ifile=3,narg
|
||||
call getarg(ifile,fname)
|
||||
write(72,*) ifile,narg,fname
|
||||
open(10,file=trim(fname),status='old',access='stream',err=4)
|
||||
|
||||
go to 5
|
||||
4 print*,'Cannot open file ',trim(fname)
|
||||
go to 999
|
||||
5 read(10) ihdr,iwave
|
||||
close(10)
|
||||
|
||||
nz=len(trim(fname))
|
||||
nyymmdd=ihdr(1)
|
||||
nutc=ihdr(2)
|
||||
if(fname(nz-3:nz).eq.'.wav') then
|
||||
read(fname(nz-16:nz-11),*) nyymmdd
|
||||
read(fname(nz-9:nz-4),*) nutc
|
||||
endif
|
||||
|
||||
call sfrx_sub(nyymmdd,nutc,nfqso,ntol,iwave)
|
||||
|
||||
nf=nf+1
|
||||
enddo
|
||||
|
||||
999 end program sfrx
|
@ -1,54 +0,0 @@
|
||||
subroutine sfrx_sub(nyymmdd,nutc,nfqso,ntol,iwave)
|
||||
|
||||
use sfox_mod
|
||||
use julian
|
||||
|
||||
integer*2 iwave(NMAX)
|
||||
integer*8 secday,ntime8
|
||||
integer*1 xdec(0:49)
|
||||
character*13 foxcall
|
||||
complex c0(NMAX) !Complex form of signal as received
|
||||
real dd(NMAX)
|
||||
logical crc_ok
|
||||
data secday/86400/
|
||||
|
||||
fsync=nfqso
|
||||
ftol=ntol
|
||||
fsample=12000.0
|
||||
call sfox_init(7,127,50,'no',fspread,delay,fsample,24)
|
||||
npts=15*12000
|
||||
|
||||
if(nyymmdd.eq.-1) then
|
||||
ntime8=itime8()/30
|
||||
ntime8=30*ntime8
|
||||
else
|
||||
iyr=2000+nyymmdd/10000
|
||||
imo=mod(nyymmdd/100,100)
|
||||
iday=mod(nyymmdd,100)
|
||||
ih=nutc/10000
|
||||
im=mod(nutc/100,100)
|
||||
is=mod(nutc,100)
|
||||
ntime8=secday*(JD(iyr,imo,iday)-2440588) + 3600*ih + 60*im + is
|
||||
endif
|
||||
|
||||
dd=iwave
|
||||
call sfox_remove_ft8(dd,npts)
|
||||
|
||||
call sfox_ana(dd,npts,c0,npts)
|
||||
|
||||
call sfox_remove_tone(c0,fsync) ! Needs testing
|
||||
|
||||
ndepth=3
|
||||
dth=0.5
|
||||
damp=1.0
|
||||
|
||||
call qpc_decode2(c0,fsync,ftol, xdec,ndepth,dth,damp,crc_ok, &
|
||||
snrsync,fbest,tbest,snr)
|
||||
if(crc_ok) then
|
||||
nsnr=nint(snr)
|
||||
nsignature = 1
|
||||
call sfox_unpack(nutc,xdec,nsnr,fbest-750.0,tbest,foxcall,nsignature)
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine sfrx_sub
|
@ -1,107 +0,0 @@
|
||||
program sftx
|
||||
|
||||
! This program is required in order to create a SuperFox transmission.
|
||||
|
||||
! The present version goes through the following steps:
|
||||
! 1. Read old-style Fox messages from file 'sfox_1.dat' in the WSJT-X
|
||||
! writable data directory.
|
||||
! 2. Parse up to NSlots=5 messages to extract MyCall, up to 9 Hound
|
||||
! calls, and the report or RR73 to be sent to each Hound.
|
||||
! 3. Assemble and encode a single SuperFox message to produce itone(1:151),
|
||||
! the array of channel symbol values.
|
||||
! 4. Write the contents of array itone to file 'sfox_2.dat'.
|
||||
|
||||
use qpc_mod
|
||||
use sfox_mod
|
||||
character*120 fname !Corrected path for sfox_1.dat
|
||||
character*120 line !List of SuperFox message pieces
|
||||
character*40 cmsg(5) !Old-style Fox messages
|
||||
character*26 freeTextMsg
|
||||
character*2 arg
|
||||
character*10 ckey
|
||||
! character*9 foxkey
|
||||
character*11 foxcall0,foxcall
|
||||
logical*1 bMoreCQs,bSendMsg
|
||||
logical crc_ok
|
||||
real py(0:127,0:127) !Probabilities for received synbol values
|
||||
integer*8 n47
|
||||
integer itone(151) !SuperFox channel-symbol values
|
||||
integer*1 xin(0:49) !Packed message as 7-bit symbols
|
||||
integer*1 xdec(0:49) !Decoded message
|
||||
integer*1 y(0:127) !Encoded symbols as i*1 integers
|
||||
integer*1 ydec(0:127) !Decoded codeword
|
||||
integer*1 yy(0:10)
|
||||
integer chansym0(127) !Transmitted symbols, data only
|
||||
integer chansym(127) !Received symbols, data only
|
||||
integer isync(24) !Symbol numbers for sync tones
|
||||
data isync/1,2,4,7,11,16,22,29,37,39,42,43,45,48,52,57,63,70,78,80, &
|
||||
83,84,86,89/
|
||||
include 'gtag.f90'
|
||||
|
||||
narg=iargc()
|
||||
if(narg.ne.3) then
|
||||
print '(" Git tag: ",z9)',ntag
|
||||
go to 999
|
||||
endif
|
||||
|
||||
! sftx <message_file_name> <foxcall> <ckey>
|
||||
call getarg(1,fname)
|
||||
do i=1,len(trim(fname))
|
||||
if(fname(i:i).eq.'\\') fname(i:i)='/'
|
||||
enddo
|
||||
call getarg(2,foxcall0)
|
||||
call getarg(3,ckey)
|
||||
|
||||
! if((foxkey(foxcall0).ne.ckey).and.(INDEX(ckey,'OTP:').eq.0)) then ! neither kind
|
||||
! itone=-99
|
||||
! go to 100
|
||||
! endif
|
||||
|
||||
fsample=12000.0
|
||||
call sfox_init(7,127,50,'no',fspread,delay,fsample,24)
|
||||
open(25,file=trim(fname),status='unknown')
|
||||
do i=1,5
|
||||
read(25,1000,end=10) cmsg(i)
|
||||
1000 format(a40)
|
||||
enddo
|
||||
i=6
|
||||
10 close(25)
|
||||
nslots=i-1
|
||||
freeTextMsg=' '
|
||||
bMoreCQs=cmsg(1)(40:40).eq.'1'
|
||||
bSendMsg=cmsg(nslots)(39:39).eq.'1'
|
||||
if(bSendMsg) then
|
||||
freeTextMsg=cmsg(nslots)(1:26)
|
||||
if(nslots.gt.2) nslots=2
|
||||
endif
|
||||
|
||||
call foxgen2(nslots,cmsg,line,foxcall) !Parse old-style Fox messages
|
||||
|
||||
! Pack message information and CRC into xin(0:49)
|
||||
call sfox_pack(line,ckey,bMoreCQs,bSendMsg,freeTextMsg,xin)
|
||||
call qpc_encode(y,xin) !Encode the message to 128 symbols
|
||||
y=cshift(y,1) !Puncture the code by removing y(0)
|
||||
y(127)=0
|
||||
chansym0=y(0:126)
|
||||
|
||||
! Create the full itone sequence containing both data and sync symbols
|
||||
j=1
|
||||
k=0
|
||||
do i=1,NDS
|
||||
if(j.le.NS .and. i.eq.isync(j)) then
|
||||
if(j.lt.NS) j=j+1 !Index for next sync symbol
|
||||
itone(i)=0 !Insert sync symbol at tone 0
|
||||
else
|
||||
k=k+1
|
||||
itone(i)=chansym0(k) + 1 !Symbol value 0 transmitted as tone 1, etc.
|
||||
endif
|
||||
enddo
|
||||
|
||||
100 i1=max(index(fname,'sfox_1'),1)
|
||||
fname(i1:i1+9)='sfox_2.dat'
|
||||
open(25,file=trim(fname),status='unknown')
|
||||
write(25,1100) itone
|
||||
1100 format(20i4)
|
||||
close(25)
|
||||
|
||||
999 end program sftx
|
@ -1,65 +0,0 @@
|
||||
subroutine sftx_sub(ckey0)
|
||||
|
||||
! This routine is required in order to create a SuperFox transmission.
|
||||
|
||||
! The present version goes through the following steps:
|
||||
! 1. Read old-style Fox messages from file 'sfox_1.dat' in the WSJT-X
|
||||
! writable data directory.
|
||||
! 2. Parse up to NSlots=5 messages to extract MyCall, up to 9 Hound
|
||||
! calls, and the report or RR73 to be sent to each Hound.
|
||||
! 3. Assemble and encode a single SuperFox message to produce itone(1:151),
|
||||
! the array of channel symbol values.
|
||||
! 4. Write the contents of array itone to file 'sfox_2.dat'.
|
||||
|
||||
use qpc_mod
|
||||
use sfox_mod
|
||||
character*120 line !List of SuperFox message pieces
|
||||
character*40 cmsg !Old-style Fox messages
|
||||
character*26 freeTextMsg
|
||||
character*(*) ckey0
|
||||
character*10 ckey
|
||||
character*11 foxcall
|
||||
logical*1 bMoreCQs,bSendMsg
|
||||
integer*1 xin(0:49) !Packed message as 7-bit symbols
|
||||
integer*1 y(0:127) !Encoded symbols as i*1 integers
|
||||
integer chansym0(127) !Transmitted symbols, data only
|
||||
integer isync(24) !Symbol numbers for sync tones
|
||||
common/foxcom3/nslots,cmsg(5),itone(151)
|
||||
data isync/1,2,4,7,11,16,22,29,37,39,42,43,45,48,52,57,63,70,78,80, &
|
||||
83,84,86,89/
|
||||
|
||||
ckey=ckey0
|
||||
|
||||
fsample=12000.0
|
||||
call sfox_init(7,127,50,'no',fspread,delay,fsample,24)
|
||||
freeTextMsg=' '
|
||||
bMoreCQs=cmsg(1)(40:40).eq.'1'
|
||||
bSendMsg=cmsg(nslots)(39:39).eq.'1'
|
||||
if(bSendMsg) then
|
||||
freeTextMsg=cmsg(nslots)(1:26)
|
||||
if(nslots.gt.4) nslots=4
|
||||
endif
|
||||
|
||||
call foxgen2(nslots,cmsg,line,foxcall) !Parse old-style Fox messages
|
||||
|
||||
! Pack message information and CRC into xin(0:49)
|
||||
call sfox_pack(line,ckey,bMoreCQs,bSendMsg,freeTextMsg,xin)
|
||||
call qpc_encode(y,xin) !Encode the message to 128 symbols
|
||||
y=cshift(y,1) !Puncture the code by removing y(0)
|
||||
y(127)=0
|
||||
chansym0=y(0:126)
|
||||
|
||||
! Create the full itone sequence containing both data and sync symbols
|
||||
j=1
|
||||
k=0
|
||||
do i=1,NDS
|
||||
if(j.le.NS .and. i.eq.isync(j)) then
|
||||
if(j.lt.NS) j=j+1 !Index for next sync symbol
|
||||
itone(i)=0 !Insert sync symbol at tone 0
|
||||
else
|
||||
k=k+1
|
||||
itone(i)=chansym0(k) + 1 !Symbol value 0 transmitted as tone 1, etc.
|
||||
endif
|
||||
enddo
|
||||
|
||||
end subroutine sftx_sub
|
@ -1,66 +0,0 @@
|
||||
Bit packing of SuperFox QPC Messages
|
||||
-----------------------------------------------------------------------------
|
||||
The IV3NWV Q-ary Polar Code has parameters (n,k) = (127,50). The last
|
||||
three 7-bit information symbols convey a 21-bit CRC based on the first
|
||||
47 symbols. Thus, each Super Fox transmission carries a payload of
|
||||
47*7=329 bits. On a modern x86 processor the decoder executes in
|
||||
deterministic time around 5 ms per decode, and always produces a
|
||||
result. The CRC test rejects all but around 1 in two million false
|
||||
decodes.
|
||||
|
||||
Bit fields are labeled with tags as defined in the QEX article "The
|
||||
FT4 and FT8 Communication Protocols" by Franke, Somerville, and Taylor
|
||||
in QEX for July/August 2020, available on the WSJT web site here:
|
||||
https://wsjt.sourceforge.io/FT4_FT8_QEX.pdf. As one example, the tag
|
||||
'c28' denotes a standard callsign, which requires 28 bits.
|
||||
|
||||
=============================================================================
|
||||
i3 = 0: Standard message: FoxCall, up to 9 HoundCalls, up to 4 signal
|
||||
reports, "MoreCQs" flag, a digital signature, and a 3-bit message type.
|
||||
-----------------------------------------------------------------------------
|
||||
F H1 H2 H3 H4 H5 H6 H7 H8 H9 R6 R7 R8 R9 U Q D M Type
|
||||
c28 c28 c28 c28 c28 c28 c28 c28 c28 c28 r5 r5 r5 r5 u5 q1 d20 i3=0 Std Msg
|
||||
280 300 305 326 329
|
||||
=============================================================================
|
||||
i3 = 1: If Fox uses a compound callsign we have space for only 8 Hound calls.
|
||||
Otherwise like type i3=0.
|
||||
-----------------------------------------------------------------------------
|
||||
FC H1 H2 H2 H4 H5 H6 H7 H8 R5 R6 R7 R8 U Q D M
|
||||
c58 c28 c28 c28 c28 c28 c28 c28 c28 r5 r5 r5 r5 u3 q1 d20 i3=1
|
||||
58 282 302 305 326 329
|
||||
=============================================================================
|
||||
i3 = 2: A free text message with up to 26 characters can be transmitted along
|
||||
with messages to as many as 4 Hounds conveying either reports or RR73s.
|
||||
-----------------------------------------------------------------------------
|
||||
F H1 H2 H3 H4 R1 R2 R3 R4 T T U Q D M Type
|
||||
c28 c28 c28 c28 c28 r5 r5 r5 r5 t71 t71 u3 q1 d20 i3=2 FT+4H
|
||||
140 160 302 305 326 329
|
||||
=============================================================================
|
||||
i3 = 3: Message "CQ FoxCall Grid <Free text>"
|
||||
-----------------------------------------------------------------------------
|
||||
FC G T T U Q D M Type
|
||||
c58 g15 t71 t71 u90 q1 d20 i3=3 CQ FT
|
||||
58 73 144 215 305 326 329
|
||||
=============================================================================
|
||||
|
||||
D Digital signature (20 bits)
|
||||
F Fox call (28 bits)
|
||||
FC Compound Fox call (58 bits)
|
||||
G Grid locator (15 bits)
|
||||
H Hound call (28 bits)
|
||||
M Message type (3 bits)
|
||||
Q MoreCQs flag
|
||||
R Report, (5 bits: -18 to +12 dB, or RR73)
|
||||
T Free text, up to 26 characters total
|
||||
U Unused bits
|
||||
|
||||
Unused callsign slots are set to the numerical value for "QU1RKS", and
|
||||
ignored when received. Similarly for unused t71 slots. Unused report
|
||||
slots are set to 0 (-20 dB). "CQ FoxCall" will be displayed along
|
||||
with other messages if the "q1" bit is 1.
|
||||
|
||||
The SuperFox decoder displays its results with a separate line for each Hound.
|
||||
Thus, the old-style message "K1ABC RR73; W9XYZ <VP8PJ> -14" becomes
|
||||
|
||||
K1ABC VP8PJ RR73
|
||||
W9XYZ VP8PJ -14
|
@ -1,19 +0,0 @@
|
||||
subroutine twkfreq2(c3,c4,npts,fsample,fshift)
|
||||
|
||||
! Adjust frequency of complex waveform
|
||||
|
||||
complex c3(npts)
|
||||
complex c4(npts)
|
||||
complex w,wstep
|
||||
data twopi/6.283185307/
|
||||
|
||||
w=1.0
|
||||
dphi=fshift*twopi/fsample
|
||||
wstep=cmplx(cos(dphi),sin(dphi))
|
||||
do i=1,npts
|
||||
w=w*wstep
|
||||
c4(i)=w*c3(i)
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine twkfreq2
|
@ -9,6 +9,7 @@
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class Configuration;
|
||||
class QDateTime;
|
||||
class QSqlTableModel;
|
||||
class QTextStream;
|
||||
class AD1CCty;
|
||||
|
109
otpgenerator.cpp
109
otpgenerator.cpp
@ -1,109 +0,0 @@
|
||||
|
||||
#include "otpgenerator.h"
|
||||
|
||||
#include <QMessageAuthenticationCode>
|
||||
#include <QtEndian>
|
||||
#include <QDateTime>
|
||||
#include <QtMath>
|
||||
|
||||
// FROM https://github.com/RikudouSage/QtOneTimePassword/
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Dominik Chrástecký
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
OTPGenerator::OTPGenerator(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray OTPGenerator::generateHOTP(const QByteArray &rawSecret, quint64 counter, int length)
|
||||
{
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
counter = qToBigEndian(counter);
|
||||
#endif
|
||||
QByteArray data;
|
||||
data.reserve(8);
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
data.append(counter & 0xff);
|
||||
counter >>= 8;
|
||||
}
|
||||
QMessageAuthenticationCode mac(QCryptographicHash::Sha1);
|
||||
mac.setKey(rawSecret);
|
||||
mac.addData(data);
|
||||
QByteArray hmac = mac.result();
|
||||
int offset = hmac.at(hmac.length() - 1) & 0xf;
|
||||
quint32 truncatedHash = ((hmac.at(offset) & 0x7f) << 24)
|
||||
| ((hmac.at(offset + 1) & 0xff) << 16)
|
||||
| ((hmac.at(offset + 2) & 0xff) << 8)
|
||||
| (hmac.at(offset + 3) & 0xff);
|
||||
int modulus = int(qPow(10, length));
|
||||
return QByteArray::number(truncatedHash % modulus, 10).rightJustified(length, '0');
|
||||
}
|
||||
|
||||
QString OTPGenerator::generateHOTP(const QString &secret, quint64 counter, int length)
|
||||
{
|
||||
return generateHOTP(fromBase32(secret), counter, length);
|
||||
}
|
||||
|
||||
QByteArray OTPGenerator::generateTOTP(const QByteArray &rawSecret, int length)
|
||||
{
|
||||
const qint64 counter = QDateTime::currentDateTime().toMSecsSinceEpoch() / 30000;
|
||||
return generateHOTP(rawSecret, counter, length);
|
||||
}
|
||||
|
||||
QString OTPGenerator::generateTOTP(const QString &secret, int length)
|
||||
{
|
||||
return generateTOTP(fromBase32(secret), length);
|
||||
}
|
||||
|
||||
QString OTPGenerator::generateTOTP(const QString &secret, QDateTime dt, int length)
|
||||
{
|
||||
const qint64 counter = dt.toMSecsSinceEpoch() / 30000;
|
||||
return generateHOTP(fromBase32(secret), counter, length);
|
||||
}
|
||||
|
||||
QByteArray OTPGenerator::fromBase32(const QString &input)
|
||||
{
|
||||
QByteArray result;
|
||||
result.reserve((input.length() * 5 + 7) / 8);
|
||||
int buffer = 0;
|
||||
int bitsLeft = 0;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
int ch = input[i].toLatin1();
|
||||
int value;
|
||||
if (ch >= 'A' && ch <= 'Z')
|
||||
value = ch - 'A';
|
||||
else if (ch >= '2' && ch <= '7')
|
||||
value = 26 + ch - '2';
|
||||
else
|
||||
continue;
|
||||
buffer = (buffer << 5) | value;
|
||||
bitsLeft += 5;
|
||||
if (bitsLeft >= 8) {
|
||||
result.append(buffer >> (bitsLeft - 8));
|
||||
bitsLeft -= 8;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#ifndef OTPGENERATOR_H
|
||||
#define OTPGENERATOR_H
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Dominik Chrástecký
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#define BASE32_CHARSET "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
||||
|
||||
class OTPGenerator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OTPGenerator(QObject *parent = nullptr);
|
||||
|
||||
QByteArray generateHOTP(const QByteArray &rawSecret, quint64 counter, int length);
|
||||
Q_INVOKABLE QString generateHOTP(const QString &secret, quint64 counter, int length);
|
||||
|
||||
QByteArray generateTOTP(const QByteArray &rawSecret, int length);
|
||||
Q_INVOKABLE QString generateTOTP(const QString &secret, QDateTime dt, int length);
|
||||
Q_INVOKABLE QString generateTOTP(const QString &secret, int length);
|
||||
private:
|
||||
QByteArray fromBase32(const QString &input);
|
||||
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // OTPGENERATOR_H
|
@ -1,7 +1,7 @@
|
||||
subroutine decode0(dd,ss,savg)
|
||||
|
||||
use timer_module, only: timer
|
||||
parameter (NSMAX=60*96000,NFFT=32768)
|
||||
parameter (NSMAX=60*96000)
|
||||
|
||||
real*4 dd(2,NSMAX),ss(400,NFFT),savg(NFFT)
|
||||
real*8 fcenter
|
||||
|
@ -89,7 +89,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widgets/activeStations.ui" line="141"/>
|
||||
<source><html><head/><body><p>Check this box to show only stations ready to be called.</p></body></html></source>
|
||||
<source><html><head/><body><p>Check tis box to show only stations ready to be called.</p></body></html></source>
|
||||
<translation><html><head/><body><p>Seleziona questa casella per visualizzare solo le stazioni pronte per essere chiamate.</p></body></html></translation>
|
||||
</message>
|
||||
<message>
|
||||
|
File diff suppressed because it is too large
Load Diff
6668
translations/wsjtx_zh_HK.ts
Normal file
6668
translations/wsjtx_zh_HK.ts
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -40,26 +40,6 @@ void ActiveStations::changeFont (QFont const& font)
|
||||
updateGeometry ();
|
||||
}
|
||||
|
||||
void ActiveStations::clearStations() {
|
||||
m_textbuffer.clear();
|
||||
m_decodes_by_frequency.clear();
|
||||
}
|
||||
|
||||
void ActiveStations::addLine(QString line) {
|
||||
QString m_textbuffer = "";
|
||||
// "012700 -1 0.2 210 ~ KJ7COA JA2HGF -14"
|
||||
unsigned freq = line.mid(16, 4).toUInt();
|
||||
m_decodes_by_frequency[freq] = line;
|
||||
// show them in frequency order
|
||||
QMap<int, QString>::const_iterator i = m_decodes_by_frequency.constBegin();
|
||||
m_textbuffer.clear();
|
||||
while (i != m_decodes_by_frequency.constEnd()) {
|
||||
m_textbuffer.append(i.value());
|
||||
++i;
|
||||
}
|
||||
this->displayRecentStations(m_mode, m_textbuffer);
|
||||
}
|
||||
|
||||
void ActiveStations::read_settings ()
|
||||
{
|
||||
SettingsGroup group {settings_, "ActiveStations"};
|
||||
@ -80,7 +60,8 @@ void ActiveStations::write_settings ()
|
||||
settings_->setValue("WantedOnly",ui->cbWantedOnly->isChecked());
|
||||
}
|
||||
|
||||
void ActiveStations::setupUi(QString mode) {
|
||||
void ActiveStations::displayRecentStations(QString mode, QString const& t)
|
||||
{
|
||||
if(mode!=m_mode) {
|
||||
m_mode=mode;
|
||||
ui->cbReadyOnly->setText(" Ready only");
|
||||
@ -90,37 +71,24 @@ void ActiveStations::setupUi(QString mode) {
|
||||
ui->cbReadyOnly->setText("* CQ only");
|
||||
} else if(m_mode=="Q65-pileup") {
|
||||
ui->header_label2->setText(" N Freq Call Grid El Age(h)");
|
||||
ui->cbWantedOnly->setText(QCoreApplication::translate("ActiveStations", "Wanted only", nullptr));
|
||||
} else if(m_mode=="Fox Mode" || m_mode=="SuperFox Mode" ) {
|
||||
ui->header_label2->setText(" UTC dB DT Freq " + tr("Message"));
|
||||
ui->cbWantedOnly->setText(QCoreApplication::translate("ActiveStations", "My call only", nullptr));
|
||||
this->setClickOK(true);
|
||||
} else {
|
||||
ui->header_label2->setText(" N Call Grid Az S/N Freq Tx Age Pts");
|
||||
ui->label->setText("Rate:");
|
||||
ui->cbWantedOnly->setText(QCoreApplication::translate("ActiveStations", "Wanted only", nullptr));
|
||||
}
|
||||
bool b=(m_mode.left(3)=="Q65");
|
||||
bool is_fox_mode =(m_mode=="Fox Mode");
|
||||
ui->bandChanges->setVisible(!b && !is_fox_mode);
|
||||
ui->cbReadyOnly->setVisible(m_mode != "Q65-pileup" && !is_fox_mode);
|
||||
ui->cbWantedOnly->setVisible(m_mode != "Q65-pileup"); // this is used for "My call only" in Fox mode
|
||||
ui->label_2->setVisible(!b && !is_fox_mode);
|
||||
ui->label_3->setVisible(!b && !is_fox_mode);
|
||||
ui->score->setVisible(!b && !is_fox_mode);
|
||||
ui->sbMaxRecent->setVisible(!b && !is_fox_mode);
|
||||
ui->bandChanges->setVisible(!b);
|
||||
ui->cbReadyOnly->setVisible(m_mode!="Q65-pileup");
|
||||
ui->cbWantedOnly->setVisible(m_mode!="Q65-pileup");
|
||||
ui->label_2->setVisible(!b);
|
||||
ui->label_3->setVisible(!b);
|
||||
ui->score->setVisible(!b);
|
||||
ui->sbMaxRecent->setVisible(!b);
|
||||
|
||||
b=(m_mode!="Q65-pileup" && !is_fox_mode);
|
||||
b=(m_mode!="Q65-pileup");
|
||||
ui->sbMaxAge->setVisible(b);
|
||||
ui->label->setVisible(b);
|
||||
ui->rate->setVisible(b);
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveStations::displayRecentStations(QString mode, QString const& t)
|
||||
{
|
||||
setupUi(mode);
|
||||
|
||||
bool bClickOK=m_clickOK;
|
||||
m_clickOK=false;
|
||||
ui->RecentStationsPlainTextEdit->setPlainText(t);
|
||||
@ -175,10 +143,7 @@ void ActiveStations::on_textEdit_clicked()
|
||||
if(text!="") {
|
||||
int nline=text.left(2).toInt();
|
||||
if(QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier)) nline=-nline;
|
||||
if (!m_mode.contains("fox", Qt::CaseInsensitive))
|
||||
emit callSandP(nline);
|
||||
else
|
||||
emit queueActiveWindowHound(text);
|
||||
emit callSandP(nline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define ARRL_DIGI_H_
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMap>
|
||||
|
||||
class QSettings;
|
||||
class QFont;
|
||||
@ -21,7 +20,6 @@ public:
|
||||
explicit ActiveStations(QSettings *, QFont const&, QWidget * parent = 0);
|
||||
~ActiveStations();
|
||||
void displayRecentStations(QString mode, QString const&);
|
||||
void setupUi(QString display_mode);
|
||||
void changeFont (QFont const&);
|
||||
int maxRecent();
|
||||
int maxAge();
|
||||
@ -32,8 +30,6 @@ public:
|
||||
void setRate(int n);
|
||||
void setBandChanges(int n);
|
||||
void setScore(int n);
|
||||
void clearStations();
|
||||
void addLine(QString);
|
||||
|
||||
bool m_clickOK=false;
|
||||
bool m_bReadyOnly;
|
||||
@ -45,16 +41,14 @@ private:
|
||||
Q_SIGNAL void callSandP(int nline);
|
||||
Q_SIGNAL void activeStationsDisplay();
|
||||
Q_SIGNAL void cursorPositionChanged();
|
||||
Q_SIGNAL void queueActiveWindowHound(QString text);
|
||||
|
||||
Q_SLOT void on_cbReadyOnly_toggled(bool b);
|
||||
Q_SLOT void on_cbWantedOnly_toggled(bool b);
|
||||
Q_SLOT void on_textEdit_clicked();
|
||||
|
||||
// qint64 m_msec0=0;
|
||||
QString m_mode="";
|
||||
QSettings * settings_;
|
||||
QString m_textbuffer=""; // F/H mode band decodes
|
||||
QMap<int, QString> m_decodes_by_frequency; // store decodes for F/H band awareness by frequency
|
||||
|
||||
QScopedPointer<Ui::ActiveStations> ui;
|
||||
};
|
||||
|
@ -69,7 +69,7 @@
|
||||
<item row="0" column="3">
|
||||
<widget class="QCheckBox" name="cbReadyOnly">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Check this box to show only stations ready to be called.</p></body></html></string>
|
||||
<string><html><head/><body><p>Check tis box to show only stations ready to be called.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ready only</string>
|
||||
|
@ -213,11 +213,27 @@ void DisplayText::insertText(QString const& text, QColor bg, QColor fg
|
||||
|
||||
void DisplayText::extend_vertical_scrollbar (int min, int max)
|
||||
{
|
||||
static int mod_last;
|
||||
static int height;
|
||||
if (high_volume_ && m_config && m_config->decodes_from_top ())
|
||||
{
|
||||
auto m = modified_vertical_scrollbar_max_;
|
||||
if (m != mod_last) { height = m - mod_last;mod_last = m; }
|
||||
//auto vp_margins2 = viewportMargins ();
|
||||
if (height == 0 && m > viewport()->height()) height = abs( - viewport()->height());
|
||||
//LOG_INFO ("scrollbar min=" << min << " max=" << max << " mod=" << modified_vertical_scrollbar_max_ << " height=" << viewport()->height() << " top=" << vp_margins2.top() << " bottom=" << vp_margins2.bottom()) << " height=" << height << " mod_last=" << mod_last;
|
||||
if (max > 60000)
|
||||
{
|
||||
QString tmp = toPlainText();
|
||||
while (tmp != NULL && tmp.length() > 100 && max > 50000)
|
||||
{
|
||||
tmp.remove(0, tmp.indexOf("\n")+1);
|
||||
max -= height;
|
||||
}
|
||||
setPlainText(tmp);
|
||||
}
|
||||
if (max && max != modified_vertical_scrollbar_max_)
|
||||
{
|
||||
setViewportMargins (0,4,0,0); // ensure first line is readable
|
||||
auto vp_margins = viewportMargins ();
|
||||
// add enough to vertical scroll bar range to allow last
|
||||
// decode to just scroll of the top of the view port
|
||||
@ -230,10 +246,6 @@ void DisplayText::extend_vertical_scrollbar (int min, int max)
|
||||
|
||||
void DisplayText::new_period ()
|
||||
{
|
||||
if (m_config->decodes_from_top ()) {
|
||||
document ()->setMaximumBlockCount (4800);
|
||||
document ()->setMaximumBlockCount (5000);
|
||||
}
|
||||
extend_vertical_scrollbar (verticalScrollBar ()->minimum (), verticalScrollBar ()->maximum ());
|
||||
if (high_volume_ && m_config && m_config->decodes_from_top () && !vertical_scroll_connection_)
|
||||
{
|
||||
@ -506,11 +518,11 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
|
||||
|
||||
void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
|
||||
bool bFastMode, double TRperiod,bool bSuperfox)
|
||||
bool bFastMode, double TRperiod)
|
||||
{
|
||||
QString t1=" @ ";
|
||||
if(modeTx=="FT4") t1=" + ";
|
||||
if(modeTx.contains("FT8")) t1=" ~ ";
|
||||
if(modeTx=="FT8") t1=" ~ ";
|
||||
if(modeTx=="JT4") t1=" $ ";
|
||||
if(modeTx=="Q65") t1=" : ";
|
||||
if(modeTx=="JT65") t1=" # ";
|
||||
@ -534,18 +546,7 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
|
||||
QColor fg;
|
||||
highlight_types types {Highlight::Tx};
|
||||
set_colours (m_config, &bg, &fg, types);
|
||||
if(bSuperfox and t.contains(";")) {
|
||||
int i0=t.indexOf(";");
|
||||
int i1=t.indexOf("<");
|
||||
int i2=t.indexOf(">");
|
||||
QString foxcall=t.mid(i1+1,i2-i1-1);
|
||||
t2=t.left(i0).replace(" RR73", " " + foxcall + " RR73");
|
||||
QString t3=t.left(24) + t.mid(i0+2,-1).remove("<").remove(">");
|
||||
insertText (t2, bg, fg);
|
||||
insertText (t3, bg, fg);
|
||||
} else {
|
||||
insertText (t, bg, fg);
|
||||
}
|
||||
insertText (t, bg, fg);
|
||||
}
|
||||
|
||||
void DisplayText::displayQSY(QString text)
|
||||
@ -560,22 +561,6 @@ void DisplayText::displayHoundToBeCalled(QString t, bool bAtTop, QColor bg, QCol
|
||||
insertText(t, bg, fg, "", "", bAtTop ? QTextCursor::Start : QTextCursor::End);
|
||||
}
|
||||
|
||||
void DisplayText::setHighlightedHoundText(QString t) {
|
||||
QColor bg=QColor{255,255,255};
|
||||
QColor fg=QColor{0,0,0};
|
||||
highlight_types types{Highlight::Call};
|
||||
set_colours(m_config, &bg, &fg, types);
|
||||
// t is multiple lines of text, each line is a hound calling
|
||||
// iterate through each line and highlight the callsign
|
||||
auto lines = t.split(QChar('\n'), SkipEmptyParts);
|
||||
clear();
|
||||
foreach (auto line, lines)
|
||||
{
|
||||
auto fields = line.split(QChar(' '), SkipEmptyParts);
|
||||
insertText(line, bg, fg, fields.first(), QString{});
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void update_selection (QTextCursor& cursor, QColor const& bg, QColor const& fg)
|
||||
@ -635,11 +620,6 @@ void DisplayText::highlight_callsign (QString const& callsign, QColor const& bg,
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (callsign == "CLEARALL!") // programmatic means of clearing all highlighting
|
||||
{
|
||||
highlighted_calls_.clear();
|
||||
return;
|
||||
}
|
||||
auto regexp = callsign;
|
||||
// allow for hashed callsigns and escape any regexp metacharacters
|
||||
QRegularExpression target {QString {"<?"}
|
||||
|
@ -30,13 +30,10 @@ public:
|
||||
void displayDecodedText(DecodedText const& decodedText, QString const& myCall, QString const& mode,
|
||||
bool displayDXCCEntity, LogBook const& logBook,
|
||||
QString const& currentBand=QString {}, bool ppfx=false, bool bCQonly=false,
|
||||
bool haveFSpread = false, float fSpread = 0.0, bool bDisplayPoints=false,
|
||||
int points=-99);
|
||||
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq, bool bFastMode,
|
||||
double TRperiod, bool bSuperfox);
|
||||
bool haveFSpread = false, float fSpread = 0.0, bool bDisplayPoints=false, int points=-99);
|
||||
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq, bool bFastMode, double TRperiod);
|
||||
void displayQSY(QString text);
|
||||
void displayHoundToBeCalled(QString t, bool bAtTop=false, QColor bg = QColor {}, QColor fg = QColor {});
|
||||
void setHighlightedHoundText(QString text);
|
||||
void new_period ();
|
||||
QString CQPriority(){return m_CQPriority;};
|
||||
qint32 m_points;
|
||||
|
@ -167,7 +167,7 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
|
||||
auto special_op = m_config->special_op_id ();
|
||||
if (SpOp::FOX == special_op
|
||||
|| (m_config->autoLog ()
|
||||
&& ((SpOp::NONE < special_op && special_op < SpOp::FOX) || SpOp::ARRL_DIGI == special_op)))
|
||||
&& SpOp::NONE < special_op && special_op < SpOp::FOX))
|
||||
{
|
||||
// allow auto logging in Fox mode and contests
|
||||
accept();
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user