mirror of https://github.com/saitohirga/WSJT-X.git
Reintegrate merge from wsjtx_exp branch.
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6122 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
1be194efdd
commit
1a23757b26
|
@ -234,6 +234,8 @@ set (wsjtx_CXXSRCS
|
|||
widegraph.cpp
|
||||
echograph.cpp
|
||||
echoplot.cpp
|
||||
fastgraph.cpp
|
||||
fastplot.cpp
|
||||
about.cpp
|
||||
astro.cpp
|
||||
messageaveraging.cpp
|
||||
|
@ -260,6 +262,7 @@ endif (WIN32)
|
|||
set (wsjt_FSRCS
|
||||
lib/afc65b.f90
|
||||
lib/afc9.f90
|
||||
lib/ana932.f90
|
||||
lib/analytic.f90
|
||||
lib/astro.f90
|
||||
lib/astrosub.f90
|
||||
|
@ -275,9 +278,9 @@ set (wsjt_FSRCS
|
|||
lib/chkss2.f90
|
||||
lib/coord.f90
|
||||
lib/db.f90
|
||||
lib/decode4.f90
|
||||
lib/decode65a.f90
|
||||
lib/decode65b.f90
|
||||
lib/decode4.f90
|
||||
lib/decoder.f90
|
||||
lib/decjt9.f90
|
||||
lib/deep4.f90
|
||||
|
@ -289,9 +292,11 @@ set (wsjt_FSRCS
|
|||
lib/encode4.f90
|
||||
lib/entail.f90
|
||||
lib/ephem.f90
|
||||
lib/extract.F90
|
||||
lib/extract.f90
|
||||
lib/extract4.f90
|
||||
lib/fano232.f90
|
||||
lib/fast9.f90
|
||||
lib/fast_decode.f90
|
||||
lib/fchisq.f90
|
||||
lib/fchisq65.f90
|
||||
lib/fftw3mod.f90
|
||||
|
@ -306,11 +311,14 @@ set (wsjt_FSRCS
|
|||
lib/flat2.f90
|
||||
lib/flat4.f90
|
||||
lib/flat65.f90
|
||||
lib/foldspec9f.f90
|
||||
lib/four2a.f90
|
||||
lib/fmtmsg.f90
|
||||
lib/gen4.f90
|
||||
lib/gen65.f90
|
||||
lib/gen9.f90
|
||||
lib/geniscat.f90
|
||||
lib/genmsk.f90
|
||||
lib/genwspr.f90
|
||||
lib/geodist.f90
|
||||
lib/getlags.f90
|
||||
|
@ -320,23 +328,28 @@ set (wsjt_FSRCS
|
|||
lib/grayline.f90
|
||||
lib/grid2deg.f90
|
||||
lib/hash.f90
|
||||
lib/hashing.f90
|
||||
lib/hspec.f90
|
||||
lib/image.f90
|
||||
lib/indexx.f90
|
||||
lib/interleave4.f90
|
||||
lib/interleave63.f90
|
||||
lib/interleave9.f90
|
||||
lib/inter_wspr.f90
|
||||
lib/iscat.f90
|
||||
lib/jplsubs.f
|
||||
lib/jt4.f90
|
||||
lib/jt4a.f90
|
||||
lib/jt65a.f90
|
||||
lib/jt9fano.f90
|
||||
lib/jtmsk.f90
|
||||
lib/libration.f90
|
||||
lib/lpf1.f90
|
||||
lib/mixlpf.f90
|
||||
lib/moondopjpl.f90
|
||||
lib/morse.f90
|
||||
lib/move.f90
|
||||
lib/mskdt.f90
|
||||
lib/options.f90
|
||||
lib/packjt.f90
|
||||
lib/pctile.f90
|
||||
|
@ -345,6 +358,7 @@ set (wsjt_FSRCS
|
|||
lib/polyfit.f90
|
||||
lib/prog_args.f90
|
||||
lib/ps4.f90
|
||||
lib/rectify_msk.f90
|
||||
lib/savec2.f90
|
||||
lib/sec_midn.f90
|
||||
lib/setup65.f90
|
||||
|
@ -354,22 +368,31 @@ set (wsjt_FSRCS
|
|||
lib/smo.f90
|
||||
lib/smo121.f90
|
||||
lib/softsym.f90
|
||||
lib/sort.f90
|
||||
lib/softsym9f.f90
|
||||
lib/shell.f90
|
||||
lib/spec9f.f90
|
||||
lib/stdmsg.f90
|
||||
lib/subtract65.f90
|
||||
lib/sun.f90
|
||||
lib/symspec.f90
|
||||
lib/symspec2.f90
|
||||
lib/symspec65.f90
|
||||
lib/sync4.f90
|
||||
lib/sync65.f90
|
||||
lib/sync9.f90
|
||||
lib/sync9f.f90
|
||||
lib/synciscat.f90
|
||||
lib/syncmsk.f90
|
||||
lib/timer.f90
|
||||
lib/timf2.f90
|
||||
lib/tweak1.f90
|
||||
lib/twkfreq.f90
|
||||
lib/twkfreq65.f90
|
||||
lib/wav11.f90
|
||||
lib/wav12.f90
|
||||
lib/wavhdr.f90
|
||||
lib/wsjt4.f90
|
||||
lib/xcor.f90
|
||||
lib/xcor4.f90
|
||||
lib/zplt.f90
|
||||
lib/wavhdr.f90
|
||||
|
@ -379,14 +402,17 @@ set (wsjt_FSRCS
|
|||
)
|
||||
|
||||
set (wsjt_CSRCS
|
||||
lib/decode_rs.c
|
||||
lib/encode_rs.c
|
||||
lib/sfrsd2/decode_rs.c
|
||||
lib/sfrsd2/encode_rs.c
|
||||
lib/sfrsd2/init_rs.c
|
||||
lib/sfrsd2/sfrsd2.c
|
||||
lib/gran.c
|
||||
lib/igray.c
|
||||
lib/init_rs.c
|
||||
lib/wsprd/nhash.c
|
||||
lib/tab.c
|
||||
lib/tmoonsub.c
|
||||
lib/usleep.c
|
||||
lib/vit213.c
|
||||
lib/wisdom.c
|
||||
lib/wrapkarn.c
|
||||
)
|
||||
|
@ -418,6 +444,7 @@ set (wsjtx_UISRCS
|
|||
about.ui
|
||||
astro.ui
|
||||
echograph.ui
|
||||
fastgraph.ui
|
||||
messageaveraging.ui
|
||||
widegraph.ui
|
||||
logqso.ui
|
||||
|
@ -515,11 +542,17 @@ endif (APPLE)
|
|||
|
||||
set_source_files_properties (${WSJTX_ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
|
||||
if (NOT WSJT_QDEBUG_IN_RELEASE)
|
||||
if (WSJT_QDEBUG_IN_RELEASE)
|
||||
# context info in Qt message handler in release configuration
|
||||
set_property (DIRECTORY APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_MESSAGELOGCONTEXT>
|
||||
)
|
||||
else (WSJT_QDEBUG_IN_RELEASE)
|
||||
# disable Qt trace and warning messages from release configurations
|
||||
set_property (DIRECTORY APPEND PROPERTY
|
||||
COMPILE_DEFINITIONS $<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG_OUTPUT;QT_NO_WARNING_OUTPUT>
|
||||
)
|
||||
endif (NOT WSJT_QDEBUG_IN_RELEASE)
|
||||
endif (WSJT_QDEBUG_IN_RELEASE)
|
||||
|
||||
set_property (SOURCE ${all_C_and_CXXSRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -include wsjtx_config.h")
|
||||
set_property (SOURCE ${all_C_and_CXXSRCS} APPEND PROPERTY OBJECT_DEPENDS wsjtx_config.h)
|
||||
|
|
|
@ -205,8 +205,8 @@ public:
|
|||
explicit FrequencyDialog (Modes * modes_model, QWidget * parent = nullptr)
|
||||
: QDialog {parent}
|
||||
{
|
||||
setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Frequency"));
|
||||
|
||||
setWindowTitle (QApplication::applicationName () + " - " +
|
||||
tr ("Add Frequency"));
|
||||
mode_combo_box_.setModel (modes_model);
|
||||
|
||||
auto form_layout = new QFormLayout ();
|
||||
|
@ -519,6 +519,8 @@ private:
|
|||
QColor color_NewCall_;
|
||||
QColor next_color_NewCall_;
|
||||
qint32 id_interval_;
|
||||
qint32 ntrials_;
|
||||
qint32 aggressive_;
|
||||
bool id_after_73_;
|
||||
bool tx_QSY_allowed_;
|
||||
bool spot_to_psk_reporter_;
|
||||
|
@ -537,6 +539,13 @@ private:
|
|||
bool TX_messages_;
|
||||
bool enable_VHF_features_;
|
||||
bool decode_at_52s_;
|
||||
bool twoPass_;
|
||||
bool MyDx_;
|
||||
bool CQMyN_;
|
||||
bool NDxG_;
|
||||
bool NN_;
|
||||
bool EMEonly_;
|
||||
bool offsetRxFreq_;
|
||||
QString udp_server_name_;
|
||||
port_type udp_server_port_;
|
||||
bool accept_udp_requests_;
|
||||
|
@ -589,6 +598,8 @@ QColor Configuration::color_DXCC () const {return m_->color_DXCC_;}
|
|||
QColor Configuration::color_NewCall () const {return m_->color_NewCall_;}
|
||||
QFont Configuration::decoded_text_font () const {return m_->decoded_text_font_;}
|
||||
qint32 Configuration::id_interval () const {return m_->id_interval_;}
|
||||
qint32 Configuration::ntrials() const {return m_->ntrials_;}
|
||||
qint32 Configuration::aggressive() const {return m_->aggressive_;}
|
||||
bool Configuration::id_after_73 () const {return m_->id_after_73_;}
|
||||
bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;}
|
||||
bool Configuration::spot_to_psk_reporter () const {return m_->spot_to_psk_reporter_;}
|
||||
|
@ -607,6 +618,13 @@ bool Configuration::watchdog () const {return m_->watchdog_;}
|
|||
bool Configuration::TX_messages () const {return m_->TX_messages_;}
|
||||
bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features_;}
|
||||
bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;}
|
||||
bool Configuration::twoPass() const {return m_->twoPass_;}
|
||||
bool Configuration::MyDx() const {return m_->MyDx_;}
|
||||
bool Configuration::CQMyN() const {return m_->CQMyN_;}
|
||||
bool Configuration::NDxG() const {return m_->NDxG_;}
|
||||
bool Configuration::NN() const {return m_->NN_;}
|
||||
bool Configuration::EMEonly() const {return m_->EMEonly_;}
|
||||
bool Configuration::offsetRxFreq () const {return m_->offsetRxFreq_;}
|
||||
bool Configuration::split_mode () const
|
||||
{
|
||||
return !m_->rig_is_dummy_ and
|
||||
|
@ -1004,6 +1022,8 @@ void Configuration::impl::initialize_models ()
|
|||
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
|
||||
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
|
||||
ui_->CW_id_interval_spin_box->setValue (id_interval_);
|
||||
ui_->sbNtrials->setValue (ntrials_);
|
||||
ui_->sbAggressive->setValue (aggressive_);
|
||||
ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true);
|
||||
ui_->save_path_display_label->setText (save_directory_.absolutePath ());
|
||||
ui_->azel_path_display_label->setText (azel_directory_.absolutePath ());
|
||||
|
@ -1025,6 +1045,13 @@ void Configuration::impl::initialize_models ()
|
|||
ui_->TX_messages_check_box->setChecked (TX_messages_);
|
||||
ui_->enable_VHF_features_check_box->setChecked(enable_VHF_features_);
|
||||
ui_->decode_at_52s_check_box->setChecked(decode_at_52s_);
|
||||
ui_->cbTwoPass->setChecked(twoPass_);
|
||||
ui_->cbMyDx->setChecked(MyDx_);
|
||||
ui_->cbCQMyN->setChecked(CQMyN_);
|
||||
ui_->cbNDxG->setChecked(NDxG_);
|
||||
ui_->cbNN->setChecked(NN_);
|
||||
ui_->cbEMEonly->setChecked(EMEonly_);
|
||||
ui_->offset_Rx_freq_check_box->setChecked(offsetRxFreq_);
|
||||
ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_);
|
||||
ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
|
||||
ui_->TX_mode_button_group->button (data_mode_)->setChecked (true);
|
||||
|
@ -1126,6 +1153,8 @@ void Configuration::impl::read_settings ()
|
|||
}
|
||||
|
||||
id_interval_ = settings_->value ("IDint", 0).toInt ();
|
||||
ntrials_ = settings_->value ("nTrials", 6).toInt ();
|
||||
aggressive_ = settings_->value ("Aggressive", 0).toInt ();
|
||||
|
||||
save_directory_ = settings_->value ("SaveDir", default_save_directory_.absolutePath ()).toString ();
|
||||
azel_directory_ = settings_->value ("AzElDir", default_azel_directory_.absolutePath ()).toString ();
|
||||
|
@ -1185,12 +1214,15 @@ void Configuration::impl::read_settings ()
|
|||
// retrieve audio channel info
|
||||
audio_input_channel_ = AudioDevice::fromString (settings_->value ("AudioInputChannel", "Mono").toString ());
|
||||
audio_output_channel_ = AudioDevice::fromString (settings_->value ("AudioOutputChannel", "Mono").toString ());
|
||||
|
||||
type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> ();
|
||||
|
||||
monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
|
||||
monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
|
||||
spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool ();
|
||||
id_after_73_ = settings_->value ("After73", false).toBool ();
|
||||
tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
|
||||
|
||||
macros_.setStringList (settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList ());
|
||||
|
||||
if (settings_->contains ("FrequenciesForModes"))
|
||||
|
@ -1241,6 +1273,13 @@ void Configuration::impl::read_settings ()
|
|||
TX_messages_ = settings_->value ("Tx2QSO", true).toBool ();
|
||||
enable_VHF_features_ = settings_->value("VHFUHF",false).toBool ();
|
||||
decode_at_52s_ = settings_->value("Decode52",false).toBool ();
|
||||
twoPass_ = settings_->value("TwoPass",true).toBool ();
|
||||
MyDx_ = settings_->value("MyDx",false).toBool ();
|
||||
CQMyN_ = settings_->value("CQMyN",false).toBool ();
|
||||
NDxG_ = settings_->value("NDxG",false).toBool ();
|
||||
NN_ = settings_->value("NN",false).toBool ();
|
||||
EMEonly_ = settings_->value("EMEonly",false).toBool ();
|
||||
offsetRxFreq_ = settings_->value("OffsetRx",false).toBool();
|
||||
rig_params_.poll_interval = settings_->value ("Polling", 0).toInt ();
|
||||
rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
|
||||
udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString ();
|
||||
|
@ -1266,6 +1305,8 @@ void Configuration::impl::write_settings ()
|
|||
settings_->setValue ("Font", font_.toString ());
|
||||
settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ());
|
||||
settings_->setValue ("IDint", id_interval_);
|
||||
settings_->setValue ("nTrials", ntrials_);
|
||||
settings_->setValue ("Aggressive", aggressive_);
|
||||
settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.ptt_type));
|
||||
settings_->setValue ("PTTport", rig_params_.ptt_port);
|
||||
settings_->setValue ("SaveDir", save_directory_.absolutePath ());
|
||||
|
@ -1328,6 +1369,13 @@ void Configuration::impl::write_settings ()
|
|||
settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode));
|
||||
settings_->setValue ("VHFUHF", enable_VHF_features_);
|
||||
settings_->setValue ("Decode52", decode_at_52s_);
|
||||
settings_->setValue ("TwoPass", twoPass_);
|
||||
settings_->setValue ("MyDx", MyDx_);
|
||||
settings_->setValue ("CQMyN", CQMyN_);
|
||||
settings_->setValue ("NDxG", NDxG_);
|
||||
settings_->setValue ("NN", NN_);
|
||||
settings_->setValue ("EMEonly", EMEonly_);
|
||||
settings_->setValue("OffsetRx",offsetRxFreq_);
|
||||
settings_->setValue ("UDPServer", udp_server_name_);
|
||||
settings_->setValue ("UDPServerPort", udp_server_port_);
|
||||
settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
|
||||
|
@ -1665,6 +1713,8 @@ void Configuration::impl::accept ()
|
|||
my_grid_ = ui_->grid_line_edit->text ();
|
||||
spot_to_psk_reporter_ = ui_->psk_reporter_check_box->isChecked ();
|
||||
id_interval_ = ui_->CW_id_interval_spin_box->value ();
|
||||
ntrials_ = ui_->sbNtrials->value ();
|
||||
aggressive_ = ui_->sbAggressive->value ();
|
||||
id_after_73_ = ui_->CW_id_after_73_check_box->isChecked ();
|
||||
tx_QSY_allowed_ = ui_->tx_QSY_check_box->isChecked ();
|
||||
monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked ();
|
||||
|
@ -1686,6 +1736,14 @@ void Configuration::impl::accept ()
|
|||
azel_directory_ = ui_->azel_path_display_label->text ();
|
||||
enable_VHF_features_ = ui_->enable_VHF_features_check_box->isChecked ();
|
||||
decode_at_52s_ = ui_->decode_at_52s_check_box->isChecked ();
|
||||
twoPass_ = ui_->cbTwoPass->isChecked ();
|
||||
MyDx_ = ui_->cbMyDx->isChecked ();
|
||||
CQMyN_ = ui_->cbCQMyN->isChecked ();
|
||||
NDxG_ = ui_->cbNDxG->isChecked ();
|
||||
NN_ = ui_->cbNN->isChecked ();
|
||||
EMEonly_ = ui_->cbEMEonly->isChecked ();
|
||||
|
||||
offsetRxFreq_ = ui_->offset_Rx_freq_check_box->isChecked();
|
||||
frequency_calibration_intercept_ = ui_->calibration_intercept_spin_box->value ();
|
||||
frequency_calibration_slope_ppm_ = ui_->calibration_slope_ppm_spin_box->value ();
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
QString my_grid () const;
|
||||
QFont decoded_text_font () const;
|
||||
qint32 id_interval () const;
|
||||
qint32 ntrials() const;
|
||||
qint32 aggressive() const;
|
||||
bool id_after_73 () const;
|
||||
bool tx_QSY_allowed () const;
|
||||
bool spot_to_psk_reporter () const;
|
||||
|
@ -110,6 +112,13 @@ public:
|
|||
bool split_mode () const;
|
||||
bool enable_VHF_features () const;
|
||||
bool decode_at_52s () const;
|
||||
bool twoPass() const;
|
||||
bool MyDx() const;
|
||||
bool CQMyN() const;
|
||||
bool NDxG() const;
|
||||
bool NN() const;
|
||||
bool EMEonly() const;
|
||||
bool offsetRxFreq () const;
|
||||
bool post_decodes () const;
|
||||
QString udp_server_name () const;
|
||||
port_type udp_server_port () const;
|
||||
|
|
328
Configuration.ui
328
Configuration.ui
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>508</width>
|
||||
<height>471</height>
|
||||
<width>535</width>
|
||||
<height>493</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -293,7 +293,7 @@ text message.</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item row="6" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="CW_id_after_73_check_box">
|
||||
|
@ -386,6 +386,13 @@ quiet period when decoding is done.</string>
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="offset_Rx_freq_check_box">
|
||||
<property name="text">
|
||||
<string>Rx frequency offset with "CQ nnn ..."</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -1180,6 +1187,26 @@ radio interface behave as expected.</string>
|
|||
<string>Audio interface settings</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="save_path_group_box">
|
||||
<property name="title">
|
||||
|
@ -1392,26 +1419,6 @@ both here.</string>
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tx_macros_tab">
|
||||
|
@ -2116,6 +2123,269 @@ Right click for insert and delete options.</string>
|
|||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Advanced</string>
|
||||
</attribute>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>211</width>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>User-selectable parameters for JT65 decoding.</p></body></html></string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>JT65 decoding parameters</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>270</y>
|
||||
<width>131</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aggressive decoding level:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>191</width>
|
||||
<height>222</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Random erasure patterns:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sbNtrials">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Maximum number of erasure patterns for stochastic soft-decision Reed Solomon decoder is 10^(n/2).</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbTwoPass">
|
||||
<property name="text">
|
||||
<string>Two-pass decoding</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>141</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>183</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Experience-based decoding</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
<width>152</width>
|
||||
<height>111</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbMyDx">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Test codewords corresponding to messages of the form &quot;MyCall DxCall Dxgrid&quot;, &quot;MyCall DxCall rpt&quot;. &quot;MyCall DxCall RRR&quot;. and &quot;MyCall DxCall 73&quot;.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>MyCall DxCall rpt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="cbCQMyN">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Test codewords corresponding to messages of the form &quot;CQ Call Grid&quot; and &quot;MyCall Call Grid&quot; for all Call/Grid combinations selected from the list of known calls.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>(CQ, MyCall) x N</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="cbNDxG">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Test codewords corresponding to messages of the form &quot;Call DxCall DxGrid OOO&quot; for all Call/Grid combinations selected from the list of known calls.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N x (DxCall Grid OOO)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="cbNN">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Test codewords corresponding to messages of the form &quot;Call1 Call2 Grid2&quot;for all Call/Grid combinations selected from the list of known calls.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>N x N</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="cbEMEonly">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Select Call/Grid combinations from list of known calls only if marked as active on EME.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>EME calls only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Aggressive decoding level:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="sbAggressive">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Higher levels will increase the probability of decoding, but will also increase probability of a false decode.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -2283,12 +2553,12 @@ soundcard changes</string>
|
|||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="CAT_data_bits_button_group"/>
|
||||
<buttongroup name="split_mode_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="CAT_handshake_button_group"/>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
@ -1,27 +1,43 @@
|
|||
#include "LettersSpinBox.hpp"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <QDebug>
|
||||
#include "moc_LettersSpinBox.cpp"
|
||||
|
||||
QString LettersSpinBox::textFromValue (int value) const
|
||||
{
|
||||
QString text;
|
||||
do
|
||||
{
|
||||
|
||||
if(value < 10) {
|
||||
do {
|
||||
auto digit = value % 26;
|
||||
value /= 26;
|
||||
text = QChar {lowercase_ ? 'a' + digit : 'A' + digit} + text;
|
||||
} while (value);
|
||||
} else {
|
||||
if(value==11) text="5";
|
||||
if(value==12) text="10";
|
||||
if(value==13) text="15";
|
||||
if(value==14) text="30";
|
||||
// if(value==15) text="60";
|
||||
|
||||
if(value==21) text="10";
|
||||
if(value==22) text="20";
|
||||
if(value==23) text="50";
|
||||
if(value==24) text="100";
|
||||
if(value==25) text="200";
|
||||
if(value==26) text="500";
|
||||
if(value==27) text="1000";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/*
|
||||
int LettersSpinBox::valueFromText (QString const& text) const
|
||||
{
|
||||
int value {0};
|
||||
for (int index = text.size (); index > 0; --index)
|
||||
{
|
||||
for (int index = text.size (); index > 0; --index) {
|
||||
value = value * 26 + text[index - 1].toLatin1 () - (lowercase_ ? 'a' : 'A');
|
||||
};
|
||||
}
|
||||
return value;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
}
|
||||
|
||||
QString textFromValue (int) const override;
|
||||
int valueFromText (QString const&) const override;
|
||||
// int valueFromText (QString const&) const override;
|
||||
|
||||
private:
|
||||
bool lowercase_;
|
||||
|
|
|
@ -20,6 +20,8 @@ public:
|
|||
JT4,
|
||||
WSPR,
|
||||
Echo,
|
||||
ISCAT,
|
||||
JTMSK,
|
||||
};
|
||||
|
||||
explicit Modes (QObject * parent = nullptr);
|
||||
|
@ -30,8 +32,7 @@ public:
|
|||
// Implement the QAbstractListModel interface
|
||||
int rowCount (QModelIndex const& parent = QModelIndex {}) const override
|
||||
{
|
||||
return parent.isValid () ? 0 : 6; // the number of modes in the
|
||||
// Mode enumeration class
|
||||
return parent.isValid () ? 0 : 8; // Number of modes in Mode enumeration class
|
||||
}
|
||||
QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
|
||||
|
|
|
@ -44,7 +44,7 @@ Modulator::Modulator (unsigned frameRate, unsigned periodLengthInSeconds,
|
|||
void Modulator::start (unsigned symbolsLength, double framesPerSymbol,
|
||||
double frequency, double toneSpacing,
|
||||
SoundOutput * stream, Channel channel,
|
||||
bool synchronize, double dBSNR)
|
||||
bool synchronize, bool fastMode, double dBSNR, int TRperiod)
|
||||
{
|
||||
Q_ASSERT (stream);
|
||||
|
||||
|
@ -66,6 +66,8 @@ void Modulator::start (unsigned symbolsLength, double framesPerSymbol,
|
|||
m_frequency = frequency;
|
||||
m_amp = std::numeric_limits<qint16>::max ();
|
||||
m_toneSpacing = toneSpacing;
|
||||
m_bFastMode=fastMode;
|
||||
m_TRperiod=TRperiod;
|
||||
|
||||
// noise generator parameters
|
||||
if (m_addNoise) {
|
||||
|
@ -76,14 +78,14 @@ void Modulator::start (unsigned symbolsLength, double framesPerSymbol,
|
|||
|
||||
unsigned mstr = ms0 % (1000 * m_period); // ms in period
|
||||
m_ic = (mstr / 1000) * m_frameRate; // we start exactly N seconds
|
||||
if(m_bFastMode) m_ic=0;
|
||||
// into period where N is the next whole second
|
||||
|
||||
m_silentFrames = 0;
|
||||
// calculate number of silent frames to send
|
||||
if (synchronize && !m_tuning) {
|
||||
if (synchronize && !m_tuning && !m_bFastMode) {
|
||||
m_silentFrames = m_ic + m_frameRate - (mstr * m_frameRate / 1000);
|
||||
}
|
||||
|
||||
initialize (QIODevice::ReadOnly, channel);
|
||||
Q_EMIT stateChanged ((m_state = (synchronize && m_silentFrames) ?
|
||||
Synchronizing : Active));
|
||||
|
@ -158,7 +160,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
|||
|
||||
case Active:
|
||||
{
|
||||
unsigned isym (m_tuning ? 0 : m_ic / (4.0 * m_nsps)); // Actual fsample=48000
|
||||
unsigned int isym=0;
|
||||
if(!m_tuning) isym=m_ic/(4.0*m_nsps); // Actual fsample=48000
|
||||
if (isym >= m_symbolsLength && icw[0] > 0) { // start CW condition
|
||||
// Output the CW ID
|
||||
m_dphi = m_twoPi * m_frequency / m_frameRate;
|
||||
|
@ -209,11 +212,24 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
|||
|
||||
double const baud (12000.0 / m_nsps);
|
||||
// fade out parameters (no fade out for tuning)
|
||||
unsigned const i0 = m_tuning ? 9999 * m_nsps : (m_symbolsLength - 0.017) * 4.0 * m_nsps;
|
||||
unsigned const i1 = m_tuning ? 9999 * m_nsps : m_symbolsLength * 4.0 * m_nsps;
|
||||
unsigned int i0,i1;
|
||||
if(m_tuning) {
|
||||
i0=9999*m_nsps;
|
||||
i1=9999*m_nsps;
|
||||
} else {
|
||||
i0=(m_symbolsLength - 0.017) * 4.0 * m_nsps;
|
||||
i1= m_symbolsLength * 4.0 * m_nsps;
|
||||
}
|
||||
if(m_bFastMode) {
|
||||
i1=m_TRperiod*48000 - 24000;
|
||||
i0=i1-816;
|
||||
}
|
||||
|
||||
|
||||
for (unsigned i = 0; i < numFrames && m_ic <= i1; ++i) {
|
||||
isym = m_tuning ? 0 : m_ic / (4.0 * m_nsps); //Actual fsample=48000
|
||||
isym=0;
|
||||
if(!m_tuning) isym=m_ic / (4.0 * m_nsps); //Actual fsample=48000
|
||||
if(m_bFastMode) isym=isym%m_symbolsLength;
|
||||
if (isym != m_isym0 || m_frequency != m_frequency0) {
|
||||
if(itone[0]>=100) {
|
||||
toneFrequency0=itone[0];
|
||||
|
@ -224,6 +240,8 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
|
|||
toneFrequency0=m_frequency + itone[isym]*m_toneSpacing;
|
||||
}
|
||||
}
|
||||
// qDebug() << "B" << m_bFastMode << m_ic << numFrames << isym << itone[isym]
|
||||
// << toneFrequency0 << m_nsps;
|
||||
m_dphi = m_twoPi * toneFrequency0 / m_frameRate;
|
||||
m_isym0 = isym;
|
||||
m_frequency0 = m_frequency; //???
|
||||
|
|
|
@ -33,7 +33,10 @@ public:
|
|||
void setSpread(double s) {m_fSpread=s;}
|
||||
void setPeriod(unsigned p) {m_period=p;}
|
||||
|
||||
Q_SLOT void start (unsigned symbolsLength, double framesPerSymbol, double frequency, double toneSpacing, SoundOutput *, Channel = Mono, bool synchronize = true, double dBSNR = 99.);
|
||||
Q_SLOT void start (unsigned symbolsLength, double framesPerSymbol, double frequency,
|
||||
double toneSpacing, SoundOutput *, Channel = Mono,
|
||||
bool synchronize = true, bool fastMode = false,
|
||||
double dBSNR = 99., int TRperiod=60);
|
||||
Q_SLOT void stop (bool quick = false);
|
||||
Q_SLOT void tune (bool newState = true);
|
||||
Q_SLOT void setFrequency (double newFrequency) {m_frequency = newFrequency;}
|
||||
|
@ -70,6 +73,7 @@ private:
|
|||
|
||||
qint64 m_silentFrames;
|
||||
qint32 m_itone0;
|
||||
qint32 m_TRperiod;
|
||||
qint16 m_ramp;
|
||||
|
||||
unsigned m_frameRate;
|
||||
|
@ -78,6 +82,7 @@ private:
|
|||
|
||||
bool volatile m_tuning;
|
||||
bool m_addNoise;
|
||||
bool m_bFastMode;
|
||||
|
||||
bool m_cwLevel;
|
||||
unsigned m_ic;
|
||||
|
|
|
@ -106,7 +106,7 @@ void TraceFile::impl::message_handler (QtMsgType type, QMessageLogContext const&
|
|||
QMutexLocker guard (&lock);
|
||||
Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to");
|
||||
*current_stream_
|
||||
<< QDateTime::currentDateTimeUtc ().toString ()
|
||||
<< QDateTime::currentDateTimeUtc ().toString ("yyyy-MM-ddTHH:mm:ss.zzzZ")
|
||||
<< '(' << context.file << ':' << context.line /* << ", " << context.function */ << ')'
|
||||
<< severity << ": " << msg.trimmed () << endl;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Version number components
|
||||
set (WSJTX_VERSION_MAJOR 1)
|
||||
set (WSJTX_VERSION_MINOR 6)
|
||||
set (WSJTX_VERSION_PATCH 0)
|
||||
set (WSJTX_VERSION_PATCH 1)
|
||||
set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions
|
||||
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
|
||||
|
|
|
@ -23,8 +23,8 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
|
|||
"Amateur Radio communication. <br><br>"
|
||||
"© 2001-2015 by Joe Taylor, K1JT, with grateful <br>"
|
||||
"acknowledgment for contributions from AC6SL, AE4JY, <br>"
|
||||
"DJ0OT, G4KLA, G4WJS, K3WYC, K9AN, KA6MAL, KA9Q, <br>"
|
||||
"KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR, <br>"
|
||||
"DJ0OT, G4KLA, G4WJS, IW3RAB, K3WYC, K9AN, KA6MAL, <br>"
|
||||
"KA9Q, KB1ZMX, KD6EKQ, KI7MT, KK1D, ND0B, PY2SDR, <br>"
|
||||
"VK3ACF, VK4BDJ, W4TI, W4TV, and W9MDB.<br>");
|
||||
}
|
||||
|
||||
|
|
11
astro.cpp
11
astro.cpp
|
@ -27,6 +27,7 @@ Astro::Astro(QSettings * settings, Configuration const * configuration, QWidget
|
|||
, ui_ {new Ui::Astro}
|
||||
, m_bRxAudioTrack {false}
|
||||
, m_bTxAudioTrack {false}
|
||||
, m_bTrackVFO {true}
|
||||
, m_DopplerMethod {0}
|
||||
, m_kHz {0}
|
||||
, m_Hz {0}
|
||||
|
@ -228,3 +229,13 @@ bool Astro::doppler_tracking () const
|
|||
{
|
||||
return ui_->cbDopplerTracking->isChecked ();
|
||||
}
|
||||
|
||||
bool Astro::trackVFO()
|
||||
{
|
||||
return m_bTrackVFO;
|
||||
}
|
||||
|
||||
void Astro::on_cbTrackVFO_toggled(bool b)
|
||||
{
|
||||
m_bTrackVFO=b;
|
||||
}
|
||||
|
|
3
astro.h
3
astro.h
|
@ -25,6 +25,7 @@ public:
|
|||
FrequencyDelta astroUpdate(QDateTime const& t, QString const& mygrid, QString const& hisgrid, Frequency frequency,
|
||||
bool dx_is_self, bool bTx);
|
||||
bool doppler_tracking () const;
|
||||
bool trackVFO();
|
||||
Q_SIGNAL void doppler_tracking_toggled (bool);
|
||||
|
||||
protected:
|
||||
|
@ -40,6 +41,7 @@ private slots:
|
|||
void on_cbTxAudioTrack_toggled(bool b);
|
||||
void on_kHzSpinBox_valueChanged(int n);
|
||||
void on_HzSpinBox_valueChanged(int n);
|
||||
void on_cbTrackVFO_toggled(bool b);
|
||||
|
||||
private:
|
||||
void read_settings ();
|
||||
|
@ -50,6 +52,7 @@ private:
|
|||
Ui::Astro * ui_;
|
||||
bool m_bRxAudioTrack;
|
||||
bool m_bTxAudioTrack;
|
||||
bool m_bTrackVFO;
|
||||
|
||||
qint32 m_DopplerMethod;
|
||||
qint32 m_kHz;
|
||||
|
|
30
astro.ui
30
astro.ui
|
@ -141,16 +141,32 @@
|
|||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Tx audio tracking</string>
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbTxAudioTrack">
|
||||
<widget class="QCheckBox" name="cbTrackVFO">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
<string>Track VFOs</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbTxAudioTrack">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Track Tx audio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -162,6 +178,12 @@
|
|||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -7,6 +7,7 @@ QString DecodedText::CQersCall()
|
|||
// extract the CQer's call TODO: does this work with all call formats?
|
||||
int s1 {0};
|
||||
int position;
|
||||
QString t=_string;
|
||||
if ((position = _string.indexOf (" CQ DX ")) >= 0)
|
||||
{
|
||||
s1 = 7 + position;
|
||||
|
@ -14,6 +15,7 @@ QString DecodedText::CQersCall()
|
|||
else if ((position = _string.indexOf (" CQ ")) >= 0)
|
||||
{
|
||||
s1 = 4 + position;
|
||||
if(_string.mid(s1,3).toInt() > 0 and _string.mid(s1,3).toInt() <= 999) s1 += 4;
|
||||
}
|
||||
else if ((position = _string.indexOf (" DE ")) >= 0)
|
||||
{
|
||||
|
@ -51,7 +53,8 @@ int DecodedText::frequencyOffset()
|
|||
|
||||
int DecodedText::snr()
|
||||
{
|
||||
return _string.mid(column_snr,3).toInt();
|
||||
int i1=_string.indexOf(" ")+1;
|
||||
return _string.mid(i1,3).toInt();
|
||||
}
|
||||
|
||||
float DecodedText::dt()
|
||||
|
|
|
@ -88,9 +88,12 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
|
|||
|
||||
// the decoder (seems) to always generate 40 chars. For a normal CQ call, the last five are spaces
|
||||
// TODO this magic 36 characters is also referenced in MainWindow::doubleClickOnCall()
|
||||
int s3 = t1.indexOf(" ",35);
|
||||
if (s3 < 35)
|
||||
s3 = 35; // we always want at least the characters to position 35
|
||||
int nmin=35;
|
||||
int i=t1.indexOf(" CQ ");
|
||||
int k=t1.string().mid(i+4,3).toInt();
|
||||
if(k>0 and k<999) nmin += 4;
|
||||
int s3 = t1.indexOf(" ",nmin);
|
||||
if (s3 < nmin) s3 = nmin; // always want at least the characters to position 35
|
||||
s3 += 1; // convert the index into a character count
|
||||
t1 = t1.left(s3); // reduce trailing white space
|
||||
charsAvail -= s3;
|
||||
|
@ -166,15 +169,28 @@ void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
|
|||
|
||||
|
||||
void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
|
||||
QColor color_TxMsg)
|
||||
QColor color_TxMsg, bool bFastMode)
|
||||
{
|
||||
QString bg=color_TxMsg.name();
|
||||
QString t1=" @ ";
|
||||
if(modeTx=="JT65") t1=" # ";
|
||||
if(modeTx=="JTMSK") t1=" & ";
|
||||
QString t2;
|
||||
t2.sprintf("%4d",txFreq);
|
||||
QString t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
|
||||
" Tx " + t2 + t1 + text; // The position of the 'Tx' is searched for in DecodedText and in MainWindow. Not sure if thats required anymore? VK3ACF
|
||||
|
||||
QString t;
|
||||
if(bFastMode) {
|
||||
t = QDateTime::currentDateTimeUtc().toString("hhmmss") + \
|
||||
" Tx " + t2 + t1 + text;
|
||||
} else {
|
||||
t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
|
||||
" Tx " + t2 + t1 + text;
|
||||
}
|
||||
appendText(t,bg);
|
||||
}
|
||||
|
||||
void DisplayText::displayQSY(QString text)
|
||||
{
|
||||
QString t = QDateTime::currentDateTimeUtc().toString("hhmmss") + " " + text;
|
||||
QString bg="hot pink";
|
||||
appendText(t,bg);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ public:
|
|||
LogBook logBook, QColor color_CQ, QColor color_MyCall,
|
||||
QColor color_DXCC, QColor color_NewCall);
|
||||
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
|
||||
QColor color_TxMsg);
|
||||
QColor color_TxMsg, bool bFastMode);
|
||||
void displayQSY(QString text);
|
||||
|
||||
signals:
|
||||
void selectCallsign(bool shift, bool ctrl);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "echograph.h"
|
||||
#include "commons.h"
|
||||
#include <QSettings>
|
||||
#include <QApplication>
|
||||
#include "echoplot.h"
|
||||
#include "ui_echograph.h"
|
||||
#include "moc_echograph.cpp"
|
||||
|
@ -13,6 +14,7 @@ EchoGraph::EchoGraph(QSettings * settings, QWidget *parent) :
|
|||
ui(new Ui::EchoGraph)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle (QApplication::applicationName () + " - " + tr ("Echo Graph"));
|
||||
installEventFilter(parent); //Installing the filter
|
||||
ui->echoPlot->setCursor(Qt::CrossCursor);
|
||||
setMaximumWidth(2048);
|
||||
|
@ -34,9 +36,10 @@ EchoGraph::EchoGraph(QSettings * settings, QWidget *parent) :
|
|||
ui->binsPerPixelSpinBox->setValue(n);
|
||||
ui->echoPlot->m_blue=m_settings->value("BlueCurve",false).toBool();
|
||||
ui->cbBlue->setChecked(ui->echoPlot->m_blue);
|
||||
m_nColor=m_settings->value("EchoColors",0).toInt();
|
||||
m_settings->endGroup();
|
||||
|
||||
ui->cbBlue->setVisible(false); //Not using "blue" (for now, at least)
|
||||
ui->echoPlot->setColors(m_nColor);
|
||||
}
|
||||
|
||||
EchoGraph::~EchoGraph()
|
||||
|
@ -61,6 +64,7 @@ void EchoGraph::saveSettings()
|
|||
m_settings->setValue("Smooth",ui->echoPlot->m_smooth);
|
||||
m_settings->setValue("EchoBPP",ui->echoPlot->m_binsPerPixel);
|
||||
m_settings->setValue("BlueCurve",ui->echoPlot->m_blue);
|
||||
m_settings->setValue("EchoColors",m_nColor);
|
||||
m_settings->endGroup();
|
||||
}
|
||||
|
||||
|
@ -100,3 +104,9 @@ void EchoGraph::on_binsPerPixelSpinBox_valueChanged(int n)
|
|||
ui->echoPlot->DrawOverlay();
|
||||
ui->echoPlot->draw();
|
||||
}
|
||||
|
||||
void EchoGraph::on_pbColors_clicked()
|
||||
{
|
||||
m_nColor = (m_nColor+1) % 6;
|
||||
ui->echoPlot->setColors(m_nColor);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,11 @@ private slots:
|
|||
void on_zeroSlider_valueChanged(int value);
|
||||
void on_binsPerPixelSpinBox_valueChanged(int n);
|
||||
|
||||
void on_pbColors_clicked();
|
||||
|
||||
private:
|
||||
QSettings * m_settings;
|
||||
qint32 m_nColor;
|
||||
|
||||
Ui::EchoGraph *ui;
|
||||
};
|
||||
|
|
13
echograph.ui
13
echograph.ui
|
@ -235,6 +235,19 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbColors">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Colors</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
|
|
33
echoplot.cpp
33
echoplot.cpp
|
@ -57,8 +57,6 @@ void EPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
|
|||
m_2DPixmap = QPixmap(m_Size.width(), m_h2);
|
||||
m_2DPixmap.fill(Qt::black);
|
||||
m_OverlayPixmap = QPixmap(m_Size.width(), m_h2);
|
||||
m_OverlayPixmap.fill(Qt::black);
|
||||
m_2DPixmap.fill(Qt::black);
|
||||
m_ScalePixmap = QPixmap(m_w,30);
|
||||
m_ScalePixmap.fill(Qt::white);
|
||||
m_fSpan=m_w*m_fftBinWidth*m_binsPerPixel;
|
||||
|
@ -83,15 +81,24 @@ void EPlotter::draw() //draw()
|
|||
int i,j,y;
|
||||
float blue[4096],red[4096];
|
||||
float gain = pow(10.0,(m_plotGain/20.0));
|
||||
QPen penBlue(QColor(0,255,255),1);
|
||||
QPen penRed(Qt::red,1);
|
||||
QPen penRed2(Qt::red,2);
|
||||
QPen penBlack(Qt::black,1);
|
||||
QPen penBlack2(Qt::black,2);
|
||||
|
||||
if(m_2DPixmap.size().width()==0) return;
|
||||
QPainter painter2D(&m_2DPixmap);
|
||||
QRect tmp(0,0,m_w,m_h2);
|
||||
if(m_nColor < 2) {
|
||||
painter2D.fillRect(tmp,Qt::black);
|
||||
} else {
|
||||
painter2D.fillRect(tmp,Qt::white);
|
||||
painter2D.setPen(penBlack);
|
||||
painter2D.drawLine(0,0,m_w,0);
|
||||
}
|
||||
|
||||
QPoint LineBuf[MAX_SCREENSIZE];
|
||||
QPen penBlue(QColor(0,255,255),1);
|
||||
QPen penRed(Qt::red,1);
|
||||
|
||||
if(m_binsPerPixel==0) m_binsPerPixel=1;
|
||||
j=0;
|
||||
|
@ -125,8 +132,15 @@ void EPlotter::draw() //draw()
|
|||
}
|
||||
painter2D.drawPolyline(LineBuf,j);
|
||||
}
|
||||
switch (m_nColor) {
|
||||
case 0: painter2D.setPen(penRed); break;
|
||||
case 1: painter2D.setPen(penRed2); break;
|
||||
case 2: painter2D.setPen(penRed); break;
|
||||
case 3: painter2D.setPen(penRed2); break;
|
||||
case 4: painter2D.setPen(penBlack); break;
|
||||
case 5: painter2D.setPen(penBlack2); break;
|
||||
}
|
||||
|
||||
painter2D.setPen(penRed);
|
||||
j=0;
|
||||
for(int i=0; i<m_w; i++) {
|
||||
y = 0.9*m_h2 - gain*(m_h/10.0)*(red[i0+i]-1.0) - 0.01*m_h2*m_plotZero;
|
||||
|
@ -234,11 +248,12 @@ void EPlotter::DrawOverlay() //DrawOverlay()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
QPen pen1(Qt::red, 3); //Mark Tx Freq with red tick
|
||||
painter0.setPen(pen1);
|
||||
x = XfromFreq(m_TxFreq);
|
||||
painter0.drawLine(x,17,x,30);
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
void EPlotter::MakeFrequencyStrs() //MakeFrequencyStrs
|
||||
|
@ -298,6 +313,12 @@ int EPlotter::getSmooth() //getSmooth()
|
|||
return m_smooth;
|
||||
}
|
||||
|
||||
void EPlotter::setColors(qint32 n) //setSmooth()
|
||||
{
|
||||
m_nColor=n;
|
||||
draw();
|
||||
}
|
||||
|
||||
int EPlotter::plotWidth(){return m_2DPixmap.width();}
|
||||
|
||||
void EPlotter::UpdateOverlay() {DrawOverlay();}
|
||||
|
|
|
@ -24,7 +24,6 @@ public:
|
|||
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const;
|
||||
QColor m_ColorTbl[256];
|
||||
float m_fSpan;
|
||||
qint32 m_TxFreq;
|
||||
qint32 m_w;
|
||||
|
@ -32,6 +31,7 @@ public:
|
|||
qint32 m_plotGain;
|
||||
qint32 m_smooth;
|
||||
qint32 m_binsPerPixel;
|
||||
qint32 m_nColor;
|
||||
bool m_blue;
|
||||
|
||||
void draw(); //Update the Echo plot
|
||||
|
@ -45,6 +45,7 @@ public:
|
|||
void DrawOverlay();
|
||||
void setSmooth(int n);
|
||||
int getSmooth();
|
||||
void setColors(qint32 n);
|
||||
|
||||
// void SetPercent2DScreen(int percent){m_Percent2DScreen=percent;}
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
#include "fastgraph.h"
|
||||
#include "commons.h"
|
||||
#include <QSettings>
|
||||
#include <QApplication>
|
||||
#include "fastplot.h"
|
||||
#include "ui_fastgraph.h"
|
||||
#include "moc_fastgraph.cpp"
|
||||
|
||||
#define NSMAX2 1366
|
||||
|
||||
FastGraph::FastGraph(QSettings * settings, QWidget *parent) :
|
||||
QDialog {parent, Qt::Window | Qt::WindowTitleHint |
|
||||
Qt::WindowCloseButtonHint |
|
||||
Qt::WindowMinimizeButtonHint},
|
||||
m_settings (settings),
|
||||
ui(new Ui::FastGraph)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle (QApplication::applicationName () + " - " + tr ("Fast Graph"));
|
||||
installEventFilter(parent); //Installing the filter
|
||||
ui->fastPlot->setCursor(Qt::CrossCursor);
|
||||
m_ave=40;
|
||||
|
||||
//Restore user's settings
|
||||
m_settings->beginGroup("FastGraph");
|
||||
restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
|
||||
ui->fastPlot->setPlotZero(m_settings->value("PlotZero", 0).toInt());
|
||||
ui->fastPlot->setPlotGain(m_settings->value("PlotGain", 0).toInt());
|
||||
ui->zeroSlider->setValue(ui->fastPlot->m_plotZero);
|
||||
ui->gainSlider->setValue(ui->fastPlot->m_plotGain);
|
||||
ui->fastPlot->setGreenZero(m_settings->value("GreenZero", 0).toInt());
|
||||
ui->greenZeroSlider->setValue(ui->fastPlot->m_greenZero);
|
||||
m_settings->endGroup();
|
||||
|
||||
connect(ui->fastPlot, SIGNAL(fastPick1(int,int,int)),this,
|
||||
SLOT(fastPick1a(int,int,int)));
|
||||
}
|
||||
|
||||
FastGraph::~FastGraph()
|
||||
{
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FastGraph::closeEvent (QCloseEvent * e)
|
||||
{
|
||||
saveSettings ();
|
||||
QDialog::closeEvent (e);
|
||||
}
|
||||
|
||||
void FastGraph::saveSettings()
|
||||
{
|
||||
//Save user's settings
|
||||
m_settings->beginGroup("FastGraph");
|
||||
m_settings->setValue ("geometry", saveGeometry ());
|
||||
m_settings->setValue("PlotZero",ui->fastPlot->m_plotZero);
|
||||
m_settings->setValue("PlotGain",ui->fastPlot->m_plotGain);
|
||||
m_settings->setValue("GreenZero",ui->fastPlot->m_greenZero);
|
||||
m_settings->setValue("GreenGain",ui->fastPlot->m_greenGain);
|
||||
m_settings->endGroup();
|
||||
}
|
||||
|
||||
void FastGraph::plotSpec()
|
||||
{
|
||||
ui->fastPlot->draw();
|
||||
}
|
||||
|
||||
void FastGraph::on_gainSlider_valueChanged(int value)
|
||||
{
|
||||
ui->fastPlot->setPlotGain(value);
|
||||
ui->fastPlot->draw();
|
||||
// qDebug() << "B" << ui->gainSlider->value() << ui->zeroSlider->value()
|
||||
// << ui->greenZeroSlider->value() << m_ave;
|
||||
}
|
||||
|
||||
void FastGraph::on_zeroSlider_valueChanged(int value)
|
||||
{
|
||||
ui->fastPlot->setPlotZero(value);
|
||||
ui->fastPlot->draw();
|
||||
}
|
||||
|
||||
void FastGraph::on_greenZeroSlider_valueChanged(int value)
|
||||
{
|
||||
ui->fastPlot->setGreenZero(value);
|
||||
ui->fastPlot->draw();
|
||||
}
|
||||
|
||||
void FastGraph::fastPick1a(int x0, int x1, int y)
|
||||
{
|
||||
Q_EMIT fastPick(x0,x1,y);
|
||||
}
|
||||
|
||||
void FastGraph::on_pbAutoLevel_clicked()
|
||||
{
|
||||
float sum=0.0;
|
||||
for(int i=0; i<=fast_jh; i++) {
|
||||
sum += fast_green[i];
|
||||
}
|
||||
m_ave=sum/fast_jh;
|
||||
ui->gainSlider->setValue(127-int(2.2*m_ave));
|
||||
ui->zeroSlider->setValue(int(m_ave)+20);
|
||||
ui->greenZeroSlider->setValue(160-int(3.3*m_ave));
|
||||
// qDebug() << "A" << ui->gainSlider->value() << ui->zeroSlider->value()
|
||||
// << ui->greenZeroSlider->value() << m_ave;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef FASTGRAPH_H
|
||||
#define FASTGRAPH_H
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class FastGraph;
|
||||
}
|
||||
|
||||
class QSettings;
|
||||
|
||||
class FastGraph : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
void closeEvent (QCloseEvent *) override;
|
||||
|
||||
public:
|
||||
explicit FastGraph(QSettings *, QWidget *parent = 0);
|
||||
~FastGraph();
|
||||
|
||||
void plotSpec();
|
||||
void saveSettings();
|
||||
|
||||
signals:
|
||||
void fastPick(int x0, int x1, int y);
|
||||
|
||||
public slots:
|
||||
void fastPick1a(int x0, int x1, int y);
|
||||
|
||||
private slots:
|
||||
void on_gainSlider_valueChanged(int value);
|
||||
void on_zeroSlider_valueChanged(int value);
|
||||
void on_greenZeroSlider_valueChanged(int value);
|
||||
void on_pbAutoLevel_clicked();
|
||||
|
||||
private:
|
||||
QSettings * m_settings;
|
||||
float m_ave;
|
||||
|
||||
Ui::FastGraph *ui;
|
||||
};
|
||||
|
||||
extern float fast_green[703];
|
||||
extern int fast_jh;
|
||||
|
||||
#endif // FASTGRAPH_H
|
|
@ -0,0 +1,254 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FastGraph</class>
|
||||
<widget class="QDialog" name="FastGraph">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>710</width>
|
||||
<height>250</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>710</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>710</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Fast Graph</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="FPlotter" name="fastPlot">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>703</width>
|
||||
<height>220</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>703</width>
|
||||
<height>220</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="gainSlider">
|
||||
<property name="toolTip">
|
||||
<string>Waterfall gain</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-60</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>140</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="zeroSlider">
|
||||
<property name="toolTip">
|
||||
<string>Waterfall zero</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-60</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="greenZeroSlider">
|
||||
<property name="toolTip">
|
||||
<string>Spectrum zero</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>160</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbAutoLevel">
|
||||
<property name="text">
|
||||
<string>Auto Level</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FPlotter</class>
|
||||
<extends>QFrame</extends>
|
||||
<header>fastplot.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,235 @@
|
|||
#include "fastplot.h"
|
||||
#include "commons.h"
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
#include "moc_fastplot.cpp"
|
||||
|
||||
#define MAX_SCREENSIZE 2048
|
||||
|
||||
FPlotter::FPlotter(QWidget *parent) : //FPlotter Constructor
|
||||
QFrame(parent)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setAttribute(Qt::WA_PaintOnScreen,false);
|
||||
setAutoFillBackground(false);
|
||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
|
||||
m_pixPerSecond= 12000.0/512.0;
|
||||
m_hdivs = 30;
|
||||
m_jh0=9999;
|
||||
m_HorizPixmap = QPixmap(703,200);
|
||||
m_ScalePixmap = QPixmap(703,20);
|
||||
m_w = 703;
|
||||
m_h = 220;
|
||||
m_h1=20;
|
||||
m_h2=m_h-m_h1;
|
||||
m_HorizPixmap = QPixmap(m_w, m_h2);
|
||||
m_HorizPixmap.fill(Qt::black);
|
||||
m_HorizPixmap.fill(Qt::black);
|
||||
m_ScalePixmap.fill(Qt::white);
|
||||
m_bPaint2=true;
|
||||
m_x0=0;
|
||||
m_x1=0;
|
||||
drawScale();
|
||||
draw();
|
||||
}
|
||||
|
||||
FPlotter::~FPlotter() { } // Destructor
|
||||
|
||||
void FPlotter::paintEvent(QPaintEvent *) // paintEvent()
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.drawPixmap(0,0,m_ScalePixmap);
|
||||
painter.drawPixmap(0,m_h1,m_HorizPixmap);
|
||||
}
|
||||
|
||||
void FPlotter::drawScale() //drawScale()
|
||||
{
|
||||
if(m_ScalePixmap.isNull()) return;
|
||||
int x;
|
||||
|
||||
QRect rect0;
|
||||
QPainter painter0(&m_ScalePixmap);
|
||||
painter0.initFrom(this);
|
||||
|
||||
//create Font to use for scales
|
||||
QFont Font("Arial");
|
||||
Font.setPointSize(8);
|
||||
QFontMetrics metrics(Font);
|
||||
Font.setWeight(QFont::Normal);
|
||||
painter0.setFont(Font);
|
||||
painter0.setPen(Qt::white);
|
||||
m_ScalePixmap.fill(Qt::black);
|
||||
painter0.drawRect(0, 0,m_w,19);
|
||||
painter0.drawLine(0,19,m_w,19);
|
||||
|
||||
//Draw ticks at 1-second intervals
|
||||
for( int i=0; i<=m_hdivs; i++) {
|
||||
x = (int)( (float)i*m_pixPerSecond );
|
||||
painter0.drawLine(x,15,x,19);
|
||||
}
|
||||
|
||||
//Write numbers on the time scale
|
||||
MakeTimeStrs();
|
||||
for( int i=0; i<=m_hdivs; i++) {
|
||||
if(0==i) {
|
||||
//left justify the leftmost text
|
||||
x = (int)( (float)i*m_pixPerSecond);
|
||||
rect0.setRect(x,0, (int)m_pixPerSecond, 20);
|
||||
painter0.drawText(rect0, Qt::AlignLeft|Qt::AlignVCenter,m_HDivText[i]);
|
||||
}
|
||||
else if(m_hdivs == i) {
|
||||
//right justify the rightmost text
|
||||
x = (int)( (float)i*m_pixPerSecond - m_pixPerSecond);
|
||||
rect0.setRect(x,0, (int)m_pixPerSecond, 20);
|
||||
painter0.drawText(rect0, Qt::AlignRight|Qt::AlignVCenter,m_HDivText[i]);
|
||||
} else {
|
||||
//center justify the rest of the text
|
||||
x = (int)( (float)i*m_pixPerSecond - m_pixPerSecond/2);
|
||||
rect0.setRect(x,0, (int)m_pixPerSecond, 20);
|
||||
painter0.drawText(rect0, Qt::AlignHCenter|Qt::AlignVCenter,m_HDivText[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FPlotter::MakeTimeStrs() //MakeTimeStrs
|
||||
{
|
||||
for(int i=0; i<=m_hdivs; i++) {
|
||||
m_HDivText[i].setNum(i);
|
||||
}
|
||||
}
|
||||
|
||||
int FPlotter::XfromTime(float t) //XfromFreq()
|
||||
{
|
||||
return int(t*m_pixPerSecond);
|
||||
}
|
||||
|
||||
float FPlotter::TimefromX(int x) //FreqfromX()
|
||||
{
|
||||
return float(x/m_pixPerSecond);
|
||||
}
|
||||
|
||||
void FPlotter::setPlotZero(int plotZero) //setPlotZero()
|
||||
{
|
||||
m_plotZero=plotZero;
|
||||
m_bPaint2=true;
|
||||
}
|
||||
|
||||
void FPlotter::setPlotGain(int plotGain) //setPlotGain()
|
||||
{
|
||||
m_plotGain=plotGain;
|
||||
m_bPaint2=true;
|
||||
}
|
||||
|
||||
void FPlotter::setGreenZero(int n)
|
||||
{
|
||||
m_greenZero=n;
|
||||
m_bPaint2=true;
|
||||
}
|
||||
|
||||
void FPlotter::draw() //draw()
|
||||
{
|
||||
QPainter painter1(&m_HorizPixmap);
|
||||
QPoint LineBuf[703];
|
||||
QPen penGreen(Qt::green,1);
|
||||
|
||||
int k0=m_jh0;
|
||||
if(fast_jh < m_jh0 or m_bPaint2) {
|
||||
k0=0;
|
||||
QRect tmp(0,0,m_w,119);
|
||||
painter1.fillRect(tmp,Qt::black);
|
||||
painter1.setPen(Qt::white);
|
||||
m_t=QDateTime::currentDateTimeUtc().toString("hh:mm:ss");
|
||||
painter1.drawText(10,95,m_t);
|
||||
}
|
||||
|
||||
float gain = pow(10.0,(m_plotGain/20.0));
|
||||
for(int k=64*k0; k<64*fast_jh; k++) { //Upper spectrogram
|
||||
int i = k%64;
|
||||
int j = k/64;
|
||||
int y=0.005*gain*fast_s[k] + m_plotZero;
|
||||
if(y<0) y=0;
|
||||
if(y>254) y=254;
|
||||
painter1.setPen(g_ColorTbl[y]);
|
||||
painter1.drawPoint(j,64-i);
|
||||
}
|
||||
|
||||
painter1.setPen(penGreen); // Upper green curve
|
||||
int j=0;
|
||||
m_greenGain=10;
|
||||
float greenGain = pow(10.0,(m_greenGain/20.0));
|
||||
for(int x=k0; x<=fast_jh; x++) {
|
||||
int y = 0.9*m_h - greenGain*fast_green[x] - m_greenZero + 40;
|
||||
if(y>119) y=119;
|
||||
LineBuf[j].setX(x);
|
||||
LineBuf[j].setY(y);
|
||||
j++;
|
||||
}
|
||||
painter1.drawPolyline(LineBuf,j);
|
||||
|
||||
if((fast_jh < m_jh0) or m_bPaint2) {
|
||||
QRect tmp(0,120,m_w,219);
|
||||
painter1.fillRect(tmp,Qt::black);
|
||||
painter1.setPen(Qt::white);
|
||||
painter1.drawText(10,195,m_t0);
|
||||
m_t0=m_t;
|
||||
|
||||
for(int k=0; k<64*fast_jh2; k++) { //Lower spectrogram
|
||||
int i = k%64;
|
||||
int j = k/64;
|
||||
int y=0.005*gain*fast_s2[k] + m_plotZero;
|
||||
if(y<0) y=0;
|
||||
if(y>254) y=254;
|
||||
painter1.setPen(g_ColorTbl[y]);
|
||||
painter1.drawPoint(j,164-i);
|
||||
}
|
||||
|
||||
painter1.setPen(penGreen); //Lower green curve
|
||||
j=0;
|
||||
for(int x=0; x<=fast_jh2; x++) {
|
||||
int y = 0.9*m_h - greenGain*fast_green2[x] - m_greenZero + 140;
|
||||
if(y>219) y=219;
|
||||
LineBuf[j].setX(x);
|
||||
LineBuf[j].setY(y);
|
||||
j++;
|
||||
}
|
||||
painter1.drawPolyline(LineBuf,j);
|
||||
m_bPaint2=false;
|
||||
}
|
||||
|
||||
painter1.setPen(Qt::white);
|
||||
painter1.drawLine(0,100, m_w,100);
|
||||
m_jh0=fast_jh;
|
||||
update(); //trigger a new paintEvent
|
||||
}
|
||||
|
||||
void FPlotter::mousePressEvent(QMouseEvent *event) //mousePressEvent
|
||||
{
|
||||
int x=event->x();
|
||||
int y=event->y();
|
||||
int n=event->button();
|
||||
// bool ctrl = (event->modifiers() & Qt::ControlModifier);
|
||||
QPainter painter(&m_HorizPixmap);
|
||||
int x0=x-n*m_pixPerSecond;
|
||||
int x1=x+n*m_pixPerSecond;
|
||||
if(x0 < 0) x0=0;
|
||||
if(x1 > 702) x1=702;
|
||||
Q_EMIT fastPick1(x0,x1,y);
|
||||
int y0=64;
|
||||
if(y >= 120) y0+=100;
|
||||
if(m_x0+m_x1 != 0) {
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawLine(m_x0,m_y0,m_x1,m_y0); //Erase previous yellow line
|
||||
painter.drawLine(m_x0,m_y0-3,m_x0,m_y0+3);
|
||||
painter.drawLine(m_x1,m_y0-3,m_x1,m_y0+3);
|
||||
}
|
||||
painter.setPen(Qt::yellow);
|
||||
painter.drawLine(x0,y0,x1,y0); //Draw yellow line
|
||||
painter.drawLine(x0,y0-3,x0,y0+3);
|
||||
painter.drawLine(x1,y0-3,x1,y0+3);
|
||||
update(); //trigger a new paintEvent
|
||||
m_x0=x0;
|
||||
m_x1=x1;
|
||||
m_y0=y0;
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Some code in this file and accompanying files is based on work by
|
||||
// Moe Wheatley, AE4Y, released under the "Simplified BSD License".
|
||||
// For more details see the accompanying file LICENSE_WHEATLEY.TXT
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FPLOTTER_H
|
||||
#define FPLOTTER_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include <QFrame>
|
||||
#include <QImage>
|
||||
#include <cstring>
|
||||
|
||||
class FPlotter : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FPlotter(QWidget *parent = 0);
|
||||
~FPlotter();
|
||||
|
||||
qint32 m_w;
|
||||
qint32 m_plotZero;
|
||||
qint32 m_plotGain;
|
||||
qint32 m_greenGain;
|
||||
qint32 m_greenZero;
|
||||
qint32 m_x0;
|
||||
qint32 m_x1;
|
||||
qint32 m_y0;
|
||||
|
||||
void draw(); //Update the Fast plot
|
||||
void setPlotZero(int plotZero);
|
||||
void setPlotGain(int plotGain);
|
||||
void setGreenZero(int n);
|
||||
void drawScale();
|
||||
|
||||
signals:
|
||||
void fastPick1(int x0, int x1, int y);
|
||||
|
||||
protected:
|
||||
//re-implemented widget event handlers
|
||||
void paintEvent(QPaintEvent *event);
|
||||
// void resizeEvent(QResizeEvent* event);
|
||||
|
||||
private slots:
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
void MakeTimeStrs();
|
||||
int XfromTime(float t);
|
||||
float TimefromX(int x);
|
||||
qint64 RoundFreq(qint64 freq, int resolution);
|
||||
|
||||
QPixmap m_HorizPixmap;
|
||||
QPixmap m_ScalePixmap;
|
||||
QString m_HDivText[483];
|
||||
QString m_t;
|
||||
QString m_t0;
|
||||
|
||||
double m_pixPerSecond;
|
||||
|
||||
qint32 m_hdivs;
|
||||
qint32 m_h;
|
||||
qint32 m_h1;
|
||||
qint32 m_h2;
|
||||
qint32 m_jh0;
|
||||
|
||||
bool m_bPaint2;
|
||||
};
|
||||
|
||||
extern float fast_green[703];
|
||||
extern float fast_green2[703];
|
||||
extern float fast_s[44992]; //44992=64*703
|
||||
extern float fast_s2[44992];
|
||||
extern int fast_jh;
|
||||
extern int fast_jh2;
|
||||
extern QVector<QColor> g_ColorTbl;
|
||||
|
||||
#endif // FPLOTTER_H
|
18
getfile.cpp
18
getfile.cpp
|
@ -42,15 +42,18 @@ void getfile(QString fname, int ntrperiod)
|
|||
|
||||
int i1=fname.lastIndexOf("/");
|
||||
QString baseName=fname.mid(i1+1);
|
||||
// qDebug() << baseName << baseName.length();
|
||||
|
||||
int i0=fname.indexOf(".wav",0,Qt::CaseInsensitive);
|
||||
i1=fname.indexOf(".wav",0,Qt::CaseInsensitive);
|
||||
jt9com_.nutc=0;
|
||||
if(i0>0) {
|
||||
int n=4;
|
||||
if(baseName.length()!=15) n=6;
|
||||
jt9com_.nutc=100*fname.mid(i0-n,2).toInt() + fname.mid(i0-n+2,2).toInt();
|
||||
if(i1>0) {
|
||||
int i0=fname.indexOf("_",-11);
|
||||
if(i1==i0+7) {
|
||||
jt9com_.nutc=fname.mid(i1-6,6).toInt();
|
||||
} else {
|
||||
jt9com_.nutc=100*fname.mid(i1-4,4).toInt();
|
||||
}
|
||||
}
|
||||
if(ntrperiod > 120 or ntrperiod <0) ntrperiod=120;
|
||||
int npts=ntrperiod*12000;
|
||||
memset(jt9com_.d2,0,2*npts);
|
||||
|
||||
|
@ -61,7 +64,7 @@ void getfile(QString fname, int ntrperiod)
|
|||
if(hdr.nsamrate==11025) wav12_(jt9com_.d2,jt9com_.d2,&n,&hdr.nbitsam2);
|
||||
fclose(fp);
|
||||
jt9com_.newdat=1;
|
||||
if(n==-99999) jt9com_.newdat=2; //Silence compiler warning
|
||||
jt9com_.kin=n;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +131,6 @@ void savewav(QString fname, int ntrperiod)
|
|||
}
|
||||
|
||||
//#define MAX_RANDOM 0x7fffffff
|
||||
|
||||
/* Generate gaussian random float with mean=0 and std_dev=1 */
|
||||
float gran()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
Before using the new "CQ nnn ..." feature in JTMSK mode, I suggest
|
||||
performing the following tests of the necessary CAT control for your
|
||||
radio. (I'm assuming that you already have some experience with
|
||||
JTMSK.)
|
||||
|
||||
TEST 1:
|
||||
--------------------------------------------------------------------------
|
||||
1. Start WSJT-X
|
||||
2. Settings: "Enable VHF/UHF/Microwave features, "Rx frequency offset
|
||||
with 'CQ nnn ...'", Split=Rig, or Split="Fake it"
|
||||
3. Main screen settings: Band=50.280, mode=JTMSK, T/R=15 s
|
||||
4. Activate CQRx, set CQ Rx=265
|
||||
==> Rx dial should now read 50.265 and Tx6 should be queued
|
||||
5. Click "Enable Tx"
|
||||
==> Tx sequences should occur at 50.280, Rx at 50.265
|
||||
|
||||
With most rigs, this test should work with Split configured as either
|
||||
"Rig" or "Fake it".
|
||||
|
||||
TEST 2:
|
||||
--------------------------------------------------------------------------
|
||||
1. Start WSJT-X
|
||||
2. Settings: MyCall=K1JT, "Enable VHF/UHF/Microwave features,
|
||||
"Rx frequency offset with 'CQ nnn ...'", Split=Rig or "Fake it"
|
||||
4. Main screen settings: Band=50.280, mode=JTMSK, T/R=15 s
|
||||
5. Open file 150826_120515.wav
|
||||
==> see decoded message "K1JT VE1SKY FN74"
|
||||
6. Click "Monitor" to restart monitoring
|
||||
7. Activate CQRx, set CQ Rx=265
|
||||
==> Rx dial should now read 50.265; Tx6 should be queued
|
||||
8. Click "Enable Tx"
|
||||
==> Tx sequences should occur at 50.280, Rx at 50.265
|
||||
9. After the start of a transmission, double-click on the decoded message
|
||||
"K1JT VE1SKY FN74"
|
||||
==> Tx2 should be generated and queued; transmission will pause
|
||||
briefly, Tx freq changed to 50.265, then Tx resumed.
|
||||
|
||||
The test file is posted at
|
||||
http://physics.princeton.edu/pulsar/K1JT/150826_120515.wav
|
|
@ -0,0 +1,395 @@
|
|||
Fast Modes in WSJT-X
|
||||
--------------------
|
||||
|
||||
#######################################################################
|
||||
|
||||
IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT
|
||||
|
||||
Third-party individuals (i.e., others not part of the WSJT development
|
||||
team) have been compiling WSJT-X from the open source code and making
|
||||
unauthorized "releases" of their builds. I do NOT reccommend use of
|
||||
unauthorized builds on the air. If a program revision has been released
|
||||
in an official way, you will see it listed here.
|
||||
|
||||
If you operate with an unauthorized "rXXXX" code revisions in our
|
||||
experimental code branch you have no idea what you've got. Quite
|
||||
possibly, the program was built from an intermediate temporary "save"
|
||||
of various files, and was not even supposed to produce a usable
|
||||
program. Your observetions about what works or does not work are then
|
||||
worse than useless -- they waste your time and ours.
|
||||
|
||||
So please, PLEASE, *PLEASE*: use *authorized*, "released* revisions
|
||||
of this still-in-development software, like the revisions described here.
|
||||
|
||||
*ALSO:* If you choose to try an experimental release of JTMSK, please
|
||||
accept the responsibility of reporting on your results. You can send
|
||||
reports to the "wsjtgroup" reflector, wsjtgroup@yahoogroups.com, or
|
||||
email them directly to me. All suggestions for improvements are
|
||||
welcome!
|
||||
|
||||
Bug reports should include details on how to reproduce the undesirable
|
||||
program behavior. Reports on decoding performance are especially
|
||||
useful when accompanied by example *.wav files with signals that
|
||||
you think should have decoded, but did not.
|
||||
|
||||
#######################################################################
|
||||
|
||||
September 18, 2015
|
||||
-----------------
|
||||
|
||||
New alpha release of experimental WSJT-X v1.6.1, r5910
|
||||
------------------------------------------------------
|
||||
Changes since revision 5889 include the following:
|
||||
|
||||
1. Improved behavior for auto-QSY with "CQ nnn ..." feature. (May not
|
||||
be exactly correct, yet, for all radios. Please report if you find
|
||||
problems with your rig.)
|
||||
|
||||
2. Allow optional use of Wide Graph in fast modes.
|
||||
|
||||
3. Add UTC labels to Fast Graph spectrograms.
|
||||
|
||||
4. Display correct DXCC entiry for "CQ nnn ..." messages.
|
||||
|
||||
5. Implement "Save Decoded" for fast modes.
|
||||
|
||||
6. Select Tx6 when "CQ Rx nnn" is enabled.
|
||||
|
||||
7. Fix bug in setting of TRperiod after switch to ISCAT mode.
|
||||
|
||||
8. Display proper symbol '&' in Tx messages in JTMSK mode.
|
||||
|
||||
|
||||
To download this alpha release for Windows, paste the following link
|
||||
into your browser:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5910-win32.exe
|
||||
|
||||
-- 73, Joe, K1JT
|
||||
|
||||
#######################################################################
|
||||
|
||||
September 12, 2015
|
||||
-----------------
|
||||
|
||||
New alpha release of experimental WSJT-X v1.6.1, r5889
|
||||
------------------------------------------------------
|
||||
|
||||
A principal new feature in this release is designed to promote the use
|
||||
of an agreed "calling frequency" for transmissions of the form
|
||||
|
||||
CQ 265 K1ABC FN42
|
||||
|
||||
signifying that K1ABC will listen for replies on 50.265 (or 144.265,
|
||||
or whatever) and will complete the QSO there. The feature uses the
|
||||
rig-control features of WSJT-X to handle the necessary frequency
|
||||
switching.
|
||||
|
||||
##########################################################################
|
||||
Changes since revision 5865 include the following:
|
||||
|
||||
1. New features that allow automatic rig control when you transmit or
|
||||
respond to messages of the form "CQ 265 K1ABC FN42" on an agreed
|
||||
calling frequency. This feature should be especially useful for
|
||||
meteor scatter.
|
||||
|
||||
2. Yellow-highlighted "Tx" messages in the right text window are now
|
||||
properly labeled with 6-digit UTC (hhmmss) in all fast modes.
|
||||
|
||||
3. Fixed a bug (introduced in r5865) that inhibited transmitting in
|
||||
JT4 mode.
|
||||
|
||||
4. Fixed a bug that caused Wide Graph to continue issuing green
|
||||
separator lines at short (e.g. 15 s) intervals after you have switched
|
||||
to a slow mode.
|
||||
|
||||
5. Fixed several more GUI appearance bugs associated with changing
|
||||
modes or submodes.
|
||||
|
||||
6. Fixed a bug in which double-clicking on the Fast Graph could cause
|
||||
program crashes.
|
||||
|
||||
7. Fixed a bug that sometimes caused "high tones" to be emitted in
|
||||
JTMSK mode.
|
||||
|
||||
#######################################################################
|
||||
Here's a brief description of how to use the "CQ nnn ..." features.
|
||||
|
||||
1. On program startup, go to the Settings | General tab and tick the
|
||||
box labeled 'Rx frequency offset with "CQ nnn ..."'
|
||||
|
||||
2. Select JTMSK mode and 50.280 (or your some other agreed calling
|
||||
frequency) from the drop-down band menu. Remember that this menu is
|
||||
not pre-populated with preferred frequencies for all modes on all
|
||||
bands. Use Settings | Frequencies to add your desired modes and
|
||||
frequencies to the list.
|
||||
|
||||
3. Tick the unlabeled checkbox just under the "Report: spinner to
|
||||
activate the "CQ Rx nnn" spinner. Set this control to your desired
|
||||
QSO frequency in kHz above the nominal band edge. On 6 meters, for
|
||||
example, "265" means "50.265".
|
||||
|
||||
4. Your transceiver dial frequency should now show 50.265. Changes to
|
||||
the "CQ Rx nnn" spinner value should be reflected immediately in the
|
||||
transceiver dial frequency, the displayed value on the WSJT-X main
|
||||
screen, and in Tx message #6, the "CQ nnn... " message.
|
||||
|
||||
5. When you transmit the Tx6 message, the Tx frequency will be set at
|
||||
the calling frequency. Otherwise (when receiving, or when
|
||||
transmitting any of the messages Tx1 through Tx5) the offset frequency
|
||||
(50.265 in my example) will be used.
|
||||
|
||||
6. If you double-click on a received "CQ nnn ..." message on the
|
||||
calling frequency, your rig will QSY to specified response frequency,
|
||||
e.g. 50.265, for both Rx and Tx.
|
||||
|
||||
7. To go back to listening on the calling frequency, uncheck the box
|
||||
that activated the "CQ Rx nnn" spinner.
|
||||
|
||||
#######################################################################
|
||||
|
||||
Fair warning: I have not yet tested all possible combinations of
|
||||
"Split Operation" configuration (i.e., "None", "Rig", and "Fake it").
|
||||
If you normally use Split operation, that should be OK for the "CQ
|
||||
nnn ..." feature.
|
||||
|
||||
|
||||
As always, please report any bugs that you find in r5889, including
|
||||
pertinent details on your settings and the exact series of steps
|
||||
required to reproduce the bug.
|
||||
|
||||
|
||||
To download this alpha release for Windows, paste the following link
|
||||
into your browser:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5889-win32.exe
|
||||
|
||||
|
||||
-- 73, Joe, K1JT
|
||||
|
||||
#######################################################################
|
||||
|
||||
New alpha release of experimental WSJT-X v1.6.1, r5865
|
||||
------------------------------------------------------
|
||||
|
||||
This alpha release of WSJT-X includes major improvements to the JTMSK
|
||||
decoder. Changes since revision 5823 include the following:
|
||||
|
||||
1. On-screen controls labeled "Rx nnnn Hz" and "F Tol" (Rx frequency
|
||||
and tolerance) now function as expected in JTMSK mode. The frequency
|
||||
search range can be up to 500 Hz, but note that sensitivity is
|
||||
necessarily reduced for signals off frequency by more than about 250
|
||||
Hz. Normally you should leave Rx Freq set at 1500 Hz; suitable values
|
||||
for F Tol are 100 to 500 Hz.
|
||||
|
||||
2. The JTMSK decoder now makes good use of strong, short pings (as
|
||||
short as 0.1 s) as well as weak pings several times longer.
|
||||
|
||||
3. Improved calculation of S/N and frequency of decoded signals.
|
||||
|
||||
4. Unified appearance of window titles on all non-modal windows.
|
||||
|
||||
5. CW ID is disabled (for now, at least) when operating in any of the
|
||||
WSJT fast modes.
|
||||
|
||||
6. In WSPR mode, display of "Receiving ... <band>" messages is
|
||||
disabled when band-hopping is not in use.
|
||||
|
||||
7. Fixed several bugs affecting status and visibility of certain
|
||||
on-screen controls after changes in operating mode.
|
||||
|
||||
8. Fixed a bug allowing display of duplicate decodes for the same
|
||||
signal.
|
||||
|
||||
9. Fixed a bug preventing compilation on 64-bit systems, and cleaned
|
||||
up some harmless compiler warnings.
|
||||
|
||||
#######################################################################
|
||||
Summary Description of JTMSK Protocol
|
||||
|
||||
JTMSK uses the same standard message structure as slow modes JT4, JT9,
|
||||
and JT65. User information is "source encoded" to 72 bits. A 15-bit
|
||||
CRC is appended and a convolutional code with constraint length K=13
|
||||
and rate r=1/2 is applied, making a total of (72+15+12)*2 = 198
|
||||
information bits. Three copies of the "Barker-11" code and three
|
||||
even-parity bits are added for synchronization, making a total of
|
||||
198+33+3 = 234 channel symbols. Modulation uses a constant-envelope,
|
||||
continuous-phase "minimum-shift keying" (MSK) waveform, with tone
|
||||
frequencies of 1000 and 2000 Hz.
|
||||
|
||||
#######################################################################
|
||||
|
||||
To download this alpha release for Windows, paste the following link
|
||||
into your browser:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5865-win32.exe
|
||||
|
||||
-- 73, Joe, K1JT
|
||||
|
||||
August 28, 2015
|
||||
---------------
|
||||
|
||||
New release of experimental WSJT-X v1.6.1, r5823
|
||||
------------------------------------------------
|
||||
|
||||
To download for Windows, paste the following link into your browser:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5823-win32.exe
|
||||
|
||||
This experimental version of WSJT-X introduces a new fast mode called
|
||||
JTMSK. The letters MS, of course, imply meteor scatter; the three
|
||||
letters MSK mean "Minimum Shift Keying", the modulation scheme used in
|
||||
this mode.
|
||||
|
||||
Revision 5823 also includes a number of (mostly minor) bug fixes
|
||||
relative to r5789.
|
||||
|
||||
IMPORTANT: If you choose to try JTMSK, please accept the
|
||||
responsibility of reporting on your results. You can send reports to
|
||||
the "wsjtgroup" reflector, wsjtgroup@yahoogroups.com or email them
|
||||
directly to me. All suggestions for improvements are welcome! Bug
|
||||
reports should include details on how to reproduce the undesirable
|
||||
program behavior.
|
||||
|
||||
The present JTMSK decoder has been optimized for short pings. It does
|
||||
not yet do a wide search for proper frequency alignment; you and your
|
||||
QSO partner need to be "on frequency" to within +/- 100 Hz or better.
|
||||
The decoder does not (yet) attempt to make optimal use of weak, slowly
|
||||
varying signals. These and other characteristics may be improved in
|
||||
coming revisions.
|
||||
|
||||
KNOWN BUG: At present you should use T/R sequence lengths 15 s in
|
||||
JTMSK mode. If you have a program crash, open Windows Task Manager,
|
||||
select the "Processes" tab, right-click on wsjtx.exe, and select "End
|
||||
Process Tree". Then restart the program.
|
||||
|
||||
I view JTMSK as a candidate for replacing both FSK441 and JTMS for all
|
||||
meteor scatter work. JTMSK has the major advantage of including
|
||||
strong forward error correction (FEC), similar in usage to the schemes
|
||||
used for many years in JT4, JT9, and JT65. The structure of user
|
||||
messages and the format of minimal QSOs is also identical to those
|
||||
other modes. But JTMSK is very fast, transmitting its full encoded
|
||||
message content in 0.117 s, in a 2 kHz bandwidth. JTMSK therefore
|
||||
makes much better use of short pings than (for example) JT9H can do.
|
||||
|
||||
The Tx waveform of JTMSK has been carefully designed to have a number
|
||||
of desirable features. All messages are exactly the same length: 72
|
||||
bits of user information are followed by a 15-bit CRC and encoded into
|
||||
198 channel bits with a convolutional code (constraint length K=13,
|
||||
rate r=1/2). Three sequences of the "Barker-11" code are added, along
|
||||
with three parity bits, making a total of 234 channel bits in each
|
||||
message. The MSK symbols for these bits are transmitted at 2000 baud,
|
||||
and the full encoded message is repeated every 117 ms.
|
||||
|
||||
A summary description of modulation parameters for all WSJT(-X) modes
|
||||
is shown in a table posted here:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.txt and
|
||||
illustrated graphically here:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.pdf
|
||||
|
||||
-- 73, Joe, K1jT
|
||||
|
||||
August 15, 2015
|
||||
---------------
|
||||
|
||||
New release of experimental WSJT-X v1.6.1, r5789
|
||||
|
||||
Changes since WSJT-X v1.6.1, revision 5779:
|
||||
|
||||
1. Major speedup (5x) of fast-JT9 decoder.
|
||||
2. Corrected logic for Auto-Sequencing operation.
|
||||
3. Stop after sending 73 five times in auto-sequence mode.
|
||||
4. Add an "Auto-Level" control to Fast Graph window.
|
||||
5. Send fast-mode decodes to PSKreporter web site.
|
||||
6. Support automatic logging via JTAlert-X.
|
||||
7. Send fast-mode output to file ALL.TXT.
|
||||
8. Better definition of dB levels for fast-JT9 signals.
|
||||
9. Rationalize the GUI behavior when changing mode, submode, fast/slow
|
||||
status, and T/R period.
|
||||
10. Correct a flaw in the display of multiple decodes in a single
|
||||
fast-JT9 sequence.
|
||||
11. Fix minor bugs reported by G3WDG, ND0B, OZ1PIF, and others.
|
||||
|
||||
To download for Windows, paste the following link into your browser:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5789-win32.exe
|
||||
|
||||
Please keep in mind that this is an experimental version of WSJT-X.
|
||||
Bug reports and other feedback will be much appreciated, and will help
|
||||
to make the program better!
|
||||
|
||||
-- 73, Joe, K1JT
|
||||
|
||||
|
||||
August 11, 2015
|
||||
---------------
|
||||
|
||||
Since its origin in the dark ages (ca. 2001) WSJT has supported "fast"
|
||||
modes (designed for meteor scatter, etc.) and "slow" modes (optimized
|
||||
for EME and other weak-signal propagation types). The most recent new
|
||||
mode, JT9, now has *both* fast and slow submodes.
|
||||
|
||||
JT9A (the "original" JT9) is like JT65 and JT4: its T/R sequences are
|
||||
one minute long, and its primary goal is best possible sensitivity for
|
||||
very weak, approximately steady signals. The new experimental JT9
|
||||
submodes use the same message structure, encoding, and modulation type
|
||||
(9-tone FSK) as JT9A, but wider tone spacing and (optionally) faster
|
||||
keying rates.
|
||||
|
||||
You can download an experimental version of WSJT-X (v1.6.1, r5779) here:
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjtx-1.6.1-r5779-win32.exe
|
||||
|
||||
The fast submodes currently being tested, JT9E - JT9H, have been found
|
||||
highly effective for meteors and ionoscatter propagation on 6 and 10
|
||||
meters. Sensitivity is similar to ISCAT, or slightly better.
|
||||
Decoding is much more reliable, because the JT9 protocol includes
|
||||
strong forward error correction. Decoding results are like those for
|
||||
all the WSJT "slow" modes: you should see messages exactly as they
|
||||
were transmitted, or nothing at all. A potential side benefit is
|
||||
automatic reporting of decodes to PSKreporter.
|
||||
|
||||
For details on the modulation parameters of the JT9 submodes, see the
|
||||
table posted at
|
||||
http://physics.princeton.edu/pulsar/K1JT/wsjt_modes.txt.
|
||||
|
||||
WSJT-X v1.6.1 r5779 has the following changes from r5769:
|
||||
|
||||
1. Numerous bug fixes
|
||||
2. Double-click on decoded message now behaves properly
|
||||
3. Faster decoding (further optimization still to come)
|
||||
4. Decoded text is highlighted as in WSJT-X slow modes
|
||||
5. Optional auto-sequencing
|
||||
|
||||
Fair warning: auto-sequencing is basically functional, but scarcely
|
||||
tested. Please watch what it is doing, and tell us how you think it
|
||||
should be improved!
|
||||
|
||||
If you use WSJT-X also for other modes and other purposes, you may
|
||||
want to save several different sets of configuration settings. In
|
||||
that case it's convenient to use the "-r xxx" option and start the
|
||||
program from a command-prompt window. For example:
|
||||
|
||||
C:\Users\joe> cd \wsjt\wsjtx\bin
|
||||
C:\WSJT\wsjtx\bin> wsjtx -r xxx
|
||||
|
||||
... where "xxx" can be anything you like, for example "ISCAT",
|
||||
"FAST9", etc.
|
||||
|
||||
Proper configuration for the JT9 fast modes includes the following
|
||||
settings:
|
||||
|
||||
On the Settings | General tab:
|
||||
|
||||
- check "Enable VHF/UHF/Microwave features"
|
||||
|
||||
Main window settings:
|
||||
|
||||
- Mode JT9
|
||||
- Tx 700 Hz
|
||||
- Rx 700 Hz
|
||||
- Sync 0
|
||||
- Submode G ... or E, F, and H (H not legal in US on 10m)
|
||||
- Tick "Fast"
|
||||
- T/R 30 s (also 5, 10, 15 s)
|
||||
- FTol 500
|
||||
|
||||
Please keep in mind that this is an experimental version of WSJT-X.
|
||||
It still has some rough edges, and no doubt some bugs. Your feedback
|
||||
will be much appreciated, and will help to make the program better!
|
||||
|
||||
-- 73, Joe, K1JT
|
|
@ -0,0 +1,123 @@
|
|||
program JTMSKcode
|
||||
|
||||
! Generate simulated data for testing of JTMSK
|
||||
|
||||
use iso_c_binding, only: c_loc,c_size_t
|
||||
use hashing
|
||||
use packjt
|
||||
character msg*22,decoded*22,bad*1,msgtype*13
|
||||
integer*4 i4tone(234) !Channel symbols (values 0-1)
|
||||
integer*1 e1(201)
|
||||
integer*1 r1(201)
|
||||
integer*1, target :: d8(13)
|
||||
integer mettab(0:255,0:1) !Metric table for BPSK modulation
|
||||
integer*1 i1hash(4)
|
||||
integer*4 i4Msg6BitWords(12) !72-bit message as 6-bit words
|
||||
character*72 c72
|
||||
! real*8 twopi,dt,f0,f1,f,phi,dphi
|
||||
real xp(29)
|
||||
equivalence (ihash,i1hash)
|
||||
data xp/0.500000, 0.401241, 0.309897, 0.231832, 0.168095, &
|
||||
0.119704, 0.083523, 0.057387, 0.039215, 0.026890, &
|
||||
0.018084, 0.012184, 0.008196, 0.005475, 0.003808, &
|
||||
0.002481, 0.001710, 0.001052, 0.000789, 0.000469, &
|
||||
0.000329, 0.000225, 0.000187, 0.000086, 0.000063, &
|
||||
0.000017, 0.000091, 0.000032, 0.000045/
|
||||
include 'testmsg.f90'
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.1) then
|
||||
print*,'Usage: JTMSKcode "message"'
|
||||
! print*,' JTMSKcode -t'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
call getarg(1,msg)
|
||||
nmsg=1
|
||||
if(msg(1:2).eq."-t") nmsg=NTEST
|
||||
|
||||
! Get the metric table
|
||||
bias=0.0
|
||||
scale=20.0
|
||||
xln2=log(2.0)
|
||||
do i=128,156
|
||||
x0=log(max(0.0001,2.0*xp(i-127)))/xln2
|
||||
x1=log(max(0.001,2.0*(1.0-xp(i-127))))/xln2
|
||||
mettab(i,0)=nint(scale*(x0-bias))
|
||||
mettab(i,1)=nint(scale*(x1-bias))
|
||||
mettab(256-i,0)=mettab(i,1)
|
||||
mettab(256-i,1)=mettab(i,0)
|
||||
enddo
|
||||
do i=157,255
|
||||
mettab(i,0)=mettab(156,0)
|
||||
mettab(i,1)=mettab(156,1)
|
||||
mettab(256-i,0)=mettab(i,1)
|
||||
mettab(256-i,1)=mettab(i,0)
|
||||
enddo
|
||||
|
||||
write(*,1010)
|
||||
1010 format(" Message Decoded Err? Type"/ &
|
||||
74("-"))
|
||||
do imsg=1,nmsg
|
||||
if(nmsg.gt.1) msg=testmsg(imsg)
|
||||
call fmtmsg(msg,iz) !To upper case, collapse multiple blanks
|
||||
ichk=0
|
||||
call genmsk(msg,ichk,decoded,i4tone,itype) !Encode message into tone #s
|
||||
msgtype=""
|
||||
if(itype.eq.1) msgtype="Std Msg"
|
||||
if(itype.eq.2) msgtype="Type 1 prefix"
|
||||
if(itype.eq.3) msgtype="Type 1 suffix"
|
||||
if(itype.eq.4) msgtype="Type 2 prefix"
|
||||
if(itype.eq.5) msgtype="Type 2 suffix"
|
||||
if(itype.eq.6) msgtype="Free text"
|
||||
|
||||
! Extract the data symbols, skipping over sync and parity bits
|
||||
n1=35
|
||||
n2=69
|
||||
n3=94
|
||||
|
||||
r1(1:n1)=i4tone(11+1:11+n1)
|
||||
r1(n1+1:n1+n2)=i4tone(23+n1+1:23+n1+n2)
|
||||
r1(n1+n2+1:n1+n2+n3)=i4tone(35+n1+n2+1:35+n1+n2+n3)
|
||||
where(r1.eq.0) r1=127
|
||||
where(r1.eq.1) r1=-127
|
||||
|
||||
j=0
|
||||
do i=1,99
|
||||
j=j+1
|
||||
e1(j)=r1(i)
|
||||
j=j+1
|
||||
e1(j)=r1(i+99)
|
||||
enddo
|
||||
|
||||
nb1=87
|
||||
call vit213(e1,nb1,mettab,d8,metric)
|
||||
|
||||
ihash=nhash(c_loc(d8),int(9,c_size_t),146)
|
||||
ihash=2*iand(ihash,32767)
|
||||
decoded=" "
|
||||
if(d8(10).eq.i1hash(2) .and. d8(11).eq.i1hash(1)) then
|
||||
write(c72,1012) d8(1:9)
|
||||
1012 format(9b8.8)
|
||||
read(c72,1014) i4Msg6BitWords
|
||||
1014 format(12b6.6)
|
||||
call unpackmsg(i4Msg6BitWords,decoded) !Unpack to get msgsent
|
||||
endif
|
||||
|
||||
bad=" "
|
||||
if(decoded.ne.msg) bad="*"
|
||||
write(*,1020) imsg,msg,decoded,bad,itype,msgtype
|
||||
1020 format(i2,'.',2x,a22,2x,a22,3x,a1,i3,": ",a13)
|
||||
|
||||
enddo
|
||||
|
||||
if(nmsg.eq.1) then
|
||||
open(10,file='JTMSKcode.out',status='unknown')
|
||||
do j=1,234
|
||||
write(10,1030) j,i4tone(j)
|
||||
1030 format(2i5)
|
||||
enddo
|
||||
close(10)
|
||||
endif
|
||||
|
||||
999 end program JTMSKcode
|
|
@ -0,0 +1,131 @@
|
|||
program JTMSKsim
|
||||
|
||||
use wavhdr
|
||||
parameter (NSPM=1404)
|
||||
parameter (NFFT=256*1024)
|
||||
parameter (NMAX=15*12000)
|
||||
type(hdr) h
|
||||
complex cb11(0:NSPM-1)
|
||||
complex cmsg(0:NSPM-1)
|
||||
complex c(0:NFFT-1)
|
||||
complex c1(0:NSPM-1)
|
||||
complex c2(0:NSPM-1)
|
||||
integer i4tone(NSPM)
|
||||
integer*2 iwave(NMAX)
|
||||
real w(0:255)
|
||||
character*8 arg
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.2) then
|
||||
print*,'Usage: JTMSK freq dB'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,arg)
|
||||
read(arg,*) fmid
|
||||
call getarg(2,arg)
|
||||
read(arg,*) snrdb
|
||||
|
||||
open(10,file='JTMSKcode.out',status='old')
|
||||
do j=1,234
|
||||
read(10,*) junk,i4tone(j)
|
||||
enddo
|
||||
close(10)
|
||||
|
||||
npts=NMAX
|
||||
h=default_header(12000,npts)
|
||||
twopi=8.0*atan(1.0)
|
||||
dt=1.0/12000.0
|
||||
df=12000.0/NFFT
|
||||
k=-1
|
||||
phi=0.
|
||||
phi0=0.
|
||||
sig=10.0**(0.05*snrdb)
|
||||
|
||||
! Generate the Tx waveform
|
||||
cb11=0.
|
||||
do j=1,234
|
||||
dphi=twopi*(fmid-500.0)*dt
|
||||
if(i4tone(j).eq.1) dphi=twopi*(fmid+500.0)*dt
|
||||
dphi0=twopi*1000.0*dt
|
||||
if(i4tone(j).eq.1) dphi0=twopi*2000.0*dt
|
||||
do i=1,6
|
||||
k=k+1
|
||||
phi=phi+dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
cmsg(k)=cmplx(cos(phi),sin(phi))
|
||||
phi0=phi0+dphi0
|
||||
if(phi0.gt.twopi) phi0=phi0-twopi
|
||||
! if((k.ge.1 .and. k.le.66) .or. (k.ge.283 .and. k.le.348) .or. &
|
||||
! (k.ge.769 .and.k.le.834)) cb11(k)=cmplx(cos(phi0),sin(phi0))
|
||||
if(k.ge.1 .and. k.le.66) cb11(k)=cmplx(cos(phi0),sin(phi0))
|
||||
! write(11,3001) k*dt,cmsg(k),phi
|
||||
!3001 format(4f12.6)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
! Generate noise with B=2500 Hz, rms=1.0
|
||||
c=0.
|
||||
ia=nint(250.0/df)
|
||||
ib=nint(2759.0/df)
|
||||
do i=ia,ib
|
||||
x=gran()
|
||||
y=gran()
|
||||
c(i)=cmplx(x,y)
|
||||
enddo
|
||||
call four2a(c,NFFT,1,1,1)
|
||||
sq=0.
|
||||
do i=0,npts-1
|
||||
sq=sq + real(c(i))**2 + aimag(c(i))**2
|
||||
enddo
|
||||
rms=sqrt(0.5*sq/npts)
|
||||
c=c/rms
|
||||
|
||||
i0=3*12000
|
||||
ncopy=NSPM
|
||||
! ncopy=0.5*NSPM
|
||||
c(i0:i0+ncopy-1)=c(i0:i0+ncopy-1) + sig*cmsg(0:ncopy-1)
|
||||
do i=1,npts
|
||||
iwave(i)=100.0*real(c(i))
|
||||
enddo
|
||||
|
||||
open(12,file='150901_000000.wav',status='unknown',access='stream')
|
||||
write(12) h,iwave(1:npts)
|
||||
|
||||
smax=0.
|
||||
fpk=0.
|
||||
jpk=0
|
||||
nfft1=256
|
||||
w=0.
|
||||
do i=0,65
|
||||
w(i)=sin(i*twopi/132.0)
|
||||
enddo
|
||||
|
||||
do ia=0,npts-nfft1
|
||||
c1(0:nfft1-1)=c(ia:ia+nfft1-1)*conjg(cb11(0:nfft1-1))
|
||||
c2(0:nfft1-1)=w(0:nfft1-1)*c1(0:nfft1-1)
|
||||
call four2a(c2,nfft1,1,-1,1)
|
||||
do i=0,nfft1-1
|
||||
! write(21,1100) i,c1(i)
|
||||
!1100 format(i6,2f12.3)
|
||||
enddo
|
||||
|
||||
df1=12000.0/nfft1
|
||||
do i=-20,20
|
||||
j=i
|
||||
if(i.lt.0) j=j+nfft1
|
||||
f=j*df1
|
||||
if(i.lt.0) f=f-12000.0
|
||||
s=1.e-3*(real(c2(j))**2 + aimag(c2(j))**2)
|
||||
if(abs(ia-i0).lt.1404) write(22,1110) f,c2(j),s,ia
|
||||
1110 format(4f12.3,i6)
|
||||
if(s.gt.smax) then
|
||||
smax=s
|
||||
jpk=ia
|
||||
fpk=f
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
print*,smax,jpk*dt,fpk
|
||||
|
||||
999 end program JTMSKsim
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
CC = gcc
|
||||
CXX = g++
|
||||
FC = gfortran
|
||||
AR = ar cr
|
||||
MKDIR = mkdir -p
|
||||
CP = cp
|
||||
RANLIB = ranlib
|
||||
RM = rm -f
|
||||
|
||||
FFLAGS = -O3 -funroll-loops -Wall -Wno-conversion -fno-second-underscore -DUNIX
|
||||
CFLAGS = -I. -fPIE
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.mod: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
#all: jt4.mod testjt4 testfast9
|
||||
all: testjt65
|
||||
|
||||
OBJS1 = testjt4.o jt4.o sync4.o ps4.o four2a.o flat1a.o smo.o xcor4.o \
|
||||
slope.o peakup.o db.o pctile.o sort.o timer.o image.o zplt.o
|
||||
|
||||
testjt4: $(OBJS1)
|
||||
$(FC) -o testjt4 $(OBJS1) -L. -lfftw3f_threads -lfftw3f
|
||||
|
||||
OBJS2 = t2.o image.o
|
||||
t2: $(OBJS2)
|
||||
$(FC) -o t2 $(OBJS2)
|
||||
|
||||
OBJS3 = testfast9.o fast9.o four2a.o pctile.o db.o interleave9.o jt9fano.o \
|
||||
sort.o fano232.o packjt.o deg2grid.o grid2deg.o fmtmsg.o \
|
||||
spec9f.o foldspec9f.o sync9f.o softsym9f.o
|
||||
testfast9: $(OBJS3)
|
||||
$(FC) -o testfast9 $(OBJS3) C:\JTSDK\fftw3f\libfftw3f-3.dll
|
||||
|
||||
OBJS4 = testjt65.o symspec65.o four2a.o db.o flat65.o pctile.o shell.o \
|
||||
xcor.o setup65.o slope.o peakup.o sync65.o
|
||||
testjt65: $(OBJS4)
|
||||
$(FC) -o testjt65 $(OBJS4) C:\JTSDK\fftw3f\libfftw3f-3.dll
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o libjt9.a testjt4
|
|
@ -0,0 +1,76 @@
|
|||
# Set paths
|
||||
EXE_DIR = ../../wsjtx_exp_install_latest
|
||||
QT_DIR = /usr/include/qt5
|
||||
INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
FC = gfortran
|
||||
AR = ar cr
|
||||
MKDIR = mkdir -p
|
||||
CP = cp
|
||||
RANLIB = ranlib
|
||||
RM = rm -f
|
||||
|
||||
FFLAGS = -I/opt/local/include -O3 -funroll-loops -Wall -Wno-conversion -fno-second-underscore -DUNIX
|
||||
CFLAGS = -I. -fbounds-check -fPIE
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: libjt9.a jt65 jt65sim
|
||||
|
||||
OBJS1 = astrosub.o astro0.o astro.o sun.o coord.o tmoonsub.o \
|
||||
fmtmsg.o deg2grid.o\
|
||||
prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \
|
||||
igray.o fftw3mod.o packjt.o\
|
||||
four2a.o grid2deg.o wisdom.o \
|
||||
symspec.o analytic.o db.o \
|
||||
encode232.o interleave9.o\
|
||||
entail.o fano232.o gran.o sync9.o decjt9.o \
|
||||
fil3.o decoder.o timer.o \
|
||||
twkfreq.o symspec2.o shell.o sync65.o peakup.o slope.o xcor.o\
|
||||
fillcom.o chkss2.o zplot9.o flat1.o flat2.o \
|
||||
jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
|
||||
filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
|
||||
extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
|
||||
move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \
|
||||
wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \
|
||||
flat4.o determ.o baddata.o subtract65.o
|
||||
|
||||
libjt9.a: $(OBJS1)
|
||||
$(AR) libjt9.a $(OBJS1)
|
||||
$(RANLIB) libjt9.a
|
||||
|
||||
OBJS7 = jt65.o
|
||||
jt65: $(OBJS7) libjt9.a libsfrsd.a
|
||||
$(FC) -o jt65 $(OBJS7) -L. -L/opt/local/lib -L./sfrsd2 -ljt9 -lsfrsd -lfftw3f_threads -lfftw3f
|
||||
$(CP) jt65 $(EXE_DIR)
|
||||
|
||||
OBJS2 = jt65sim.o wavhdr.o
|
||||
jt65sim: $(OBJS2) libjt9.a
|
||||
$(FC) -o jt65sim $(OBJS2) -L. -L/opt/local/lib -ljt9
|
||||
$(CP) jt65sim $(EXE_DIR)
|
||||
|
||||
init_rs.o: init_rs.c
|
||||
$(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c
|
||||
|
||||
encode_rs.o: encode_rs.c
|
||||
$(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c
|
||||
|
||||
decode_rs.o: decode_rs.c
|
||||
$(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o libjt9.a jt65
|
|
@ -0,0 +1,63 @@
|
|||
# Set paths
|
||||
EXE_DIR = ../../wsjtx_exp_install_latest
|
||||
QT_DIR = /usr/include/qt5
|
||||
INCPATH = -I${QT_DIR} -I${QT_DIR}/QtCore
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
FC = gfortran
|
||||
AR = ar cr
|
||||
MKDIR = mkdir -p
|
||||
CP = cp
|
||||
RANLIB = ranlib
|
||||
RM = rm -f
|
||||
|
||||
FFLAGS = -I/opt/local/include -O2 -Wall -Wno-conversion \
|
||||
-fno-second-underscore -fbounds-check -DUNIX
|
||||
CFLAGS = -I. -fPIE
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: libjt9.a jt65
|
||||
|
||||
OBJS1 = astrosub.o astro0.o astro.o sun.o coord.o tmoonsub.o \
|
||||
fmtmsg.o deg2grid.o\
|
||||
prog_args.o options.o pctile.o graycode.o sort.o chkmsg.o \
|
||||
igray.o fftw3mod.o packjt.o\
|
||||
four2a.o grid2deg.o wisdom.o \
|
||||
symspec.o analytic.o db.o \
|
||||
encode232.o interleave9.o\
|
||||
entail.o fano232.o gran.o sync9.o decjt9.o \
|
||||
fil3.o decoder.o timer.o \
|
||||
twkfreq.o symspec2.o shell.o sync65.o peakup.o slope.o xcor.o\
|
||||
fillcom.o chkss2.o zplot9.o flat1.o flat2.o \
|
||||
jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \
|
||||
filbig.o fil6521.o afc65b.o decode65b.o setup65.o \
|
||||
extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \
|
||||
move.o indexx.o graycode65.o twkfreq65.o smo.o smo121.o \
|
||||
wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o fil4.o \
|
||||
flat4.o determ.o baddata.o subtract65.o
|
||||
|
||||
libjt9.a: $(OBJS1)
|
||||
$(AR) libjt9.a $(OBJS1)
|
||||
$(RANLIB) libjt9.a
|
||||
|
||||
OBJS7 = jt65.o
|
||||
jt65: $(OBJS7) libjt9.a libsfrsd.a
|
||||
$(FC) -o jt65 $(OBJS7) -L. -ljt9 -lsfrsd -lfftw3f_threads -lfftw3f
|
||||
$(CP) jt65 $(EXE_DIR)
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o libjt9.a jt65
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
# Set paths
|
||||
EXE_DIR = ..\\..\\wsjtx_install
|
||||
QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32
|
||||
FFTW3_DIR = ..
|
||||
|
||||
INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include
|
||||
|
||||
# Compilers
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
FC = gfortran
|
||||
AR = ar cr
|
||||
RANLIB = ranlib
|
||||
MKDIR = mkdir -p
|
||||
CP = cp
|
||||
RM = rm -f
|
||||
|
||||
FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion
|
||||
CFLAGS = -O2 -I.
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
#all: jt9code JTMSKcode
|
||||
all: testmsk JTMSKcode
|
||||
|
||||
OBJS4 = jt9code.o packjt.o fmtmsg.o gen9.o deg2grid.o grid2deg.o \
|
||||
entail.o encode232.o interleave9.o graycode.o igray.o
|
||||
jt9code: $(OBJS4)
|
||||
$(FC) -o jt9code $(OBJS4)
|
||||
|
||||
OBJS5 = JTMSKcode.o packjt.o fmtmsg.o genmsk.o deg2grid.o grid2deg.o \
|
||||
entail.o nhash.o tab.o vit213.o
|
||||
JTMSKcode: $(OBJS5)
|
||||
$(FC) -o JTMSKcode $(OBJS5)
|
||||
|
||||
OBJS6 = testmsk.o jtmsk.o analytic.o four2a.o db.o mskdf.o pctile.o \
|
||||
sort.o tweak1.o syncmsk.o genmsk.o packjt.o fmtmsg.o indexx.o \
|
||||
deg2grid.o grid2deg.o entail.o nhash.o tab.o vit213.o
|
||||
testmsk: $(OBJS6)
|
||||
$(FC) -o testmsk $(OBJS6) -lfftw3f
|
||||
|
||||
OBJS1 = t1.o four2a.o db.o
|
||||
t1: $(OBJS1)
|
||||
$(FC) -o t1 $(OBJS1) -lfftw3f
|
||||
|
||||
OBJS2 = t6.o four2a.o db.o
|
||||
t6: $(OBJS2)
|
||||
$(FC) -o t6 $(OBJS2) -lfftw3f
|
||||
|
||||
nhash.o: wsprd/nhash.h wsprd/nhash.c
|
||||
$(CC) -c -O2 wsprd/nhash.c
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o JTMSKcode JTMSKcode.exe
|
|
@ -0,0 +1,69 @@
|
|||
|
||||
# Set paths
|
||||
EXE_DIR = ..\\..\\wsjtx_install
|
||||
QT_DIR = C:/wsjt-env/Qt5/5.2.1/mingw48_32
|
||||
FFTW3_DIR = ..
|
||||
|
||||
INCPATH = -I${QT_DIR}/include/QtCore -I${QT_DIR}/include
|
||||
|
||||
# Compilers
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
FC = gfortran
|
||||
AR = ar cr
|
||||
RANLIB = ranlib
|
||||
MKDIR = mkdir -p
|
||||
CP = cp
|
||||
RM = rm -f
|
||||
|
||||
FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion
|
||||
CFLAGS = -O2 -I.
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
#all: jt9code JTMSKcode.exe
|
||||
all: testmsk.exe JTMSKsim.exe JTMSKcode.exe fixwav.exe
|
||||
|
||||
OBJS3 = JTMSKsim.o wavhdr.o gran.o four2a.o db.o
|
||||
JTMSKsim.exe: $(OBJS3)
|
||||
$(FC) -o JTMSKsim.exe $(OBJS3) C:\JTSDK\fftw3f\libfftw3f-3.dll
|
||||
|
||||
OBJS4 = jt9code.o packjt.o fmtmsg.o gen9.o deg2grid.o grid2deg.o \
|
||||
entail.o encode232.o interleave9.o graycode.o igray.o
|
||||
jt9code: $(OBJS4)
|
||||
$(FC) -o jt9code $(OBJS4)
|
||||
|
||||
OBJS5 = JTMSKcode.o packjt.o fmtmsg.o genmsk.o deg2grid.o grid2deg.o \
|
||||
entail.o tab.o vit213.o hashing.o nhash.o
|
||||
JTMSKcode.exe: $(OBJS5)
|
||||
$(FC) -o JTMSKcode.exe $(OBJS5)
|
||||
|
||||
OBJS6 = testmsk.o jtmsk.o analytic.o four2a.o db.o pctile.o \
|
||||
shell.o tweak1.o syncmsk.o genmsk.o packjt.o fmtmsg.o indexx.o \
|
||||
deg2grid.o grid2deg.o entail.o hashing.o nhash.o tab.o vit213.o \
|
||||
mskdt.o timer.o rectify_msk.o
|
||||
testmsk.exe: $(OBJS6)
|
||||
$(FC) -o testmsk.exe $(OBJS6) C:\JTSDK\fftw3f\libfftw3f-3.dll
|
||||
|
||||
OBJS1 = fixwav.o wavhdr.o
|
||||
fixwav.exe: $(OBJS1)
|
||||
$(FC) -o fixwav.exe $(OBJS1)
|
||||
|
||||
OBJS2 = t6.o four2a.o db.o
|
||||
t6: $(OBJS2)
|
||||
$(FC) -o t6 $(OBJS2) C:\JTSDK\fftw3f\libfftw3f-3.dll
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o JTMSKcode JTMSKcode.exe
|
|
@ -9,11 +9,14 @@ subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest)
|
|||
a(2)=0.
|
||||
a(3)=0.
|
||||
a(4)=0.
|
||||
! deltaa(1)=2.0
|
||||
! deltaa(2)=2.0
|
||||
! deltaa(3)=2.0
|
||||
! deltaa(4)=0.05
|
||||
deltaa(1)=2.0
|
||||
deltaa(2)=2.0
|
||||
deltaa(3)=2.0
|
||||
deltaa(4)=0.05
|
||||
nterms=3 !Maybe 2 is enough?
|
||||
deltaa(3)=1.0
|
||||
nterms=2 !Maybe 2 is enough?
|
||||
|
||||
! Start the iteration
|
||||
chisqr=0.
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
subroutine ana932(dat,npts0,cdat,npts)
|
||||
|
||||
real dat(npts0)
|
||||
complex cdat(262145)
|
||||
|
||||
n=log(float(npts0))/log(2.0)
|
||||
nfft1=2**(n+1)
|
||||
nfft2=9*nfft1/32
|
||||
df932=11025.0/nfft1
|
||||
fac=2.0/nfft1
|
||||
do i=1,npts0/2
|
||||
cdat(i)=fac*cmplx(dat(2*i-1),dat(2*i))
|
||||
enddo
|
||||
cdat(npts0/2+1:nfft1/2)=0.
|
||||
call four2a(cdat,nfft1,1,-1,0) !Forward r2c FFT
|
||||
call four2a(cdat,nfft2,1,1,1) !Inverse c2c FFT
|
||||
npts=npts0*9.0/32.0 !Downsampled data length
|
||||
npts2=npts
|
||||
|
||||
return
|
||||
end subroutine ana932
|
|
@ -1,24 +1,53 @@
|
|||
subroutine analytic(d,npts,nfft,s,c)
|
||||
subroutine analytic(d,npts,nfft,c)
|
||||
|
||||
! Convert real data to analytic signal
|
||||
|
||||
parameter (NFFTMAX=128*1024)
|
||||
parameter (NFFTMAX=1024*1024)
|
||||
real d(npts)
|
||||
real s(npts)
|
||||
real h(NFFTMAX/2)
|
||||
complex c(NFFTMAX)
|
||||
data nfft0/0/
|
||||
save nfft0,h
|
||||
|
||||
df=12000.0/nfft
|
||||
nh=nfft/2
|
||||
if(nfft.ne.nfft0) then
|
||||
t=1.0/2000.0
|
||||
beta=0.6
|
||||
pi=4.0*atan(1.0)
|
||||
do i=1,nh+1
|
||||
ff=(i-1)*df
|
||||
f=ff-1500.0
|
||||
h(i)=0.
|
||||
if(abs(f).le.(1-beta)/(2*t)) h(i)=1.0
|
||||
if(abs(f).gt.(1-beta)/(2*t) .and. abs(f).le.(1+beta)/(2*t)) then
|
||||
h(i)=0.5*(1+cos((pi*t/beta )*(abs(f)-(1-beta)/(2*t))))
|
||||
endif
|
||||
h(i)=sqrt(h(i))
|
||||
enddo
|
||||
nfft0=nfft
|
||||
endif
|
||||
|
||||
fac=2.0/nfft
|
||||
c(1:npts)=fac*d(1:npts)
|
||||
c(npts+1:nfft)=0.
|
||||
call four2a(c,nfft,1,-1,1) !Forward c2c FFT
|
||||
|
||||
do i=1,nh
|
||||
s(i)=real(c(i))**2 + aimag(c(i))**2
|
||||
enddo
|
||||
! do i=1,nh
|
||||
! f=(i-1)*df
|
||||
! s(i)=real(c(i))**2 + aimag(c(i))**2
|
||||
! write(12,3001) f,s(i),db(s(i))
|
||||
!3001 format(3f12.3)
|
||||
! enddo
|
||||
|
||||
c(1)=0.5*c(1)
|
||||
c(nh+2:nfft)=0.
|
||||
! ia=700.0/df
|
||||
! c(1:ia)=0.
|
||||
! ib=2300.0/df
|
||||
! c(ib:nfft)=0.
|
||||
|
||||
c(1:nh+1)=h(1:nh+1)*c(1:nh+1)
|
||||
c(1)=0.5*c(1) !Half of DC term
|
||||
c(nh+2:nfft)=0. !Zero the negative frequencies
|
||||
call four2a(c,nfft,1,1,1) !Inverse c2c FFT
|
||||
|
||||
return
|
||||
|
|
|
@ -7,7 +7,7 @@ subroutine astro0(nyear,month,nday,uth8,freq8,mygrid,hisgrid, &
|
|||
character*6 mygrid,hisgrid
|
||||
real*8 AzSun8,ElSun8,AzMoon8,ElMoon8,AzMoonB8,ElMoonB8
|
||||
real*8 dbMoon8,RAMoon8,DecMoon8,HA8,Dgrd8,xnr8,dfdt,dfdt0,dt
|
||||
real*8 sd8,poloffset8,day8,width1,width2,xlst8
|
||||
real*8 sd8,poloffset8,width1,width2,xlst8
|
||||
real*8 uth8,techo8,freq8
|
||||
real*8 xl,b
|
||||
common/librcom/xl(2),b(2)
|
||||
|
@ -53,6 +53,7 @@ subroutine astro0(nyear,month,nday,uth8,freq8,mygrid,hisgrid, &
|
|||
RAMoon8=RAMoon/15.0
|
||||
DecMoon8=DecMoon
|
||||
HA8=HA
|
||||
xlst8=xlst
|
||||
Dgrd8=Dgrd
|
||||
sd8=sd
|
||||
poloffset8=poloffset
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
-12.8 1.000 -9.966 1.000000 0.000000
|
||||
-12.7 1.000 -9.966 1.000000 0.000000
|
||||
-12.6 1.000 -9.966 1.000000 0.000000
|
||||
-12.5 1.000 -9.966 1.000000 0.000000
|
||||
-12.4 1.000 -9.966 1.000000 0.000000
|
||||
-12.3 1.000 -9.966 1.000000 0.000000
|
||||
-12.2 1.000 -9.966 1.000000 0.000000
|
||||
-12.1 1.000 -9.966 1.000000 0.000000
|
||||
-12.0 1.000 -9.966 1.000000 0.000000
|
||||
-11.9 1.000 -9.966 1.000000 0.000000
|
||||
-11.8 1.000 -9.966 1.000000 0.000000
|
||||
-11.7 1.000 -9.966 1.000000 0.000000
|
||||
-11.6 1.000 -9.966 1.000000 0.000000
|
||||
-11.5 1.000 -9.966 1.000000 0.000000
|
||||
-11.4 1.000 -9.966 1.000000 0.000000
|
||||
-11.3 1.000 -9.966 1.000000 0.000000
|
||||
-11.2 1.000 -9.966 1.000000 0.000000
|
||||
-11.1 1.000 -9.966 1.000000 0.000000
|
||||
-11.0 1.000 -9.966 1.000000 0.000000
|
||||
-10.9 1.000 -9.966 1.000000 0.000000
|
||||
-10.8 1.000 -9.966 1.000000 0.000000
|
||||
-10.7 1.000 -9.966 1.000000 0.000000
|
||||
-10.6 1.000 -9.966 1.000000 0.000000
|
||||
-10.5 1.000 -9.966 1.000000 0.000000
|
||||
-10.4 1.000 -9.966 1.000000 0.000000
|
||||
-10.3 1.000 -9.966 1.000000 0.000000
|
||||
-10.2 1.000 -9.966 1.000000 0.000000
|
||||
-10.1 1.000 -9.966 1.000000 0.000000
|
||||
-10.0 1.000 -9.966 1.000000 0.000000
|
||||
-9.9 1.000 -9.966 1.000000 0.000000
|
||||
-9.8 1.000 -9.966 1.000000 0.000000
|
||||
-9.7 1.000 -9.966 1.000000 0.000000
|
||||
-9.6 1.000 -9.966 1.000000 0.000000
|
||||
-9.5 1.000 -9.966 1.000000 0.000000
|
||||
-9.4 1.000 -9.966 1.000000 0.000000
|
||||
-9.3 1.000 -9.966 1.000000 0.000000
|
||||
-9.2 1.000 -9.966 1.000000 0.000000
|
||||
-9.1 1.000 -9.966 1.000000 0.000000
|
||||
-9.0 1.000 -9.966 1.000000 0.000000
|
||||
-8.9 1.000 -9.966 1.000000 0.000000
|
||||
-8.8 1.000 -9.966 1.000000 0.000000
|
||||
-8.7 1.000 -9.966 1.000000 0.000000
|
||||
-8.6 1.000 -9.966 1.000000 0.000000
|
||||
-8.5 1.000 -9.966 1.000000 0.000000
|
||||
-8.4 1.000 -9.966 1.000000 0.000000
|
||||
-8.3 1.000 -9.966 1.000000 0.000000
|
||||
-8.2 1.000 -9.966 1.000000 0.000000
|
||||
-8.1 1.000 -9.966 1.000000 0.000000
|
||||
-8.0 1.000 -9.966 1.000000 0.000000
|
||||
-7.9 1.000 -9.966 1.000000 0.000000
|
||||
-7.8 1.000 -9.966 1.000000 0.000000
|
||||
-7.7 1.000 -9.966 1.000000 0.000000
|
||||
-7.6 1.000 -9.966 1.000000 0.000000
|
||||
-7.5 1.000 -9.966 1.000000 0.000000
|
||||
-7.4 1.000 -9.966 1.000000 0.000000
|
||||
-7.3 1.000 -9.966 1.000000 0.000000
|
||||
-7.2 1.000 -9.966 1.000000 0.000000
|
||||
-7.1 1.000 -9.966 1.000000 0.000000
|
||||
-7.0 1.000 -9.966 1.000000 0.000000
|
||||
-6.9 1.000 -9.966 1.000000 0.000000
|
||||
-6.8 1.000 -9.966 1.000000 0.000000
|
||||
-6.7 1.000 -9.966 1.000000 0.000000
|
||||
-6.6 1.000 -9.966 1.000000 0.000000
|
||||
-6.5 1.000 -9.966 1.000000 0.000000
|
||||
-6.4 1.000 -9.966 1.000000 0.000000
|
||||
-6.3 1.000 -9.966 1.000000 0.000000
|
||||
-6.2 1.000 -9.966 1.000000 0.000000
|
||||
-6.1 1.000 -9.966 1.000000 0.000000
|
||||
-6.0 1.000 -9.966 1.000000 0.000000
|
||||
-5.9 1.000 -9.966 1.000000 0.000000
|
||||
-5.8 1.000 -9.966 1.000000 0.000000
|
||||
-5.7 1.000 -9.966 1.000000 0.000000
|
||||
-5.6 1.000 -9.966 1.000000 0.000000
|
||||
-5.5 1.000 -9.966 1.000000 0.000000
|
||||
-5.4 1.000 -9.966 1.000000 0.000000
|
||||
-5.3 1.000 -9.966 1.000000 0.000000
|
||||
-5.2 1.000 -9.966 1.000000 0.000000
|
||||
-5.1 1.000 -9.966 1.000000 0.000000
|
||||
-5.0 1.000 -9.966 1.000000 0.000000
|
||||
-4.9 1.000 -9.966 1.000000 0.000000
|
||||
-4.8 1.000 -9.966 1.000000 0.000000
|
||||
-4.7 1.000 -9.966 1.000000 0.000000
|
||||
-4.6 1.000 -9.966 1.000000 0.000000
|
||||
-4.5 1.000 -9.966 1.000000 0.000000
|
||||
-4.4 1.000 -9.966 1.000000 0.000000
|
||||
-4.3 1.000 -9.966 1.000000 0.000000
|
||||
-4.2 1.000 -9.966 1.000000 0.000000
|
||||
-4.1 1.000 -9.966 1.000000 0.000000
|
||||
-4.0 1.000 -9.966 1.000000 0.000000
|
||||
-3.9 1.000 -9.966 1.000000 0.000000
|
||||
-3.8 1.000 -9.966 1.000000 0.000000
|
||||
-3.7 1.000 -9.966 1.000000 0.000000
|
||||
-3.6 1.000 -9.966 1.000000 0.000000
|
||||
-3.5 1.000 -9.966 1.000000 0.000000
|
||||
-3.4 1.000 -9.966 1.000000 0.000000
|
||||
-3.3 1.000 -9.966 1.000000 0.000000
|
||||
-3.2 1.000 -9.966 1.000000 0.000000
|
||||
-3.1 1.000 -9.966 1.000000 0.000000
|
||||
-3.0 1.000 -9.966 1.000000 0.000000
|
||||
-2.9 1.000 -9.966 1.000000 0.000000
|
||||
-2.8 1.000 -9.966 0.999955 0.000045
|
||||
-2.7 1.000 -9.966 0.999968 0.000032
|
||||
-2.6 1.000 -9.966 0.999909 0.000091
|
||||
-2.5 1.000 -9.966 0.999983 0.000017
|
||||
-2.4 1.000 -9.966 0.999937 0.000063
|
||||
-2.3 1.000 -9.966 0.999914 0.000086
|
||||
-2.2 1.000 -9.966 0.999813 0.000187
|
||||
-2.1 1.000 -9.966 0.999775 0.000225
|
||||
-2.0 1.000 -9.966 0.999671 0.000329
|
||||
-1.9 0.999 -9.966 0.999531 0.000469
|
||||
-1.8 0.999 -9.308 0.999211 0.000789
|
||||
-1.7 0.998 -8.893 0.998948 0.001052
|
||||
-1.6 0.998 -8.191 0.998290 0.001710
|
||||
-1.5 0.996 -7.655 0.997519 0.002481
|
||||
-1.4 0.994 -7.037 0.996192 0.003808
|
||||
-1.3 0.992 -6.513 0.994525 0.005475
|
||||
-1.2 0.988 -5.931 0.991804 0.008196
|
||||
-1.1 0.982 -5.359 0.987816 0.012184
|
||||
-1.0 0.974 -4.789 0.981916 0.018084
|
||||
-0.9 0.961 -4.217 0.973110 0.026890
|
||||
-0.8 0.942 -3.672 0.960785 0.039215
|
||||
-0.7 0.915 -3.123 0.942613 0.057387
|
||||
-0.6 0.874 -2.582 0.916477 0.083523
|
||||
-0.5 0.816 -2.062 0.880296 0.119704
|
||||
-0.4 0.734 -1.573 0.831905 0.168095
|
||||
-0.3 0.619 -1.109 0.768168 0.231832
|
||||
-0.2 0.465 -0.690 0.690103 0.309897
|
||||
-0.1 0.260 -0.317 0.598759 0.401241
|
||||
0.0 0.000 0.000 0.500000 0.500000
|
||||
0.1 -0.317 0.260 0.401241 0.598759
|
||||
0.2 -0.690 0.465 0.309897 0.690103
|
||||
0.3 -1.109 0.619 0.231832 0.768168
|
||||
0.4 -1.573 0.734 0.168095 0.831905
|
||||
0.5 -2.062 0.816 0.119704 0.880296
|
||||
0.6 -2.582 0.874 0.083523 0.916477
|
||||
0.7 -3.123 0.915 0.057387 0.942613
|
||||
0.8 -3.672 0.942 0.039215 0.960785
|
||||
0.9 -4.217 0.961 0.026890 0.973110
|
||||
1.0 -4.789 0.974 0.018084 0.981916
|
||||
1.1 -5.359 0.982 0.012184 0.987816
|
||||
1.2 -5.931 0.988 0.008196 0.991804
|
||||
1.3 -6.513 0.992 0.005475 0.994525
|
||||
1.4 -7.037 0.994 0.003808 0.996192
|
||||
1.5 -7.655 0.996 0.002481 0.997519
|
||||
1.6 -8.191 0.998 0.001710 0.998290
|
||||
1.7 -8.893 0.998 0.001052 0.998948
|
||||
1.8 -9.308 0.999 0.000789 0.999211
|
||||
1.9 -9.966 0.999 0.000469 0.999531
|
||||
2.0 -9.966 1.000 0.000329 0.999671
|
||||
2.1 -9.966 1.000 0.000225 0.999775
|
||||
2.2 -9.966 1.000 0.000187 0.999813
|
||||
2.3 -9.966 1.000 0.000086 0.999914
|
||||
2.4 -9.966 1.000 0.000063 0.999937
|
||||
2.5 -9.966 1.000 0.000017 0.999983
|
||||
2.6 -9.966 1.000 0.000091 0.999909
|
||||
2.7 -9.966 1.000 0.000032 0.999968
|
||||
2.8 -9.966 1.000 0.000045 0.999955
|
||||
2.9 -9.966 1.000 0.000000 1.000000
|
||||
3.0 -9.966 1.000 0.000000 1.000000
|
||||
3.1 -9.966 1.000 0.000000 1.000000
|
||||
3.2 -9.966 1.000 0.000000 1.000000
|
||||
3.3 -9.966 1.000 0.000000 1.000000
|
||||
3.4 -9.966 1.000 0.000000 1.000000
|
||||
3.5 -9.966 1.000 0.000000 1.000000
|
||||
3.6 -9.966 1.000 0.000000 1.000000
|
||||
3.7 -9.966 1.000 0.000000 1.000000
|
||||
3.8 -9.966 1.000 0.000000 1.000000
|
||||
3.9 -9.966 1.000 0.000000 1.000000
|
||||
4.0 -9.966 1.000 0.000000 1.000000
|
||||
4.1 -9.966 1.000 0.000000 1.000000
|
||||
4.2 -9.966 1.000 0.000000 1.000000
|
||||
4.3 -9.966 1.000 0.000000 1.000000
|
||||
4.4 -9.966 1.000 0.000000 1.000000
|
||||
4.5 -9.966 1.000 0.000000 1.000000
|
||||
4.6 -9.966 1.000 0.000000 1.000000
|
||||
4.7 -9.966 1.000 0.000000 1.000000
|
||||
4.8 -9.966 1.000 0.000000 1.000000
|
||||
4.9 -9.966 1.000 0.000000 1.000000
|
||||
5.0 -9.966 1.000 0.000000 1.000000
|
||||
5.1 -9.966 1.000 0.000000 1.000000
|
||||
5.2 -9.966 1.000 0.000000 1.000000
|
||||
5.3 -9.966 1.000 0.000000 1.000000
|
||||
5.4 -9.966 1.000 0.000000 1.000000
|
||||
5.5 -9.966 1.000 0.000000 1.000000
|
||||
5.6 -9.966 1.000 0.000000 1.000000
|
||||
5.7 -9.966 1.000 0.000000 1.000000
|
||||
5.8 -9.966 1.000 0.000000 1.000000
|
||||
5.9 -9.966 1.000 0.000000 1.000000
|
||||
6.0 -9.966 1.000 0.000000 1.000000
|
||||
6.1 -9.966 1.000 0.000000 1.000000
|
||||
6.2 -9.966 1.000 0.000000 1.000000
|
||||
6.3 -9.966 1.000 0.000000 1.000000
|
||||
6.4 -9.966 1.000 0.000000 1.000000
|
||||
6.5 -9.966 1.000 0.000000 1.000000
|
||||
6.6 -9.966 1.000 0.000000 1.000000
|
||||
6.7 -9.966 1.000 0.000000 1.000000
|
||||
6.8 -9.966 1.000 0.000000 1.000000
|
||||
6.9 -9.966 1.000 0.000000 1.000000
|
||||
7.0 -9.966 1.000 0.000000 1.000000
|
||||
7.1 -9.966 1.000 0.000000 1.000000
|
||||
7.2 -9.966 1.000 0.000000 1.000000
|
||||
7.3 -9.966 1.000 0.000000 1.000000
|
||||
7.4 -9.966 1.000 0.000000 1.000000
|
||||
7.5 -9.966 1.000 0.000000 1.000000
|
||||
7.6 -9.966 1.000 0.000000 1.000000
|
||||
7.7 -9.966 1.000 0.000000 1.000000
|
||||
7.8 -9.966 1.000 0.000000 1.000000
|
||||
7.9 -9.966 1.000 0.000000 1.000000
|
||||
8.0 -9.966 1.000 0.000000 1.000000
|
||||
8.1 -9.966 1.000 0.000000 1.000000
|
||||
8.2 -9.966 1.000 0.000000 1.000000
|
||||
8.3 -9.966 1.000 0.000000 1.000000
|
||||
8.4 -9.966 1.000 0.000000 1.000000
|
||||
8.5 -9.966 1.000 0.000000 1.000000
|
||||
8.6 -9.966 1.000 0.000000 1.000000
|
||||
8.7 -9.966 1.000 0.000000 1.000000
|
||||
8.8 -9.966 1.000 0.000000 1.000000
|
||||
8.9 -9.966 1.000 0.000000 1.000000
|
||||
9.0 -9.966 1.000 0.000000 1.000000
|
||||
9.1 -9.966 1.000 0.000000 1.000000
|
||||
9.2 -9.966 1.000 0.000000 1.000000
|
||||
9.3 -9.966 1.000 0.000000 1.000000
|
||||
9.4 -9.966 1.000 0.000000 1.000000
|
||||
9.5 -9.966 1.000 0.000000 1.000000
|
||||
9.6 -9.966 1.000 0.000000 1.000000
|
||||
9.7 -9.966 1.000 0.000000 1.000000
|
||||
9.8 -9.966 1.000 0.000000 1.000000
|
||||
9.9 -9.966 1.000 0.000000 1.000000
|
||||
10.0 -9.966 1.000 0.000000 1.000000
|
||||
10.1 -9.966 1.000 0.000000 1.000000
|
||||
10.2 -9.966 1.000 0.000000 1.000000
|
||||
10.3 -9.966 1.000 0.000000 1.000000
|
||||
10.4 -9.966 1.000 0.000000 1.000000
|
||||
10.5 -9.966 1.000 0.000000 1.000000
|
||||
10.6 -9.966 1.000 0.000000 1.000000
|
||||
10.7 -9.966 1.000 0.000000 1.000000
|
||||
10.8 -9.966 1.000 0.000000 1.000000
|
||||
10.9 -9.966 1.000 0.000000 1.000000
|
||||
11.0 -9.966 1.000 0.000000 1.000000
|
||||
11.1 -9.966 1.000 0.000000 1.000000
|
||||
11.2 -9.966 1.000 0.000000 1.000000
|
||||
11.3 -9.966 1.000 0.000000 1.000000
|
||||
11.4 -9.966 1.000 0.000000 1.000000
|
||||
11.5 -9.966 1.000 0.000000 1.000000
|
||||
11.6 -9.966 1.000 0.000000 1.000000
|
||||
11.7 -9.966 1.000 0.000000 1.000000
|
||||
11.8 -9.966 1.000 0.000000 1.000000
|
||||
11.9 -9.966 1.000 0.000000 1.000000
|
||||
12.0 -9.966 1.000 0.000000 1.000000
|
||||
12.1 -9.966 1.000 0.000000 1.000000
|
||||
12.2 -9.966 1.000 0.000000 1.000000
|
||||
12.3 -9.966 1.000 0.000000 1.000000
|
||||
12.4 -9.966 1.000 0.000000 1.000000
|
||||
12.5 -9.966 1.000 0.000000 1.000000
|
||||
12.6 -9.966 1.000 0.000000 1.000000
|
||||
12.7 -9.966 1.000 0.000000 1.000000
|
15
lib/ccf2.f90
15
lib/ccf2.f90
|
@ -1,7 +1,7 @@
|
|||
subroutine ccf2(ss,nz,nflip,ccfbest,lagpk)
|
||||
subroutine ccf2(ss,nz,nflip,ccfbest,xlagpk)
|
||||
|
||||
parameter (LAGMAX=60)
|
||||
! parameter (LAGMAX=200)
|
||||
! parameter (LAGMAX=60)
|
||||
parameter (LAGMAX=200)
|
||||
real ss(nz)
|
||||
real ccf(-LAGMAX:LAGMAX)
|
||||
integer npr(126)
|
||||
|
@ -24,9 +24,9 @@ subroutine ccf2(ss,nz,nflip,ccfbest,lagpk)
|
|||
s0=0.
|
||||
s1=0.
|
||||
do i=1,126
|
||||
j=2*(8*i + 43) + lag
|
||||
j=16*(i-1)+1 + lag
|
||||
if(j.ge.1 .and. j.le.nz-8) then
|
||||
x=ss(j)+ss(j+8) !Add two half-symbol contributions
|
||||
x=ss(j)
|
||||
if(npr(i).eq.0) then
|
||||
s0=s0 + x
|
||||
else
|
||||
|
@ -40,6 +40,9 @@ subroutine ccf2(ss,nz,nflip,ccfbest,lagpk)
|
|||
lagpk=lag
|
||||
endif
|
||||
enddo
|
||||
|
||||
if( lagpk.gt.-LAGMAX .and. lagpk.lt.LAGMAX) then
|
||||
call peakup(ccf(lagpk-1),ccf(lagpk),ccf(lagpk+1),dx)
|
||||
xlagpk=lagpk+dx
|
||||
endif
|
||||
return
|
||||
end subroutine ccf2
|
||||
|
|
|
@ -4,14 +4,13 @@ subroutine decjt9(ss,id2,nutc,nfqso,newdat,npts8,nfa,nfsplit,nfb,ntol, &
|
|||
include 'constants.f90'
|
||||
real ss(184,NSMAX)
|
||||
character*22 msg
|
||||
character*500 infile
|
||||
real*4 ccfred(NSMAX)
|
||||
real*4 red2(NSMAX)
|
||||
logical ccfok(NSMAX)
|
||||
logical done(NSMAX)
|
||||
integer*2 id2(NTMAX*12000)
|
||||
integer*1 i1SoftSymbols(207)
|
||||
common/decstats/num65,numbm,numkv,num9,numfano,infile
|
||||
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
||||
save ccfred,red2
|
||||
|
||||
nsynced=0
|
||||
|
@ -114,10 +113,6 @@ subroutine decjt9(ss,id2,nutc,nfqso,newdat,npts8,nfa,nfsplit,nfb,ntol, &
|
|||
!$omp critical(decode_results) ! serialize writes - see also jt65a.f90
|
||||
write(*,1000) nutc,nsnr,xdt,nint(freq),msg
|
||||
1000 format(i4.4,i4,f5.1,i5,1x,'@',1x,a22)
|
||||
! i1=index(infile,'.wav')
|
||||
! write(*,1000) infile(i1-11:i1-1),nsnr,xdt,nint(freq),msg, &
|
||||
! schk,drift,a3,nlim
|
||||
!1000 format(a11,i4,f5.1,i5,1x,'@',1x,a22,3f6.1,i6)
|
||||
write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg
|
||||
1002 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9')
|
||||
call flush(6)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,sync2,a,dt, &
|
||||
nbmkv,nhist,decoded)
|
||||
subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,ntrials, &
|
||||
naggressive,ndepth,sync2,a,dt,nsf,nhist,decoded)
|
||||
|
||||
! Apply AFC corrections to a candidate JT65 signal, then decode it.
|
||||
|
||||
|
@ -17,35 +17,23 @@ subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,sync2,a,dt, &
|
|||
save
|
||||
|
||||
! Mix sync tone to baseband, low-pass filter, downsample to 1378.125 Hz
|
||||
dt00=dt
|
||||
call timer('filbig ',0)
|
||||
call filbig(dd,npts,f0,newdat,cx,n5,sq0)
|
||||
call timer('filbig ',1)
|
||||
|
||||
! NB: cx has sample rate 12000*77125/672000 = 1378.125 Hz
|
||||
|
||||
! Find best DF, f1, f2, and DT. Start by downsampling to 344.53125 Hz
|
||||
! Find best DF, drift, curvature, and DT. Start by downsampling to 344.53125 Hz
|
||||
call timer('fil6521 ',0)
|
||||
! Add some zeros at start of c5 arrays -- empirical fix for negative DT's
|
||||
nadd=1089
|
||||
c5x(:nadd)=0.
|
||||
call fil6521(cx,n5,c5x(nadd+1),n6)
|
||||
n6=n6+nadd
|
||||
call fil6521(cx,n5,c5x,n6)
|
||||
call timer('fil6521 ',1)
|
||||
|
||||
fsample=1378.125/4.
|
||||
a(5)=dt00
|
||||
i0=nint((a(5)+0.5)*fsample) - 2 + nadd
|
||||
if(i0.lt.1) then
|
||||
i0=1
|
||||
endif
|
||||
nz=n6+1-i0
|
||||
|
||||
! We're looking only at sync tone here... so why not downsample by another
|
||||
! factor of 1/8, say? Should be a significant execution speed-up.
|
||||
call timer('afc65b ',0)
|
||||
! Best fit for DF, f1, and f2
|
||||
call afc65b(c5x(i0),nz,fsample,nflip,a,ccfbest,dtbest)
|
||||
! Best fit for DF, drift, banana-coefficient, and dt. fsample = 344.53125 S/s
|
||||
dtbest=dt
|
||||
call afc65b(c5x,n6,fsample,nflip,a,ccfbest,dtbest)
|
||||
call timer('afc65b ',1)
|
||||
|
||||
sync2=3.7e-4*ccfbest/sq0 !Constant is empirical
|
||||
|
@ -53,26 +41,23 @@ subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,sync2,a,dt, &
|
|||
! Apply AFC corrections to the time-domain signal
|
||||
! Now we are back to using the 1378.125 Hz sample rate, enough to
|
||||
! accommodate the full JT65C bandwidth.
|
||||
|
||||
a(3)=0
|
||||
call timer('twkfreq ',0)
|
||||
call twkfreq65(cx,n5,a)
|
||||
call timer('twkfreq ',1)
|
||||
|
||||
! Compute spectrum for each half symbol.
|
||||
! Adding or subtracting a small number (e.g., 5) to j may make it decode.\
|
||||
! NB: might want to try computing full-symbol spectra (nfft=512, even for
|
||||
! submodes B and C).
|
||||
|
||||
! Compute spectrum for each symbol.
|
||||
nsym=126
|
||||
nfft=512
|
||||
j=(dt00+dtbest+2.685)*1378.125
|
||||
j=int(dtbest*1378.125)
|
||||
if(j.lt.0) j=0
|
||||
|
||||
c5a=cmplx(0.0,0.0)
|
||||
call timer('sh_ffts ',0)
|
||||
do k=1,nsym
|
||||
do i=1,nfft
|
||||
j=j+1
|
||||
c5a(i)=cx(j)
|
||||
if( j .le. NMAX/8 ) c5a(i)=cx(j)
|
||||
enddo
|
||||
call four2a(c5a,nfft,1,1,1)
|
||||
do i=1,66
|
||||
|
@ -85,8 +70,9 @@ subroutine decode65a(dd,npts,newdat,nqd,f0,nflip,mode65,sync2,a,dt, &
|
|||
call timer('sh_ffts ',1)
|
||||
|
||||
call timer('dec65b ',0)
|
||||
call decode65b(s2,nflip,mode65,nqd,nbmkv,nhist,decoded)
|
||||
dt=dt00 + dtbest + 1.7
|
||||
call decode65b(s2,nflip,mode65,ntrials,naggressive,ndepth,nqd,nsf, &
|
||||
nhist,decoded)
|
||||
dt=dtbest !return new, improved estimate of dt
|
||||
call timer('dec65b ',1)
|
||||
|
||||
return
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
subroutine decode65b(s2,nflip,mode65,nqd,nbmkv,nhist,decoded)
|
||||
subroutine decode65b(s2,nflip,mode65,ntrials,naggressive,ndepth,nqd, &
|
||||
nsf,nhist,decoded)
|
||||
|
||||
real s2(66,126)
|
||||
real s3(64,63)
|
||||
|
@ -22,13 +23,15 @@ subroutine decode65b(s2,nflip,mode65,nqd,nbmkv,nhist,decoded)
|
|||
enddo
|
||||
|
||||
nadd=mode65
|
||||
call extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv) !Extract message
|
||||
call extract(s3,nadd,nqd,ntrials,naggressive,ndepth,ncount,nhist, &
|
||||
decoded,ltext,nsf) !Extract the message
|
||||
|
||||
! Suppress "birdie messages" and other garbage decodes:
|
||||
if(decoded(1:7).eq.'000AAA ') ncount=-1
|
||||
if(decoded(1:7).eq.'0L6MWK ') ncount=-1
|
||||
if(nflip.lt.0 .and. ltext) ncount=-1
|
||||
if(ncount.lt.0) then
|
||||
nbmkv=0
|
||||
nsf=0
|
||||
decoded=' '
|
||||
endif
|
||||
|
||||
|
|
|
@ -13,13 +13,21 @@ subroutine decoder(ss,id2,nfsample)
|
|||
ntol,kin,nzhsym,nsubmode,nagain,ndepth,ntxmode,nmode,minw,nclearave, &
|
||||
minsync,emedelay,dttol,nlist,listutc(10),datetime,mycall,mygrid, &
|
||||
hiscall,hisgrid
|
||||
|
||||
common/tracer/limtrace,lu
|
||||
integer onlevel(0:10)
|
||||
common/tracer_priv/level,onlevel
|
||||
!$omp threadprivate(/tracer_priv/)
|
||||
!$omp threadprivate(/tracer_priv/)
|
||||
save
|
||||
|
||||
n2pass=ndepth/100000
|
||||
ndepth=ndepth-n2pass*100000
|
||||
n=ndepth/1000
|
||||
if(mod(n,2).eq.0) ntrials=10**(n/2)
|
||||
if(mod(n,2).eq.1) ntrials=3*10**(n/2)
|
||||
if(n.eq.0) ntrials=0
|
||||
naggressive=(ndepth - (n*1000))/10
|
||||
ndepth=mod(ndepth,10)
|
||||
|
||||
rms=sqrt(dot_product(float(id2(300000:310000)), &
|
||||
float(id2(300000:310000)))/10000.0)
|
||||
if(rms.lt.2.0) go to 800
|
||||
|
@ -55,7 +63,7 @@ subroutine decoder(ss,id2,nfsample)
|
|||
go to 800
|
||||
endif
|
||||
|
||||
ntol65=20
|
||||
ntol65=ntol !### is this OK? ###
|
||||
newdat65=newdat
|
||||
newdat9=newdat
|
||||
|
||||
|
@ -70,7 +78,7 @@ subroutine decoder(ss,id2,nfsample)
|
|||
nf2=nfb
|
||||
call timer('jt65a ',0)
|
||||
call jt65a(dd,npts65,newdat65,nutc,nf1,nf2,nfqso,ntol65,nsubmode, &
|
||||
nagain,ndecoded)
|
||||
minsync,nagain,n2pass,ntrials,naggressive,ndepth,ndecoded)
|
||||
call timer('jt65a ',1)
|
||||
|
||||
else if(nmode.eq.9 .or. (nmode.eq.(65+9) .and. ntxmode.eq.9)) then
|
||||
|
@ -89,7 +97,7 @@ subroutine decoder(ss,id2,nfsample)
|
|||
nf2=nfb
|
||||
call timer('jt65a ',0)
|
||||
call jt65a(dd,npts65,newdat65,nutc,nf1,nf2,nfqso,ntol65,nsubmode, &
|
||||
nagain,ndecoded)
|
||||
minsync,nagain,n2pass,ntrials,naggressive,ndepth,ndecoded)
|
||||
call timer('jt65a ',1)
|
||||
else
|
||||
call timer('decjt9 ',0)
|
||||
|
|
|
@ -27,9 +27,11 @@ subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
|
|||
do j=1,63
|
||||
s1=-1.e30
|
||||
fsum=0.
|
||||
psum=0. ! used for sfrsd metrics
|
||||
do i=1,64
|
||||
x=min(afac*s3(i,j)/ave,50.d0)
|
||||
fs(i)=exp(x)
|
||||
psum=psum+s3(i,j)
|
||||
fsum=fsum+fs(i)
|
||||
if(s3(i,j).gt.s1) then
|
||||
s1=s3(i,j)
|
||||
|
@ -44,8 +46,10 @@ subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
|
|||
i2=i !Second most reliable
|
||||
endif
|
||||
enddo
|
||||
p1=fs(i1)/fsum !Normalized probabilities
|
||||
p2=fs(i2)/fsum
|
||||
! p1=fs(i1)/fsum !Normalized probabilities for kvasd
|
||||
! p2=fs(i2)/fsum
|
||||
p1=s1/psum !Use these for sfrsd
|
||||
p2=s2/psum !
|
||||
mrsym(j)=i1-1
|
||||
mr2sym(j)=i2-1
|
||||
mrprob(j)=scale*p1
|
||||
|
@ -56,7 +60,7 @@ subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
|
|||
do j=1,63
|
||||
if(mrprob(j).le.5) nlow=nlow+1
|
||||
enddo
|
||||
ntest=sum(mrprob)/63.0
|
||||
ntest=sum(mrprob)
|
||||
|
||||
return
|
||||
end subroutine demod64a
|
||||
|
|
|
@ -11,7 +11,7 @@ subroutine ephem(mjd0,dut,east_long,geodetic_lat,height,nspecial, &
|
|||
real*8 rmeTrue(6) !Include nutation
|
||||
real*8 raeTrue(6) !Vector from Earth center to Obs at Date
|
||||
real*8 rmaTrue(6) !Vector from Obs to Moon at Date
|
||||
logical km,bary,jplok !Set km=.true. to get km, km/s from ephemeris
|
||||
logical km,bary !Set km=.true. to get km, km/s from ephemeris
|
||||
common/stcomx/km,bary,pvsun(6) !Common used in JPL subroutines
|
||||
common/librcom/xl(2),b(2)
|
||||
|
||||
|
@ -32,8 +32,6 @@ subroutine ephem(mjd0,dut,east_long,geodetic_lat,height,nspecial, &
|
|||
djtt=mjd + sla_DTT(jd)/86400.d0
|
||||
ttjd=jd + sla_DTT(jd)/86400.d0
|
||||
|
||||
! inquire(file='JPLEPH',exist=jplok)
|
||||
! if(jplok) then
|
||||
if(nspecial.ne.8) then
|
||||
call pleph(ttjd,10,3,rme2000) !RME (J2000) from JPL ephemeris
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
subroutine extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)
|
||||
subroutine extract(s3,nadd,nqd,ntrials,naggressive,ndepth,ncount,nhist, &
|
||||
decoded,ltext,nsf)
|
||||
|
||||
! Input:
|
||||
! s3 64-point spectra for each of 63 data symbols
|
||||
|
@ -10,7 +11,7 @@ subroutine extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)
|
|||
! nhist maximum number of identical symbol values
|
||||
! decoded decoded message (if ncount >=0)
|
||||
! ltext true if decoded message is free text
|
||||
! nbmkv 0=no decode; 1=BM decode; 2=KV decode
|
||||
! nsf 0=no decode; 1=BM decode; 2=KV decode
|
||||
|
||||
use prog_args !shm_key, exe_dir, data_dir
|
||||
use packjt
|
||||
|
@ -19,29 +20,26 @@ subroutine extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)
|
|||
character decoded*22
|
||||
integer dat4(12)
|
||||
integer mrsym(63),mr2sym(63),mrprob(63),mr2prob(63)
|
||||
integer correct(63),tmp(63)
|
||||
integer param(0:7)
|
||||
integer indx(0:62)
|
||||
real*8 tt
|
||||
logical nokv,ltext
|
||||
common/decstats/num65,numbm,numkv,num9,numfano
|
||||
common/chansyms65/correct
|
||||
data nokv/.false./,nsec1/0/
|
||||
save
|
||||
|
||||
nbirdie=7
|
||||
npct=40
|
||||
afac1=10.1
|
||||
xlambda=7.999
|
||||
if(nqd.eq.1) xlambda=11.999 !Increase depth at QSO frequency
|
||||
nbmkv=0
|
||||
nbirdie=20
|
||||
npct=50
|
||||
afac1=1.1
|
||||
nsf=0
|
||||
nfail=0
|
||||
decoded=' '
|
||||
call pctile(s3,4032,npct,base)
|
||||
s3=s3/base
|
||||
|
||||
! Get most reliable and second-most-reliable symbol values, and their
|
||||
! probabilities
|
||||
1 call demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
|
||||
if(ntest.lt.100) then
|
||||
ncount=-999 !Flag and reject bad data
|
||||
go to 900
|
||||
endif
|
||||
|
||||
call chkhist(mrsym,nhist,ipk) !Test for birdies and QRM
|
||||
if(nhist.ge.nbirdie) then
|
||||
|
@ -59,63 +57,46 @@ subroutine extract(s3,nadd,nqd,ncount,nhist,decoded,ltext,nbmkv)
|
|||
call graycode65(mrsym,63,-1) !Remove gray code
|
||||
call interleave63(mrsym,-1) !Remove interleaving
|
||||
call interleave63(mrprob,-1)
|
||||
num65=num65+1
|
||||
|
||||
! Decode using Berlekamp-Massey algorithm
|
||||
call timer('rs_decod',0)
|
||||
call rs_decode(mrsym,0,0,dat4,ncount)
|
||||
call timer('rs_decod',1)
|
||||
if(ncount.ge.0) then
|
||||
call unpackmsg(dat4,decoded)
|
||||
if(iand(dat4(10),8).ne.0) ltext=.true.
|
||||
nbmkv=1
|
||||
go to 900
|
||||
endif
|
||||
|
||||
! Berlekamp-Massey algorithm failed, try Koetter-Vardy
|
||||
if(nokv) go to 900
|
||||
|
||||
maxe=8 !Max KV errors in 12 most reliable symbols
|
||||
call graycode65(mr2sym,63,-1) !Remove gray code and interleaving
|
||||
call interleave63(mr2sym,-1) !from second-most-reliable symbols
|
||||
call interleave63(mr2prob,-1)
|
||||
|
||||
nsec1=nsec1+1
|
||||
dat4=0
|
||||
write(22,rec=1) nsec1,xlambda,maxe,200,mrsym,mrprob,mr2sym,mr2prob
|
||||
write(22,rec=2) -1,-1,dat4
|
||||
call flush(22)
|
||||
call timer('kvasd ',0)
|
||||
nverbose=0
|
||||
ntry=0
|
||||
call timer('sfrsd ',0)
|
||||
call sfrsd2(mrsym,mrprob,mr2sym,mr2prob,ntrials,nverbose,correct, &
|
||||
param,indx,tt,ntry)
|
||||
call timer('sfrsd ',1)
|
||||
ncandidates=param(0)
|
||||
nhard=param(1)
|
||||
nsoft=param(2)
|
||||
nera=param(3)
|
||||
ngmd=param(4)
|
||||
ndone=ndone+1
|
||||
do i=1,12
|
||||
dat4(i)=correct(13-i)
|
||||
enddo
|
||||
|
||||
#ifdef WIN32
|
||||
iret=system('""'//trim(exe_dir)//'/kvasd" "'//trim(temp_dir)//'/kvasd.dat" >"'//trim(temp_dir)//'/dev_null""')
|
||||
#else
|
||||
iret=system('"'//trim(exe_dir)//'/kvasd" "'//trim(temp_dir)//'/kvasd.dat" >/dev/null')
|
||||
#endif
|
||||
|
||||
call timer('kvasd ',1)
|
||||
if(iret.ne.0) then
|
||||
if(.not.nokv) write(*,1000) iret
|
||||
1000 format('Error in KV decoder, or no KV decoder present.',i12)
|
||||
! nokv=.true.
|
||||
go to 900
|
||||
endif
|
||||
|
||||
read(22,rec=2,err=900) nsec2,ncount,dat4
|
||||
j=nsec2 !Silence compiler warning
|
||||
ncount=-1
|
||||
decoded=' '
|
||||
ltext=.false.
|
||||
if(ncount.ge.0) then
|
||||
if(nhard.ge.0) then
|
||||
!turn the corrected symbol array into channel symbols for subtraction
|
||||
!pass it back to jt65a via common block "chansyms65"
|
||||
do i=1,63
|
||||
tmp(i)=correct(64-i)
|
||||
enddo
|
||||
correct(1:63)=tmp(1:63)
|
||||
call interleave63(correct,63,1)
|
||||
call graycode65(correct,63,1)
|
||||
call unpackmsg(dat4,decoded) !Unpack the user message
|
||||
if(index(decoded,'...... ').gt.0) then
|
||||
ncount=-1
|
||||
go to 900
|
||||
endif
|
||||
ncount=0
|
||||
if(iand(dat4(10),8).ne.0) ltext=.true.
|
||||
nbmkv=2
|
||||
nsf=1
|
||||
endif
|
||||
|
||||
900 continue
|
||||
|
||||
return
|
||||
end subroutine extract
|
||||
|
|
@ -12,11 +12,11 @@ subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat, &
|
|||
integer mettab(-128:127,0:1) !Metric table
|
||||
|
||||
! These were the "node" structure in Karn's C code:
|
||||
integer nstate(0:MAXBITS-1) !Encoder state of next node
|
||||
integer gamma(0:MAXBITS-1) !Cumulative metric to this node
|
||||
integer metrics(0:3,0:MAXBITS-1) !Metrics indexed by all possible Tx syms
|
||||
integer tm(0:1,0:MAXBITS-1) !Sorted metrics for current hypotheses
|
||||
integer ii(0:MAXBITS-1) !Current branch being tested
|
||||
integer nstate(0:MAXBITS) !Encoder state of next node
|
||||
integer gamma(0:MAXBITS) !Cumulative metric to this node
|
||||
integer metrics(0:3,0:MAXBITS) !Metrics indexed by all possible Tx syms
|
||||
integer tm(0:1,0:MAXBITS) !Sorted metrics for current hypotheses
|
||||
integer ii(0:MAXBITS) !Current branch being tested
|
||||
|
||||
logical noback
|
||||
include 'conv232.f90' !Polynomials defined here
|
||||
|
@ -69,7 +69,7 @@ subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat, &
|
|||
gamma(np+1)=ngamma !Move forward
|
||||
nstate(np+1)=ishft(nstate(np),1)
|
||||
np=np+1
|
||||
if(np.eq.nbits-1) go to 100 !We're done!
|
||||
if(np.eq.nbits) go to 100 !We're done!
|
||||
|
||||
n=iand(nstate(np),npoly1)
|
||||
n=ieor(n,ishft(n,-16))
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
subroutine fast9(id2,narg,line)
|
||||
|
||||
! Decoder for "fast9" modes, JT9E to JT9H.
|
||||
|
||||
parameter (NMAX=30*12000,NSAVE=500)
|
||||
integer*2 id2(0:NMAX)
|
||||
integer narg(0:11)
|
||||
integer*1 i1SoftSymbols(207)
|
||||
integer*1 i1save(207,NSAVE)
|
||||
integer indx(NSAVE)
|
||||
integer*8 count0,count1,clkfreq
|
||||
real s1(720000) !To reserve space. Logically s1(nq,jz)
|
||||
real s2(240,340) !Symbol spectra at quarter-symbol steps
|
||||
real ss2(0:8,85) !Folded symbol spectra
|
||||
real ss3(0:7,69) !Folded spectra without sync symbols
|
||||
real s(1500)
|
||||
real ccfsave(NSAVE)
|
||||
real t0save(NSAVE)
|
||||
real t1save(NSAVE)
|
||||
real freqSave(NSAVE)
|
||||
real t(6)
|
||||
character*22 msg !Decoded message
|
||||
character*80 line(100)
|
||||
data nsubmode0/-1/,ntot/0/
|
||||
save s1,nsubmode0,ntot
|
||||
|
||||
! Parameters from GUI are in narg():
|
||||
nutc=narg(0) !UTC
|
||||
npts=min(narg(1),NMAX) !Number of samples in id2 (12000 Hz)
|
||||
nsubmode=narg(2) !0=A 1=B 2=C 3=D 4=E 5=F 6=G 7=H
|
||||
if(nsubmode.lt.4) go to 900
|
||||
newdat=narg(3) !1==> new data, compute symbol spectra
|
||||
minsync=narg(4) !Lower sync limit
|
||||
npick=narg(5)
|
||||
t0=0.001*narg(6)
|
||||
t1=0.001*narg(7)
|
||||
maxlines=narg(8) !Max # of decodes to return to caller
|
||||
nmode=narg(9)
|
||||
nrxfreq=narg(10) !Targer Rx audio frequency (Hz)
|
||||
ntol=narg(11) !Search range, +/- ntol (Hz)
|
||||
|
||||
tmid=npts*0.5/12000.0
|
||||
line(1:100)(1:1)=char(0)
|
||||
s=0
|
||||
s2=0
|
||||
nsps=60 * 2**(7-nsubmode) !Samples per sysbol
|
||||
nfft=2*nsps !FFT size
|
||||
nh=nfft/2
|
||||
nq=nfft/4
|
||||
istep=nsps/4 !Symbol spectra at quarter-symbol steps
|
||||
jz=npts/istep
|
||||
df=12000.0/nfft !FFT bin width
|
||||
db1=db(2500.0/df)
|
||||
nfa=max(200,nrxfreq-ntol) !Lower frequency limit
|
||||
nfb=min(nrxfreq+ntol,2500) !Upper frequency limit
|
||||
nline=0
|
||||
t=0.
|
||||
|
||||
if(newdat.eq.1 .or. nsubmode.ne.nsubmode0) then
|
||||
call system_clock(count0,clkfreq)
|
||||
call spec9f(id2,npts,nsps,s1,jz,nq) !Compute symbol spectra, s1
|
||||
call system_clock(count1,clkfreq)
|
||||
t(1)=t(1)+float(count1-count0)/float(clkfreq)
|
||||
endif
|
||||
|
||||
nsubmode0=nsubmode
|
||||
tmsg=nsps*85.0/12000.0
|
||||
limit=2000
|
||||
nlen0=0
|
||||
i1=0
|
||||
i2=0
|
||||
ccfsave=0.
|
||||
do ilength=1,14
|
||||
nlen=1.4142136**(ilength-1)
|
||||
if(nlen.gt.jz/340) nlen=jz/340
|
||||
if(nlen.eq.nlen0) cycle
|
||||
nlen0=nlen
|
||||
|
||||
db0=db(float(nlen))
|
||||
jlen=nlen*340
|
||||
jstep=jlen/4 !### Is this about right? ###
|
||||
if(nsubmode.ge.6) jstep=jlen/2
|
||||
|
||||
do ja=1,jz-jlen,jstep
|
||||
jb=ja+jlen-1
|
||||
call system_clock(count0,clkfreq)
|
||||
call foldspec9f(s1,nq,jz,ja,jb,s2) !Fold symbol spectra into s2
|
||||
call system_clock(count1,clkfreq)
|
||||
t(2)=t(2)+float(count1-count0)/float(clkfreq)
|
||||
|
||||
! Find sync; put sync'ed symbol spectra into ss2 and ss3
|
||||
! Might want to do a peakup in DT and DF, then re-compute symbol spectra.
|
||||
|
||||
call system_clock(count0,clkfreq)
|
||||
call sync9f(s2,nq,nfa,nfb,ss2,ss3,lagpk,ipk,ccfbest)
|
||||
call system_clock(count1,clkfreq)
|
||||
t(3)=t(3)+float(count1-count0)/float(clkfreq)
|
||||
|
||||
i1=i1+1
|
||||
if(ccfbest.lt.30.0) cycle
|
||||
call system_clock(count0,clkfreq)
|
||||
call softsym9f(ss2,ss3,i1SoftSymbols) !Compute soft symbols
|
||||
call system_clock(count1,clkfreq)
|
||||
t(4)=t(4)+float(count1-count0)/float(clkfreq)
|
||||
|
||||
i2=i2+1
|
||||
ccfsave(i2)=ccfbest
|
||||
i1save(1:207,i2)=i1SoftSymbols
|
||||
t0=(ja-1)*istep/12000.0
|
||||
t1=(jb-1)*istep/12000.0
|
||||
t0save(i2)=t0
|
||||
t1save(i2)=t1
|
||||
freq=ipk*df
|
||||
freqSave(i2)=freq
|
||||
enddo
|
||||
enddo
|
||||
nsaved=i2
|
||||
|
||||
ccfsave(1:nsaved)=-ccfsave(1:nsaved)
|
||||
call system_clock(count0,clkfreq)
|
||||
indx=0
|
||||
call indexx(ccfsave,nsaved,indx)
|
||||
call system_clock(count1,clkfreq)
|
||||
t(5)=t(5)+float(count1-count0)/float(clkfreq)
|
||||
|
||||
ccfsave(1:nsaved)=-ccfsave(1:nsaved)
|
||||
|
||||
do iter=1,2
|
||||
! do isave=1,nsaved
|
||||
do isave=1,50
|
||||
i2=indx(isave)
|
||||
if(i2.lt.1 .or. i2.gt.nsaved) cycle !### Why needed? ###
|
||||
t0=t0save(i2)
|
||||
t1=t1save(i2)
|
||||
if(iter.eq.1 .and. t1.lt.tmid) cycle
|
||||
if(iter.eq.2 .and. t1.ge.tmid) cycle
|
||||
ccfbest=ccfsave(i2)
|
||||
i1SoftSymbols=i1save(1:207,i2)
|
||||
freq=freqSave(i2)
|
||||
call system_clock(count0,clkfreq)
|
||||
call jt9fano(i1SoftSymbols,limit,nlim,msg) !Invoke Fano decoder
|
||||
call system_clock(count1,clkfreq)
|
||||
t(6)=t(6)+float(count1-count0)/float(clkfreq)
|
||||
|
||||
i=t0*12000.0
|
||||
kz=(t1-t0)/0.02
|
||||
smax=0.
|
||||
do k=1,kz
|
||||
sq=0.
|
||||
do n=1,240
|
||||
i=i+1
|
||||
x=id2(i)
|
||||
sq=sq+x*x
|
||||
enddo
|
||||
s(k)=sq/240.
|
||||
smax=max(s(k),smax)
|
||||
enddo
|
||||
call pctile(s,kz,35,base)
|
||||
snr=smax/(1.1*base) - 1.0
|
||||
nsnr=-20
|
||||
if(snr.gt.0.0) nsnr=nint(db(snr))
|
||||
|
||||
! write(72,3002) nutc,iter,isave,nlen,tmid,t0,t1,ccfbest, &
|
||||
! nint(freq),nlim,msg
|
||||
!3002 format(i6.6,i1,i4,i3,4f6.1,i5,i7,1x,a22)
|
||||
|
||||
if(msg.ne.' ') then
|
||||
|
||||
! Display multiple decodes only if they differ:
|
||||
do n=1,nline
|
||||
if(index(line(n),msg).gt.1) go to 100
|
||||
enddo
|
||||
!### Might want to use decoded message to get a complete estimate of S/N.
|
||||
nline=nline+1
|
||||
write(line(nline),1000) nutc,nsnr,t0,nint(freq),msg,char(0)
|
||||
1000 format(i6.6,i4,f5.1,i5,1x,'@',1x,a22,a1)
|
||||
ntot=ntot+1
|
||||
! write(70,5001) nsaved,isave,nline,maxlines,ntot,nutc,msg
|
||||
!5001 format(5i5,i7.6,1x,a22)
|
||||
if(nline.ge.maxlines) go to 900
|
||||
endif
|
||||
100 continue
|
||||
enddo
|
||||
enddo
|
||||
|
||||
900 continue
|
||||
! write(*,6001) t,t(6)/sum(t)
|
||||
!6001 format(7f10.3)
|
||||
|
||||
return
|
||||
end subroutine fast9
|
|
@ -0,0 +1,79 @@
|
|||
subroutine fast_decode(id2,narg,line)
|
||||
|
||||
parameter (NMAX=30*12000)
|
||||
integer*2 id2(NMAX)
|
||||
integer narg(0:9)
|
||||
real dat(30*12000)
|
||||
complex cdat(262145),cdat2(262145)
|
||||
real psavg(450)
|
||||
logical pick
|
||||
character*6 cfile6
|
||||
character*80 line(100)
|
||||
save npts
|
||||
|
||||
nutc=narg(0)
|
||||
ndat0=narg(1)
|
||||
nsubmode=narg(2)
|
||||
newdat=narg(3)
|
||||
minsync=narg(4)
|
||||
npick=narg(5)
|
||||
t0=0.001*narg(6)
|
||||
t1=0.001*narg(7)
|
||||
maxlines=narg(8)
|
||||
nmode=narg(9)
|
||||
|
||||
! call sleep_msec(100) !### TEMPORARY ###
|
||||
|
||||
if(nmode.eq.102) then
|
||||
call fast9(id2,narg,line)
|
||||
go to 900
|
||||
else if(nmode.eq.103) then
|
||||
call jtmsk(id2,narg,line)
|
||||
go to 900
|
||||
endif
|
||||
|
||||
if(newdat.eq.1) then
|
||||
cdat2=cdat
|
||||
ndat=ndat0
|
||||
call wav11(id2,ndat,dat)
|
||||
ndat=min(ndat,30*11025)
|
||||
call ana932(dat,ndat,cdat,npts) !Make downsampled analytic signal
|
||||
endif
|
||||
|
||||
! Now cdat() is the downsampled analytic signal.
|
||||
! New sample rate = fsample = BW = 11025 * (9/32) = 3100.78125 Hz
|
||||
! NB: npts, nsps, etc., are all reduced by 9/32
|
||||
|
||||
write(cfile6,'(i6.6)') nutc
|
||||
ntol=400
|
||||
nfreeze=1
|
||||
mousedf=0
|
||||
mousebutton=0
|
||||
mode4=1
|
||||
if(nsubmode.eq.1) mode4=2
|
||||
nafc=0
|
||||
ndebug=0
|
||||
t2=0.
|
||||
ia=1
|
||||
ib=npts
|
||||
pick=.false.
|
||||
|
||||
if(npick.gt.0) then
|
||||
pick=.true.
|
||||
dt=1.0/11025.0 * (32.0/9.0)
|
||||
ia=t0/dt + 1.
|
||||
ib=t1/dt + 1.
|
||||
t2=t0
|
||||
endif
|
||||
jz=ib-ia+1
|
||||
line(1:100)(1:1)=char(0)
|
||||
if(npick.eq.2) then
|
||||
call iscat(cdat2(ia),jz,3,40,t2,pick,cfile6,minsync,ntol,NFreeze, &
|
||||
MouseDF,mousebutton,mode4,nafc,ndebug,psavg,nmax,nlines,line)
|
||||
else
|
||||
call iscat(cdat(ia),jz,3,40,t2,pick,cfile6,minsync,ntol,NFreeze, &
|
||||
MouseDF,mousebutton,mode4,nafc,ndebug,psavg,maxlines,nlines,line)
|
||||
endif
|
||||
|
||||
900 return
|
||||
end subroutine fast_decode
|
|
@ -39,30 +39,28 @@ real function fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
|
|||
enddo
|
||||
endif
|
||||
|
||||
! Compute 1/2-symbol powers at 1/16-symbol steps.
|
||||
! Compute whole-symbol powers at 1/16-symbol steps.
|
||||
fac=1.e-4
|
||||
|
||||
do i=1,nout
|
||||
j=i*nsps/ndiv
|
||||
k=j-nsph
|
||||
j=nsps+(i-1)*nsps/16 !steps by 8 samples (1/16 of a symbol)
|
||||
k=j-nsps
|
||||
ss(i)=0.
|
||||
if(k.ge.1) then
|
||||
z=csx(j)-csx(k)
|
||||
if(k.ge.0) then
|
||||
z=csx(j)-csx(k) ! difference over span of 128 pts
|
||||
ss(i)=fac*(real(z)**2 + aimag(z)**2)
|
||||
endif
|
||||
enddo
|
||||
|
||||
ccfmax=0.
|
||||
call timer('ccf2 ',0)
|
||||
call ccf2(ss,nout,nflip,ccf,lagpk)
|
||||
call ccf2(ss,nout,nflip,ccf,xlagpk)
|
||||
call timer('ccf2 ',1)
|
||||
if(ccf.gt.ccfmax) then
|
||||
ccfmax=ccf
|
||||
dtmax=lagpk*dtstep
|
||||
dtmax=xlagpk*dtstep
|
||||
endif
|
||||
fchisq65=-ccfmax
|
||||
|
||||
call timer('fchisq65',1)
|
||||
|
||||
return
|
||||
end function fchisq65
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
program fixwav
|
||||
|
||||
use wavhdr
|
||||
parameter (NBANDS=23,NMODES=11)
|
||||
parameter(NMAX=120*12000)
|
||||
type(hdr) h
|
||||
integer*2 id2(NMAX),id(4)
|
||||
character*8 mode,mode0
|
||||
character*6 band
|
||||
character*12 arg
|
||||
character*80 infile
|
||||
character*1 c
|
||||
logical ok
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.1 .and. nargs.ne.5) then
|
||||
print*,'Usage: fixwav [fMHz mode submode TRperiod] infile'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,infile)
|
||||
if(nargs.eq.1) go to 10
|
||||
read(infile,*) fMHz
|
||||
call getarg(2,mode0)
|
||||
call getarg(3,arg)
|
||||
nsubmode0=-1
|
||||
do i=1,8
|
||||
if(arg(1:1).eq.char(ichar('A')-1+i)) nsubmode0=i
|
||||
enddo
|
||||
if(nsubmode0.lt.0) read(arg,*) nsubmode0
|
||||
call getarg(4,arg)
|
||||
read(arg,*) ntrperiod0
|
||||
call getarg(5,infile)
|
||||
|
||||
10 open(10,file=infile,status='old',access='stream')
|
||||
read(10) h
|
||||
npts=h%ndata/2
|
||||
nfsample=h%nsamrate
|
||||
read(10) id2(1:npts)
|
||||
write(*,1002) h%nchan2,h%nbitsam2,h%nsamrate,npts
|
||||
1002 format('Channels:',i2,' Bits/sample:',i3,' Sample rate:',i6, &
|
||||
' Npts:',i8)
|
||||
|
||||
call get_wsjtx_wav_params(id2,band,mode,nsubmode,ntrperiod,ok)
|
||||
if(nfsample.ne.11025 .and. nfsample.ne.12000) ok=.false.
|
||||
if(ok) write(*,1010) band,ntrperiod,mode,char(ichar('A')-1+id2(3))
|
||||
1010 format('Band: ',a6,' T/R period:',i4,' Mode: ',a8,1x,a1)
|
||||
|
||||
if(.not.ok) write(*,'(a)') 'File has no valid WSJT-X params.'
|
||||
if(ok .and. nargs.eq.1) go to 999
|
||||
|
||||
write(*,'(a)',advance='no') 'Do you want to add or change them? (Y/N): '
|
||||
read*,c
|
||||
if(c.ne.'y' .and. c.ne.'Y') go to 999
|
||||
|
||||
print*,fMHz,mode0,nsubmode0,ntrperiod0
|
||||
call set_wsjtx_wav_params(fMHz,mode0,nsubmode0,ntrperiod0,id2)
|
||||
band=""
|
||||
mode=""
|
||||
nsubmode=0
|
||||
ntrperiod=0
|
||||
call get_wsjtx_wav_params(id2,band,mode,nsubmode,ntrperiod,ok)
|
||||
write(*,1010) band,ntrperiod,mode,char(ichar('A')-1+id2(3))
|
||||
rewind 10
|
||||
write(10) h,id2(1:npts)
|
||||
|
||||
999 end program fixwav
|
|
@ -22,7 +22,7 @@ subroutine flat4(s,npts0,nflatten)
|
|||
nlen=npts/nseg !Length of test segment
|
||||
i0=npts/2 !Midpoint
|
||||
k=0
|
||||
do n=2,nseg !Skip first segment, likely rolloff here
|
||||
do n=1,nseg !Skip first segment, likely rolloff here
|
||||
ib=n*nlen
|
||||
ia=ib-nlen+1
|
||||
if(n.eq.nseg) ib=npts
|
||||
|
@ -37,7 +37,7 @@ subroutine flat4(s,npts0,nflatten)
|
|||
enddo
|
||||
kz=k
|
||||
a=0.
|
||||
nterms=3
|
||||
nterms=5
|
||||
|
||||
call polyfit(x,y,y,kz,nterms,0,a,chisqr) !Fit a low-order polynomial
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
subroutine foldspec9f(s1,nq,jz,ja,jb,s2)
|
||||
|
||||
! Fold symbol spectra (quarter-symbol steps) from s1 into s2
|
||||
|
||||
real s1(nq,jz)
|
||||
real s2(240,340) !340 = 4*85
|
||||
integer nsum(340)
|
||||
|
||||
s2=0.
|
||||
nsum=0
|
||||
|
||||
do j=ja,jb
|
||||
k=mod(j-1,340)+1
|
||||
nsum(k)=nsum(k)+1
|
||||
do i=1,NQ
|
||||
s2(i,k)=s2(i,k) + s1(i,j)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
do k=1,340
|
||||
fac=1.0
|
||||
if(nsum(k).gt.0) fac=1.0/nsum(k)
|
||||
s2(1:nq,k)=fac*s2(1:nq,k)
|
||||
enddo
|
||||
|
||||
ave=sum(s2)/(340.0*nq)
|
||||
if(ave.gt.0.0) s2=s2/ave
|
||||
|
||||
return
|
||||
end subroutine foldspec9f
|
|
@ -0,0 +1,55 @@
|
|||
subroutine geniscat(msg,msgsent,itone)
|
||||
|
||||
! Generate an ISCAT waveform.
|
||||
|
||||
parameter (NSZ=1291)
|
||||
character msg*28,msgsent*28 !Message to be transmitted
|
||||
integer imsg(30)
|
||||
integer itone(NSZ)
|
||||
real*8 sps
|
||||
character c*42
|
||||
integer icos(4) !Costas array
|
||||
data icos/0,1,3,2/
|
||||
data nsync/4/,nlen/2/,ndat/18/
|
||||
data c/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /.?@-'/
|
||||
|
||||
sps=256.d0*12000.d0/11025.d0
|
||||
nsym=int(30*12000.d0/sps)
|
||||
nblk=nsync+nlen+ndat
|
||||
|
||||
do i=22,1,-1
|
||||
if(msg(i:i).ne.' ' .and. msg(i:i).ne.char(0)) exit
|
||||
enddo
|
||||
nmsg=i
|
||||
msglen=nmsg+1
|
||||
k=0
|
||||
kk=1
|
||||
imsg(1)=40 !Always start with BOM char: '@'
|
||||
do i=1,nmsg !Define the tone sequence
|
||||
imsg(i+1)=36 !Illegal char set to blank
|
||||
do j=1,42
|
||||
if(msg(i:i).eq.c(j:j)) imsg(i+1)=j-1
|
||||
enddo
|
||||
enddo
|
||||
|
||||
do i=1,nsym !Total symbols in 30 s
|
||||
j=mod(i-1,nblk)+1
|
||||
if(j.le.nsync) then
|
||||
itone(i)=icos(j) !Insert 4x4 Costas array
|
||||
else if(j.gt.nsync .and. j.le.nsync+nlen) then
|
||||
itone(i)=msglen !Insert message-length indicator
|
||||
if(j.ge.nsync+2) then
|
||||
n=msglen + 5*(j-nsync-1)
|
||||
if(n.gt.41) n=n-42
|
||||
itone(i)=n
|
||||
endif
|
||||
else
|
||||
k=k+1
|
||||
kk=mod(k-1,msglen)+1
|
||||
itone(i)=imsg(kk)
|
||||
endif
|
||||
enddo
|
||||
msgsent=msg
|
||||
|
||||
return
|
||||
end subroutine geniscat
|
|
@ -0,0 +1,100 @@
|
|||
subroutine genmsk(msg0,ichk,msgsent,i4tone,itype)
|
||||
|
||||
! Encode a JTMSK message
|
||||
! Input:
|
||||
! - msg0 requested message to be transmitted
|
||||
! - ichk if nonzero, return only msgsent
|
||||
! - msgsent message as it will be decoded
|
||||
! - i4tone array of audio tone values, 0 or 1
|
||||
! - itype message type
|
||||
! 1 = standard message <call1> <call2> <grid/rpt>
|
||||
! 2 = type 1 prefix
|
||||
! 3 = type 1 suffix
|
||||
! 4 = type 2 prefix
|
||||
! 5 = type 2 suffix
|
||||
! 6 = free text (up to 13 characters)
|
||||
|
||||
use iso_c_binding, only: c_loc,c_size_t
|
||||
use packjt
|
||||
use hashing
|
||||
character*22 msg0
|
||||
character*22 message !Message to be generated
|
||||
character*22 msgsent !Message as it will be received
|
||||
integer*4 i4Msg6BitWords(13) !72-bit message as 6-bit words
|
||||
integer*1, target:: i1Msg8BitBytes(13) !72 bits and zero tail as 8-bit bytes
|
||||
integer*1 e1(198) !Encoded bits before re-ordering
|
||||
integer*1 i1EncodedBits(198) !Encoded information-carrying bits
|
||||
integer i4tone(234) !Tone #s, data and sync (values 0-1)
|
||||
integer*1 i1hash(4)
|
||||
integer b11(11)
|
||||
data b11/1,1,1,0,0,0,1,0,0,1,0/ !Barker 11 code
|
||||
equivalence (ihash,i1hash)
|
||||
save
|
||||
|
||||
if(msg0(1:1).eq.'@') then !Generate a fixed tone
|
||||
read(msg0(2:5),*,end=1,err=1) nfreq !at specified frequency
|
||||
go to 2
|
||||
1 nfreq=1000
|
||||
2 i4tone(1)=nfreq
|
||||
else
|
||||
message=msg0
|
||||
do i=1,22
|
||||
if(ichar(message(i:i)).eq.0) then
|
||||
message(i:)=' '
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
|
||||
do i=1,22 !Strip leading blanks
|
||||
if(message(1:1).ne.' ') exit
|
||||
message=message(i+1:)
|
||||
enddo
|
||||
|
||||
call packmsg(message,i4Msg6BitWords,itype) !Pack into 12 6-bit bytes
|
||||
call unpackmsg(i4Msg6BitWords,msgsent) !Unpack to get msgsent
|
||||
if(ichk.ne.0) go to 999
|
||||
call entail(i4Msg6BitWords,i1Msg8BitBytes) !Add tail, make 8-bit bytes
|
||||
ihash=nhash(c_loc(i1Msg8BitBytes),int(9,c_size_t),146)
|
||||
ihash=2*iand(ihash,32767) !Generate the CRC
|
||||
i1Msg8BitBytes(10)=i1hash(2) !CRC to bytes 10 and 11
|
||||
i1Msg8BitBytes(11)=i1hash(1)
|
||||
|
||||
nsym=198 !(72+12+15)*2 = 198
|
||||
kc=13
|
||||
nc=2
|
||||
nbits=87
|
||||
call enc213(i1Msg8BitBytes,nbits,e1,nsym,kc,nc) !Encode the message
|
||||
|
||||
j=0
|
||||
do i=1,nsym/2 !Reorder the encoded bits
|
||||
j=j+1
|
||||
i1EncodedBits(j)=e1(2*i-1)
|
||||
i1EncodedBits(j+99)=e1(2*i)
|
||||
enddo
|
||||
|
||||
! Insert three Barker 11 codes and three "even-f0-parity" bits
|
||||
i4tone=0 !Start with all 0's
|
||||
n1=35
|
||||
n2=69
|
||||
n3=94
|
||||
i4tone(1:11)=b11 !11 sync bits
|
||||
i4tone(11+1:11+n1)=i1EncodedBits(1:n1) !n1 data bits
|
||||
nn1=count(i4tone(11+1:11+n1).eq.0) !Count the 0's
|
||||
if(mod(nn1,2).eq.0) i4tone(12+n1)=1 !1 parity bit
|
||||
|
||||
i4tone(13+n1:23+n1)=b11 !11 sync bits
|
||||
i4tone(23+n1+1:23+n1+n2)=i1EncodedBits(n1+1:n1+n2) !n2 data bits
|
||||
nn2=count(i4tone(23+n1+1:23+n1+n2).eq.0) !Count the 0's
|
||||
if(mod(nn2,2).eq.0) i4tone(24+n1+n2)=1 !1 parity bit
|
||||
|
||||
i4tone(25+n1+n2:35+n1+n2)=b11 !11 sync bits
|
||||
i4tone(35+n1+n2+1:35+n1+n2+n3)=i1EncodedBits(n1+n2+1:n1+n2+n3)!n3 data bits
|
||||
nn3=count(i4tone(35+n1+n2+1:35+n1+n2+n3).eq.0) !Count the 0's
|
||||
if(mod(nn3,2).eq.0) i4tone(36+n1+n2+n3)=1 !1 parity bit
|
||||
endif
|
||||
|
||||
n=count(i4tone.eq.0)
|
||||
if(mod(n,2).ne.0) stop 'Parity error in genmsk.'
|
||||
|
||||
999 return
|
||||
end subroutine genmsk
|
15
lib/hash.f90
15
lib/hash.f90
|
@ -1,15 +1,10 @@
|
|||
subroutine hash(string,len,ihash)
|
||||
|
||||
use iso_c_binding, only: c_loc,c_size_t
|
||||
use hashing
|
||||
parameter (MASK15=32767)
|
||||
character*(*) string
|
||||
integer*1 ic(12)
|
||||
|
||||
do i=1,len
|
||||
ic(i)=ichar(string(i:i))
|
||||
enddo
|
||||
i=nhash(ic,len,146)
|
||||
! character*(*), target :: string
|
||||
character*1, target :: string
|
||||
i=nhash(c_loc(string),int(len,c_size_t),146)
|
||||
ihash=iand(i,MASK15)
|
||||
|
||||
! print*,'C',ihash,len,string
|
||||
return
|
||||
end subroutine hash
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
module hashing
|
||||
interface
|
||||
integer(c_int32_t) function nhash (key, length, initval) bind(C, name="nhash")
|
||||
use iso_c_binding, only: c_ptr, c_size_t, c_int32_t
|
||||
type(c_ptr), intent(in), value :: key
|
||||
integer(c_size_t), intent(in), value :: length
|
||||
integer(c_int32_t), intent(in), value :: initval
|
||||
end function nhash
|
||||
end interface
|
||||
end module hashing
|
|
@ -0,0 +1,59 @@
|
|||
subroutine hspec(id2,k,ingain,green,s,jh)
|
||||
|
||||
! Input:
|
||||
! k pointer to the most recent new data
|
||||
|
||||
! Output:
|
||||
! green() power
|
||||
! s() spectrum for horizontal spectrogram
|
||||
! jh index of most recent data in green(), s()
|
||||
|
||||
parameter (JZ=703)
|
||||
integer*2 id2(0:120*12000-1)
|
||||
real green(0:JZ-1)
|
||||
real s(0:63,0:JZ-1)
|
||||
real x(512)
|
||||
complex cx(0:256)
|
||||
data rms/999.0/,k0/99999999/
|
||||
equivalence (x,cx)
|
||||
save ja,rms0
|
||||
|
||||
gain=10.0**(0.1*ingain)
|
||||
nfft=512
|
||||
if(k.gt.30*12000) go to 900
|
||||
if(k.lt.nfft) then
|
||||
jh=0
|
||||
go to 900 !Wait for enough samples to start
|
||||
endif
|
||||
|
||||
if(k.lt.k0) then !Start a new data block
|
||||
ja=0
|
||||
jh=-1
|
||||
rms0=0.0
|
||||
endif
|
||||
|
||||
do iblk=1,7
|
||||
if(jh.lt.JZ-1) jh=jh+1
|
||||
jb=ja+nfft-1
|
||||
x=id2(ja:jb)
|
||||
sq=dot_product(x,x)
|
||||
rms=sqrt(gain*sq/nfft)
|
||||
green(jh)=0.
|
||||
if(rms.gt.0.0) green(jh)=20.0*log10(0.5*(rms0+rms))
|
||||
rms0=rms
|
||||
call four2a(x,nfft,1,-1,0) !Real-to-complex FFT
|
||||
df=12000.0/nfft
|
||||
fac=(1.0/nfft)**2
|
||||
do i=1,64
|
||||
j=2*i
|
||||
sx=real(cx(j))**2 + aimag(cx(j))**2 + real(cx(j-1))**2 + &
|
||||
aimag(cx(j-1))**2
|
||||
s(i-1,jh)=fac*gain*sx
|
||||
enddo
|
||||
if(ja+2*nfft.gt.k) exit
|
||||
ja=ja+nfft
|
||||
enddo
|
||||
k0=k
|
||||
|
||||
900 return
|
||||
end subroutine hspec
|
|
@ -2,7 +2,7 @@ subroutine indexx(arr,n,indx)
|
|||
|
||||
parameter (M=7,NSTACK=50)
|
||||
integer n,indx(n)
|
||||
integer arr(n)
|
||||
real arr(n)
|
||||
integer i,indxt,ir,itemp,j,jstack,k,l,istack(NSTACK)
|
||||
real a
|
||||
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
subroutine iscat(cdat0,npts0,nh,npct,t2,pick,cfile6,minsync,ntol, &
|
||||
NFreeze,MouseDF,mousebutton,mode4,nafc,nmore,psavg,maxlines,nlines,line)
|
||||
|
||||
! Decode an ISCAT signal
|
||||
|
||||
parameter (NMAX=30*3101)
|
||||
parameter (NSZ=4*1400)
|
||||
character cfile6*6 !File time
|
||||
character c42*42
|
||||
character msg*29,msg1*29,msgbig*29
|
||||
character*80 line(100)
|
||||
character csync*1
|
||||
complex cdat0(NMAX)
|
||||
complex cdat(NMAX)
|
||||
real s0(288,NSZ)
|
||||
real fs1(0:41,30)
|
||||
real psavg(72) !Average spectrum of whole file
|
||||
integer nsum(30)
|
||||
integer ntol
|
||||
integer icos(4)
|
||||
logical pick,last
|
||||
data icos/0,1,3,2/
|
||||
data nsync/4/,nlen/2/,ndat/18/
|
||||
data c42/'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /.?@-'/
|
||||
|
||||
nlines = 0
|
||||
fsample=3100.78125 !Sample rate after 9/32 downsampling
|
||||
nsps=144/mode4
|
||||
|
||||
bigworst=-1.e30 !Silence compiler warnings ...
|
||||
bigxsync=0.
|
||||
bigsig=-1.e30
|
||||
msglenbig=0
|
||||
ndf0big=0
|
||||
nfdotbig=0
|
||||
bigt2=0.
|
||||
bigavg=0.
|
||||
bigtana=0.
|
||||
if(nmore.eq.-999) bigsig=-1 !... to here
|
||||
|
||||
last=.false.
|
||||
do inf=1,6 !Loop over data-segment sizes
|
||||
nframes=2**inf
|
||||
if(nframes*24*nsps.gt.npts0) then
|
||||
nframes=npts0/(24*nsps)
|
||||
last=.true.
|
||||
endif
|
||||
npts=nframes*24*nsps
|
||||
|
||||
do ia=1,npts0-npts,nsps*24 !Loop over start times stepped by 1 frame
|
||||
ib=ia+npts-1
|
||||
cdat(1:npts)=cdat0(ia:ib)
|
||||
t3=(ia + 0.5*npts)/fsample + 0.9
|
||||
if(pick) t3=t2+t3
|
||||
|
||||
! Compute symbol spectra and establish sync:
|
||||
call synciscat(cdat,npts,nh,npct,s0,jsym,df,ntol,NFreeze, &
|
||||
MouseDF,mousebutton,mode4,nafc,psavg,xsync,sig,ndf0,msglen, &
|
||||
ipk,jpk,idf,df1)
|
||||
nfdot=nint(idf*df1)
|
||||
|
||||
isync=xsync
|
||||
if(msglen.eq.0 .or. isync.lt.max(minsync,0)) then
|
||||
msglen=0
|
||||
worst=1.
|
||||
avg=1.
|
||||
ndf0=0
|
||||
cycle
|
||||
endif
|
||||
|
||||
ipk3=0 !Silence compiler warning
|
||||
nblk=nsync+nlen+ndat
|
||||
fs1=0.
|
||||
nsum=0
|
||||
nfold=jsym/96
|
||||
jb=96*nfold
|
||||
k=0
|
||||
n=0
|
||||
do j=jpk,jsym,4 !Fold information symbols into fs1
|
||||
k=k+1
|
||||
km=mod(k-1,nblk)+1
|
||||
if(km.gt.6) then
|
||||
n=n+1
|
||||
m=mod(n-1,msglen)+1
|
||||
ii=nint(idf*float(j-jb/2)/float(jb))
|
||||
do i=0,41
|
||||
iii=ii+ipk+2*i
|
||||
if(iii.ge.1 .and. iii.le.288) fs1(i,m)=fs1(i,m) + s0(iii,j)
|
||||
enddo
|
||||
nsum(m)=nsum(m)+1
|
||||
endif
|
||||
enddo
|
||||
|
||||
do m=1,msglen
|
||||
fs1(0:41,m)=fs1(0:41,m)/nsum(m)
|
||||
enddo
|
||||
|
||||
! Read out the message contents:
|
||||
msg= ' '
|
||||
msg1=' '
|
||||
mpk=0
|
||||
worst=9999.
|
||||
sum=0.
|
||||
do m=1,msglen
|
||||
smax=0.
|
||||
smax2=0.
|
||||
do i=0,41
|
||||
if(fs1(i,m).gt.smax) then
|
||||
smax=fs1(i,m)
|
||||
ipk3=i
|
||||
endif
|
||||
enddo
|
||||
do i=0,41
|
||||
if(fs1(i,m).gt.smax2 .and. i.ne.ipk3) smax2=fs1(i,m)
|
||||
enddo
|
||||
rr=0.
|
||||
if(smax2.gt.0.0) rr=smax/smax2
|
||||
sum=sum + rr
|
||||
if(rr.lt.worst) worst=rr
|
||||
if(ipk3.eq.40) mpk=m
|
||||
msg1(m:m)=c42(ipk3+1:ipk3+1)
|
||||
enddo
|
||||
|
||||
avg=sum/msglen
|
||||
if(mpk.eq.1) then
|
||||
msg=msg1(2:)
|
||||
else if(mpk.lt.msglen) then
|
||||
msg=msg1(mpk+1:msglen)//msg1(1:mpk-1)
|
||||
else
|
||||
msg=msg1(1:msglen-1)
|
||||
endif
|
||||
|
||||
ttot=npts/3100.78125
|
||||
|
||||
if(worst.gt.bigworst) then
|
||||
bigworst=worst
|
||||
bigavg=avg
|
||||
bigxsync=xsync
|
||||
bigsig=sig
|
||||
ndf0big=ndf0
|
||||
nfdotbig=nfdot
|
||||
msgbig=msg
|
||||
msglenbig=msglen
|
||||
bigt2=t3
|
||||
bigtana=nframes*24*nsps/fsample
|
||||
endif
|
||||
|
||||
isync = xsync
|
||||
if(navg.gt.0 .and. isync.ge.max(minsync,0) .and. maxlines.ge.2) then
|
||||
nsig=nint(sig)
|
||||
nworst=10.0*(worst-1.0)
|
||||
navg=10.0*(avg-1.0)
|
||||
if(nworst.gt.10) nworst=10
|
||||
if(navg.gt.10) navg=10
|
||||
tana=nframes*24*nsps/fsample
|
||||
csync=' '
|
||||
if(isync.ge.1) csync='*'
|
||||
if(nlines.le.maxlines-1) nlines = nlines + 1
|
||||
write(line(nlines),1020) cfile6,isync,nsig,t2,ndf0,nfdot,csync, &
|
||||
msg(1:28),msglen,nworst,navg,tana,char(0)
|
||||
endif
|
||||
enddo
|
||||
if(last) exit
|
||||
enddo
|
||||
|
||||
worst=bigworst
|
||||
avg=bigavg
|
||||
xsync=bigxsync
|
||||
sig=bigsig
|
||||
ndf0=ndf0big
|
||||
nfdot=nfdotbig
|
||||
msg=msgbig
|
||||
msglen=msglenbig
|
||||
t2=bigt2
|
||||
tana=bigtana
|
||||
|
||||
isync=xsync
|
||||
nworst=10.0*(worst-1.0)
|
||||
navg=10.0*(avg-1.0)
|
||||
if(nworst.gt.10) nworst=10
|
||||
if(navg.gt.10) navg=10
|
||||
|
||||
if(navg.le.0 .or. isync.lt.max(minsync,0)) then
|
||||
msg=' '
|
||||
nworst=0
|
||||
navg=0
|
||||
ndf0=0
|
||||
nfdot=0
|
||||
sig=-20
|
||||
msglen=0
|
||||
tana=0.
|
||||
t2=0.
|
||||
endif
|
||||
csync=' '
|
||||
if(isync.ge.1) csync='*'
|
||||
nsig=nint(sig)
|
||||
|
||||
if(nlines.le.maxlines-1) nlines = nlines + 1
|
||||
write(line(nlines),1020) cfile6,isync,nsig,t2,ndf0,nfdot,csync,msg(1:28), &
|
||||
msglen,nworst,navg,tana,char(0)
|
||||
1020 format(a6,2i4,f5.1,i5,i4,1x,a1,2x,a28,i4,2i3,f5.1,a1)
|
||||
|
||||
return
|
||||
end subroutine iscat
|
|
@ -52,6 +52,7 @@ C IF 'INQUIRE' DOES NOT WORK, USUALLY IRECSZ WILL BE LEFT AT 0
|
|||
. ' INQUIRE STATEMENT PROBABLY DID NOT WORK'
|
||||
|
||||
KSIZE=IRECSZ/NRECL
|
||||
if(nrfile.eq.-99) stop !silence compiler warning
|
||||
|
||||
RETURN
|
||||
|
||||
|
@ -290,7 +291,7 @@ C (SEE THE DISCUSSION IN THE SUBROUTINE STATE)
|
|||
11 IF(FIRST) CALL STATE(ZIPS,LIST,PVST,PNUT)
|
||||
FIRST=.FALSE.
|
||||
|
||||
96 IF(NTARG .EQ. NCENT) RETURN
|
||||
IF(NTARG .EQ. NCENT) RETURN
|
||||
|
||||
DO I=1,12
|
||||
LIST(I)=0
|
||||
|
|
|
@ -42,6 +42,8 @@ program jt4sim
|
|||
npts=60*12000
|
||||
sps=12000.d0/4.375d0 !2742.857...
|
||||
f0=1000.d0 !Frequency of lowest tone (Hz)
|
||||
freq=f0 !Silence compiler warning
|
||||
dphi=0.0 !Silence compiler warning
|
||||
|
||||
h=default_header(12000,npts)
|
||||
|
||||
|
|
88
lib/jt65.f90
88
lib/jt65.f90
|
@ -2,67 +2,95 @@ program jt65
|
|||
|
||||
! Test the JT65 decoder for WSJT-X
|
||||
|
||||
use options
|
||||
character c
|
||||
logical :: display_help=.false.,err
|
||||
parameter (NZMAX=60*12000)
|
||||
integer*4 ihdr(11)
|
||||
integer*2 id2(NZMAX)
|
||||
real*4 dd(NZMAX)
|
||||
character*80 infile
|
||||
integer*2 nfmt2,nchan2,nbitsam2,nbytesam2
|
||||
character*4 ariff,awave,afmt,adata
|
||||
common/hdr/ariff,lenfile,awave,afmt,lenfmt,nfmt2,nchan2, &
|
||||
nsamrate,nbytesec,nbytesam2,nbitsam2,adata,ndata
|
||||
character(len=500) optarg
|
||||
common/tracer/limtrace,lu
|
||||
equivalence (lenfile,ihdr(2))
|
||||
type (option) :: long_options(3) = [ &
|
||||
option ('help',.false.,'h','Display this help message',''), &
|
||||
option ('ntrials',.true.,'n','default=1000',''), &
|
||||
option ('single-signal mode',.false.,'s','default=1000','') ]
|
||||
|
||||
limtrace=0
|
||||
lu=12
|
||||
ntol=50
|
||||
nfqso=1270
|
||||
nagain=0
|
||||
nsubmode=0
|
||||
ntrials=10000
|
||||
nlow=200
|
||||
nhigh=4000
|
||||
n2pass=2
|
||||
|
||||
do
|
||||
call getopt('hn:s',long_options,c,optarg,narglen,nstat,noffset,nremain,err)
|
||||
if( nstat .ne. 0 ) then
|
||||
exit
|
||||
end if
|
||||
select case (c)
|
||||
case ('h')
|
||||
display_help = .true.
|
||||
case ('n')
|
||||
read (optarg(:narglen), *) ntrials
|
||||
case ('s')
|
||||
nlow=1250
|
||||
nhigh=1290
|
||||
n2pass=1
|
||||
end select
|
||||
end do
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.lt.1) then
|
||||
print*,'Usage: jt65 file1 [file2 ...]'
|
||||
if(display_help .or. (nargs.lt.1)) then
|
||||
print*,'Usage: jt65 [-n ntrials] [-s] file1 [file2 ...]'
|
||||
print*,' -s single-signal mode'
|
||||
go to 999
|
||||
endif
|
||||
limtrace=0
|
||||
lu=12
|
||||
|
||||
newdat=1
|
||||
ntol=50
|
||||
nfa=2700
|
||||
! nfb=4000
|
||||
nfqso=933
|
||||
nagain=0
|
||||
|
||||
open(12,file='timer.out',status='unknown')
|
||||
open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown')
|
||||
|
||||
call timer('jt65 ',0)
|
||||
|
||||
ndecoded=0
|
||||
do ifile=1,nargs
|
||||
call getarg(ifile,infile)
|
||||
newdat=1
|
||||
nfa=nlow
|
||||
nfb=nhigh
|
||||
call getarg(ifile+noffset,infile)
|
||||
if( infile.eq.'' ) goto 900
|
||||
open(10,file=infile,access='stream',status='old',err=998)
|
||||
|
||||
call timer('read ',0)
|
||||
read(10) ihdr
|
||||
nutc=ihdr(1) !Silence compiler warning
|
||||
i1=index(infile,'.wav')
|
||||
read(infile(i1-4:i1-1),*,err=10) nutc
|
||||
go to 20
|
||||
10 nutc=0
|
||||
20 npts=52*12000
|
||||
if( i1 .eq. 0 ) i1=index(infile,'.WAV')
|
||||
read(infile(i1-4:i1-1),*,err=998) nutc
|
||||
npts=52*12000
|
||||
read(10) id2(1:npts)
|
||||
call timer('read ',1)
|
||||
dd(1:npts)=id2(1:npts)
|
||||
dd(npts+1:)=0.
|
||||
|
||||
call timer('jt65a ',0)
|
||||
call jt65a(dd,npts,newdat,nutc,ntol,nfa,nfqso,nagain,ndecoded)
|
||||
|
||||
! open(56,file='subtracted.wav',access='stream',status='unknown')
|
||||
! write(56) ihdr(1:11)
|
||||
|
||||
call jt65a(dd,npts,newdat,nutc,nfa,nfb,nfqso,ntol,nsubmode, &
|
||||
minsync,nagain,n2pass,ntrials, naggressive,ndepth,ndecoded)
|
||||
call timer('jt65a ',1)
|
||||
enddo
|
||||
|
||||
call timer('jt65 ',1)
|
||||
900 call timer('jt65 ',1)
|
||||
call timer('jt65 ',101)
|
||||
call four2a(a,-1,1,1,1) !Free the memory used for plans
|
||||
call filbig(a,-1,1,0.0,0,0,0,0,0) ! (ditto)
|
||||
! call four2a(a,-1,1,1,1) !Free the memory used for plans
|
||||
! call filbig(a,-1,1,0.0,0,0,0,0,0) ! (ditto)
|
||||
go to 999
|
||||
|
||||
998 print*,'Cannot open file:'
|
||||
998 print*,'Cannot read from file:'
|
||||
print*,infile
|
||||
|
||||
999 end program jt65
|
||||
|
|
179
lib/jt65a.f90
179
lib/jt65a.f90
|
@ -1,106 +1,143 @@
|
|||
subroutine jt65a(dd0,npts,newdat,nutc,nf1,nf2,nfqso,ntol,nsubmode, &
|
||||
nagain,ndecoded)
|
||||
minsync,nagain,n2pass,ntrials,naggressive,ndepth,ndecoded)
|
||||
|
||||
! Process dd() data to find and decode JT65 signals.
|
||||
! Process dd0() data to find and decode JT65 signals.
|
||||
|
||||
parameter (NSZ=3413)
|
||||
parameter (NZMAX=60*12000)
|
||||
parameter (NFFT=8192)
|
||||
parameter (NSZ=3413,NZMAX=60*12000)
|
||||
parameter (NFFT=1000)
|
||||
real dd0(NZMAX)
|
||||
real dd(NZMAX)
|
||||
real*4 ss(322,NSZ)
|
||||
real*4 savg(NSZ)
|
||||
logical done(NSZ)
|
||||
! integer*2 id2(NZMAX)
|
||||
real ss(322,NSZ)
|
||||
real savg(NSZ)
|
||||
real a(5)
|
||||
character decoded*22
|
||||
common/decstats/num65,numbm,numkv,num9,numfano
|
||||
character*22 decoded,decoded0
|
||||
type candidate
|
||||
real freq
|
||||
real dt
|
||||
real sync
|
||||
end type candidate
|
||||
type(candidate) ca(300)
|
||||
type decode
|
||||
real freq
|
||||
real dt
|
||||
real sync
|
||||
character*22 decoded
|
||||
end type decode
|
||||
type(decode) dec(30)
|
||||
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
||||
common/steve/thresh0
|
||||
save
|
||||
|
||||
dd=0.
|
||||
tskip=2.0
|
||||
nskip=12000*tskip
|
||||
dd(1+nskip:npts+nskip)=dd0(1:npts)
|
||||
npts=npts+nskip
|
||||
dd=dd0
|
||||
ndecoded=0
|
||||
|
||||
if(newdat.ne.0) then
|
||||
do ipass=1,n2pass ! 2-pass decoding loop
|
||||
newdat=1
|
||||
if(ipass.eq.1) then !first-pass parameters
|
||||
thresh0=2.5 ! use thresh0=2.0 for -24dB files when using 1-bit sync ccf
|
||||
nsubtract=1
|
||||
elseif( ipass.eq.2 ) then !second-pass parameters
|
||||
thresh0=2.5
|
||||
nsubtract=0
|
||||
endif
|
||||
if(n2pass.lt.2) nsubtract=0
|
||||
|
||||
! if(newdat.ne.0) then
|
||||
call timer('symsp65 ',0)
|
||||
ss=0.
|
||||
call symspec65(dd,npts,ss,nhsym,savg) !Get normalized symbol spectra
|
||||
call timer('symsp65 ',1)
|
||||
! endif
|
||||
nfa=nf1
|
||||
nfb=nf2
|
||||
! nfa=max(200,nfqso-ntol)
|
||||
! nfb=min(4000,nfqso+ntol)
|
||||
|
||||
ncand=0
|
||||
nrobust=0 ! controls use of robust correlation estimator in sync65
|
||||
call timer('sync65 ',0)
|
||||
call sync65(ss,nfa,nfb,nhsym,ca,ncand,nrobust) !Get a list of JT65 candidates
|
||||
call timer('sync65 ',1)
|
||||
|
||||
! When AGC threshold is set too low, noise will suddenly quiet when a strong
|
||||
! signal starts up. This causes a lot of false syncs, and bogs down the decoder.
|
||||
! If 1-bit correlation doesn't tame the resulting false syncs then, as a last
|
||||
! resort, drop down to nrials=100.
|
||||
if(ncand.ge.50) then
|
||||
ncand=0
|
||||
nrobust=1
|
||||
call timer('sync65 ',0)
|
||||
call sync65(ss,nfa,nfb,nhsym,ca,ncand,nrobust) !Get a list of JT65 candidates
|
||||
call timer('sync65 ',1)
|
||||
endif
|
||||
!write(*,*) 'ncand',ncand
|
||||
nvec=ntrials
|
||||
if(ncand.gt.75) then
|
||||
! write(*,*) 'Pass ',ipass,' ncandidates too large ',ncand
|
||||
nvec=100
|
||||
endif
|
||||
|
||||
df=12000.0/NFFT !df = 12000.0/16384 = 0.732 Hz
|
||||
ftol=16.0 !Frequency tolerance (Hz)
|
||||
df=12000.0/NFFT !df = 12000.0/8192 = 1.465 Hz
|
||||
mode65=2**nsubmode
|
||||
done=.false.
|
||||
freq0=-999.
|
||||
nflip=1 !### temporary ###
|
||||
nqd=0
|
||||
decoded0=""
|
||||
|
||||
do nqd=1,0,-1
|
||||
if(nqd.eq.1) then !Quick decode, at fQSO
|
||||
fa=nfqso - ntol
|
||||
fb=nfqso + ntol
|
||||
else !Wideband decode at all freqs
|
||||
fa=nf1
|
||||
fb=nf2
|
||||
endif
|
||||
ia=max(51,nint(fa/df))
|
||||
ib=min(NSZ-51,nint(fb/df))
|
||||
do icand=1,ncand
|
||||
freq=ca(icand)%freq
|
||||
dtx=ca(icand)%dt
|
||||
sync1=ca(icand)%sync
|
||||
|
||||
thresh0=1.5
|
||||
|
||||
do i=ia,ib !Search over freq range
|
||||
freq=i*df
|
||||
if(savg(i).lt.thresh0 .or. done(i)) cycle
|
||||
|
||||
call timer('ccf65 ',0)
|
||||
call ccf65(ss(1,i),nhsym,savg(i),sync1,dt,flipk,syncshort,snr2,dt2)
|
||||
call timer('ccf65 ',1)
|
||||
|
||||
ftest=abs(freq-freq0)
|
||||
thresh1=1.0
|
||||
if(nqd.eq.1 .and. ntol.le.100) thresh1=0.
|
||||
if(sync1.lt.thresh1 .or. ftest.lt.ftol) cycle
|
||||
|
||||
nflip=nint(flipk)
|
||||
if(ipass.eq.1) ntry65a=ntry65a + 1
|
||||
if(ipass.eq.2) ntry65b=ntry65b + 1
|
||||
call timer('decod65a',0)
|
||||
call decode65a(dd,npts,newdat,nqd,freq,nflip,mode65,sync2,a,dt, &
|
||||
nbmkv,nhist,decoded)
|
||||
call decode65a(dd,npts,newdat,nqd,freq,nflip,mode65,nvec, &
|
||||
naggressive,ndepth,sync2,a,dtx,nsf,nhist,decoded)
|
||||
call timer('decod65a',1)
|
||||
!write(*,*) icand,freq+a(1),dtx,sync1,sync2
|
||||
if(decoded.eq.decoded0) cycle !Don't display dupes
|
||||
|
||||
ftest=abs(freq+a(1)-freq0)
|
||||
if(ftest.lt.ftol) cycle
|
||||
|
||||
if(decoded.ne.' ') then
|
||||
ndecoded=1
|
||||
if(decoded.ne.' ' .or. minsync.lt.0) then
|
||||
if( nsubtract .eq. 1 ) then
|
||||
call timer('subtr65 ',0)
|
||||
call subtract65(dd,npts,freq,dtx)
|
||||
call timer('subtr65 ',1)
|
||||
endif
|
||||
nfreq=nint(freq+a(1))
|
||||
ndrift=nint(2.0*a(2))
|
||||
s2db=10.0*log10(sync2) - 32 !### empirical (was 40) ###
|
||||
s2db=10.0*log10(sync2) - 35 !### empirical ###
|
||||
nsnr=nint(s2db)
|
||||
if(nsnr.lt.-30) nsnr=-30
|
||||
if(nsnr.gt.-1) nsnr=-1
|
||||
dt=dt-tskip
|
||||
if(nbmkv.eq.1) numbm=numbm+1
|
||||
if(nbmkv.eq.2) numkv=numkv+1
|
||||
|
||||
! Serialize writes - see also decjt9.f90
|
||||
|
||||
!$omp critical(decode_results)
|
||||
|
||||
write(*,1010) nutc,nsnr,dt,nfreq,decoded
|
||||
!$omp critical(decode_results)
|
||||
ndupe=0 ! de-dedupe
|
||||
do i=1, ndecoded
|
||||
if( decoded==dec(i)%decoded ) ndupe=1
|
||||
enddo
|
||||
if(ndupe.ne.1) then
|
||||
if(ipass.eq.1) n65a=n65a + 1
|
||||
if(ipass.eq.2) n65b=n65b + 1
|
||||
ndecoded=ndecoded+1
|
||||
dec(ndecoded)%freq=freq+a(1)
|
||||
dec(ndecoded)%dt=dtx
|
||||
dec(ndecoded)%sync=sync2
|
||||
dec(ndecoded)%decoded=decoded
|
||||
write(*,1010) nutc,nsnr,dtx-1.0,nfreq,decoded
|
||||
1010 format(i4.4,i4,f5.1,i5,1x,'#',1x,a22)
|
||||
write(13,1012) nutc,nint(sync1),nsnr,dt,float(nfreq),ndrift, &
|
||||
decoded,nbmkv
|
||||
write(13,1012) nutc,nint(sync1),nsnr,dtx-1.0,float(nfreq),ndrift, &
|
||||
decoded,nsf
|
||||
1012 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT65',i4)
|
||||
call flush(6)
|
||||
call flush(13)
|
||||
!$omp end critical(decode_results)
|
||||
|
||||
freq0=freq+a(1)
|
||||
i2=min(NSZ,i+15) !### ??? ###
|
||||
done(i:i2)=.true.
|
||||
endif
|
||||
enddo
|
||||
if(nagain.eq.1) exit
|
||||
enddo
|
||||
!$omp end critical(decode_results)
|
||||
endif
|
||||
enddo !candidate loop
|
||||
if(ndecoded.lt.1) exit
|
||||
enddo !two-pass loop
|
||||
|
||||
return
|
||||
end subroutine jt65a
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
program jt65sim
|
||||
|
||||
! Generate simulated data for testing of WSJT-X
|
||||
|
||||
use wavhdr
|
||||
use packjt
|
||||
parameter (NTMAX=54)
|
||||
parameter (NMAX=NTMAX*12000)
|
||||
type(hdr) h
|
||||
integer*2 iwave(NMAX) !Generated waveform (no noise)
|
||||
integer*4 itone(126) !Channel symbols (values 0-65)
|
||||
integer dgen(12),sent(63)
|
||||
real*4 dat(NMAX)
|
||||
real*8 f0,dt,twopi,phi,dphi,baud,fsample,freq,sps
|
||||
character msg*22,arg*8,fname*11,csubmode*1
|
||||
integer nprc(126)
|
||||
data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, &
|
||||
0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, &
|
||||
0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, &
|
||||
0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, &
|
||||
1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, &
|
||||
0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, &
|
||||
1,1,1,1,1,1/
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.5) then
|
||||
print*,'Usage: jt65sim mode nRay nsigs SNR nfiles'
|
||||
print*,'Example: jt65sim B 0 10 -24 1'
|
||||
print*,'Enter SNR = 0 to generate a range of SNRs.'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
csubmode='A'
|
||||
call getarg(1,csubmode)
|
||||
mode65=1
|
||||
if(csubmode.eq.'B') mode65=2
|
||||
if(csubmode.eq.'C') mode65=4
|
||||
call getarg(2,arg)
|
||||
read(arg,*) nRay !1 ==> Rayleigh fading
|
||||
call getarg(3,arg)
|
||||
read(arg,*) nsigs !Number of signals in each file
|
||||
call getarg(4,arg)
|
||||
read(arg,*) snrdb !S/N in dB (2500 hz reference BW)
|
||||
call getarg(5,arg)
|
||||
read(arg,*) nfiles !Number of files
|
||||
|
||||
rmsdb=25.
|
||||
rms=10.0**(0.05*rmsdb)
|
||||
fsample=12000.d0 !Sample rate (Hz)
|
||||
dt=1.d0/fsample !Sample interval (s)
|
||||
twopi=8.d0*atan(1.d0)
|
||||
npts=54*12000
|
||||
baud=11025.d0/4096.d0
|
||||
sps=12000.d0/baud !Samples per symbol, at fsample=12000 Hz
|
||||
nsym=126
|
||||
h=default_header(12000,npts)
|
||||
|
||||
do ifile=1,nfiles !Loop over all files
|
||||
nmin=ifile
|
||||
ihr=nmin/60
|
||||
imin=mod(nmin,60)
|
||||
write(fname,1002) ihr,imin !Output filename
|
||||
1002 format('000000_',2i2.2)
|
||||
open(10,file=fname//'.wav',access='stream',status='unknown')
|
||||
|
||||
if(snrdb.lt.90) then
|
||||
do i=1,npts
|
||||
dat(i)=gran() !Generate AWGN
|
||||
enddo
|
||||
else
|
||||
dat(1:npts)=0.
|
||||
endif
|
||||
|
||||
dfsig=2000.0/nsigs
|
||||
do isig=1,nsigs
|
||||
if(mod(nsigs,2).eq.0) f0=1500.0 + dfsig*(isig-0.5-nsigs/2)
|
||||
if(mod(nsigs,2).eq.1) f0=1500.0 + dfsig*(isig-(nsigs+1)/2)
|
||||
nsnr=nint(snrdb)
|
||||
if(snrdb.eq.0.0) nsnr=-19 - isig
|
||||
write(msg,1010) nsnr
|
||||
1010 format('K1ABC W9XYZ ',i3.2)
|
||||
|
||||
call packmsg(msg,dgen,itype) !Pack message into 12 six-bit bytes
|
||||
call rs_encode(dgen,sent) !RS encode
|
||||
call interleave63(sent,1) !Interleave channel symbols
|
||||
call graycode65(sent,63,1) !Apply Gray code
|
||||
|
||||
k=0
|
||||
do j=1,nsym
|
||||
if(nprc(j).eq.0) then
|
||||
k=k+1
|
||||
itone(j)=sent(k)+2
|
||||
else
|
||||
itone(j)=0
|
||||
endif
|
||||
enddo
|
||||
|
||||
sig=10.0**(0.05*nsnr)
|
||||
if(nsnr.gt.90.0) sig=1.0
|
||||
write(*,1020) ifile,isig,f0,csubmode,nsnr,sig,msg
|
||||
1020 format(i3,i4,f10.3,1x,a1,i5,f8.4,2x,a22)
|
||||
|
||||
phi=0.d0
|
||||
dphi=0.d0
|
||||
k=12000 !Start audio at t = 1.0 s
|
||||
isym0=-99
|
||||
do i=1,npts
|
||||
isym=nint(i/sps)+1
|
||||
if(isym.gt.nsym) exit
|
||||
if(isym.ne.isym0) then
|
||||
freq=f0 + itone(isym)*baud*mode65
|
||||
dphi=twopi*freq*dt
|
||||
isym0=isym
|
||||
endif
|
||||
phi=phi + dphi
|
||||
if(phi.gt.twopi) phi=phi-twopi
|
||||
xphi=phi
|
||||
k=k+1
|
||||
dat(k)=dat(k) + sig*sin(xphi)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
fac=32767.0/nsigs !### ??? ###
|
||||
if(snrdb.ge.90.0) iwave(1:npts)=nint(fac*dat(1:npts))
|
||||
if(snrdb.lt.90.0) iwave(1:npts)=nint(rms*dat(1:npts))
|
||||
write(10) h,iwave(1:npts)
|
||||
close(10)
|
||||
|
||||
enddo
|
||||
|
||||
999 end program jt65sim
|
15
lib/jt9.f90
15
lib/jt9.f90
|
@ -17,7 +17,7 @@ program jt9
|
|||
character(len=500) optarg, infile
|
||||
character wisfile*80
|
||||
integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700, &
|
||||
fhigh=4000,nrxfreq=1500,ntrperiod=1,ndepth=1
|
||||
fhigh=4000,nrxfreq=1500,ntrperiod=1,ndepth=60001
|
||||
logical :: shmem = .false., read_files = .false., have_args = .false., &
|
||||
tx9 = .false., display_help = .false.
|
||||
type (option) :: long_options(17) = [ &
|
||||
|
@ -58,7 +58,7 @@ program jt9
|
|||
|
||||
common/tracer/limtrace,lu
|
||||
common/patience/npatience,nthreads
|
||||
common/decstats/num65,numbm,numkv,num9,numfano,infile
|
||||
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
||||
data npatience/1/,nthreads/1/
|
||||
|
||||
do
|
||||
|
@ -144,9 +144,10 @@ program jt9
|
|||
wisfile=trim(data_dir)//'/jt9_wisdom.dat'// C_NULL_CHAR
|
||||
iret=fftwf_import_wisdom_from_filename(wisfile)
|
||||
|
||||
num65=0
|
||||
numbm=0
|
||||
numkv=0
|
||||
ntry65a=0
|
||||
ntry65b=0
|
||||
n65a=0
|
||||
n65b=0
|
||||
num9=0
|
||||
numfano=0
|
||||
|
||||
|
@ -243,8 +244,8 @@ program jt9
|
|||
|
||||
999 continue
|
||||
! Output decoder statistics
|
||||
write(12,1100) numbm,numkv,numbm+numkv,num65,numfano,num9
|
||||
1100 format(58('-')/' BM KV JT65 Tries JT9 Tries'/ &
|
||||
write(12,1100) n65a,ntry65a,n65b,ntry65b,numfano,num9
|
||||
1100 format(58('-')/' JT65_1 Tries_1 JT65_2 Tries_2 JT9 Tries'/ &
|
||||
58('-')/6i8)
|
||||
|
||||
! Save wisdom and free memory
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
subroutine jtmsk(id2,narg,line)
|
||||
|
||||
! Decoder for JTMSK
|
||||
|
||||
parameter (NMAX=30*12000)
|
||||
parameter (NFFTMAX=512*1024)
|
||||
parameter (NSPM=1404) !Samples per JTMSK message
|
||||
integer*2 id2(0:NMAX) !Raw i*2 data, up to T/R = 30 s
|
||||
real d(0:NMAX) !Raw r*4 data
|
||||
real ty(703)
|
||||
real yellow(703)
|
||||
! real spk2(20)
|
||||
! real fpk2(20)
|
||||
! integer jpk2(20)
|
||||
complex c(NFFTMAX) !Complex (analytic) data
|
||||
complex cdat(24000) !Short segments, up to 2 s
|
||||
complex cdat2(24000)
|
||||
integer narg(0:11) !Arguments passed from calling pgm
|
||||
character*22 msg,msg0 !Decoded message
|
||||
character*80 line(100) !Decodes passed back to caller
|
||||
common/tracer/ limtrace,lu
|
||||
|
||||
limtrace=-1
|
||||
lu=12
|
||||
! Parameters from GUI are in narg():
|
||||
nutc=narg(0) !UTC
|
||||
npts=min(narg(1),NMAX) !Number of samples in id2 (12000 Hz)
|
||||
newdat=narg(3) !1==> new data, compute symbol spectra
|
||||
minsync=narg(4) !Lower sync limit
|
||||
npick=narg(5)
|
||||
t0=0.001*narg(6)
|
||||
t1=0.001*narg(7)
|
||||
maxlines=narg(8) !Max # of decodes to return to caller
|
||||
nmode=narg(9)
|
||||
nrxfreq=narg(10) !Target Rx audio frequency (Hz)
|
||||
ntol=narg(11) !Search range, +/- ntol (Hz)
|
||||
|
||||
nsnr0=-99
|
||||
nline=0
|
||||
line(1:100)(1:1)=char(0)
|
||||
msg0=' '
|
||||
msg=msg0
|
||||
|
||||
d(0:npts-1)=id2(0:npts-1)
|
||||
rms=sqrt(dot_product(d(0:npts-1),d(0:npts-1))/npts)
|
||||
d(0:npts-1)=d(0:npts-1)/rms
|
||||
call timer('mskdt ',0)
|
||||
call mskdt(d,npts,ty,yellow,nyel)
|
||||
nyel=min(nyel,5)
|
||||
call timer('mskdt ',1)
|
||||
|
||||
n=log(float(npts))/log(2.0) + 1.0
|
||||
nfft=min(2**n,1024*1024)
|
||||
call timer('analytic',0)
|
||||
call analytic(d,npts,nfft,c) !Convert to analytic signal
|
||||
call timer('analytic',1)
|
||||
|
||||
nbefore=NSPM
|
||||
nafter=4*NSPM
|
||||
! Process ping list (sorted by S/N) from top down.
|
||||
do n=1,nyel
|
||||
ia=ty(n)*12000.0 - nbefore
|
||||
if(ia.lt.1) ia=1
|
||||
ib=ia + nafter
|
||||
if(ib.gt.NFFTMAX) ib=NFFTMAX
|
||||
iz=ib-ia+1
|
||||
cdat2(1:iz)=c(ia:ib) !Select nlen complex samples
|
||||
ja=ia/NSPM + 1
|
||||
jb=ib/NSPM
|
||||
t0=ia/12000.0
|
||||
! call msksync(cdat,iz,jpk2,fpk2,spk2)
|
||||
! call softmsk(cdat,iz,jpk2,fpk2,spk2)
|
||||
|
||||
do itry=1,21
|
||||
idf1=(itry/2) * 50
|
||||
if(mod(itry,2).eq.1) idf1=-idf1
|
||||
if(abs(idf1).gt.ntol) exit
|
||||
fpk=idf1 + nrxfreq
|
||||
call timer('tweak1 ',0)
|
||||
call tweak1(cdat2,iz,1500.0-fpk,cdat)
|
||||
call timer('tweak1 ',1)
|
||||
|
||||
call timer('syncmsk ',0)
|
||||
call syncmsk(cdat,iz,jpk,ipk,idf,rmax,snr,metric,msg)
|
||||
call timer('syncmsk ',1)
|
||||
freq=fpk+idf
|
||||
! write(72,4001) jpk,idf,nint(freq),rmax,snr,msg
|
||||
!4001 format(3i6,2f9.2,2x,a22)
|
||||
if(metric.eq.-9999) cycle !No output if no significant sync
|
||||
t0=(ia+jpk)/12000.0
|
||||
nsnr=nint(yellow(n)-2.0)
|
||||
if(msg.ne.' ') then
|
||||
if(msg.ne.msg0) then
|
||||
nline=nline+1
|
||||
nsnr0=-99
|
||||
endif
|
||||
if(nsnr.gt.nsnr0) then
|
||||
call rectify_msk(cdat2(jpk:jpk+NSPM-1),msg,freq2)
|
||||
write(line(nline),1020) nutc,nsnr,t0,nint(freq2),msg
|
||||
1020 format(i6.6,i4,f5.1,i5,' & ',a22)
|
||||
nsnr0=nsnr
|
||||
go to 900
|
||||
endif
|
||||
msg0=msg
|
||||
if(nline.ge.maxlines) go to 900
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
900 if(line(1)(1:6).eq.' ') line(1)(1:1)=char(0)
|
||||
|
||||
return
|
||||
end subroutine jtmsk
|
|
@ -32,8 +32,8 @@ subroutine MoonDopJPL(nyear,month,nday,uth4,lon4,lat4,RAMoon4, &
|
|||
|
||||
RAMoon4=RA
|
||||
DecMoon4=Dec
|
||||
LST4=LST
|
||||
HA4=HA
|
||||
LST4=0. !These two variables not presently used
|
||||
HA4=0.
|
||||
AzMoon4=Az*rad
|
||||
ElMoon4=El*rad
|
||||
vr4=vr
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
subroutine mskdt(d,npts,ty,yellow,nyel)
|
||||
|
||||
parameter (NFFT=1024,NH=NFFT/2)
|
||||
real d(npts)
|
||||
real x(0:NFFT-1)
|
||||
real green(703)
|
||||
real yellow(703) !703 = 30*12000/512
|
||||
real ty(703)
|
||||
real y2(175)
|
||||
real ty2(175)
|
||||
integer indx(703)
|
||||
logical ok
|
||||
complex c(0:NH)
|
||||
equivalence (x,c)
|
||||
|
||||
df=12000.0/NFFT
|
||||
i1=nint(300.0/df)
|
||||
i2=nint(800.0/df)
|
||||
i3=nint(2200.0/df)
|
||||
i4=nint(2700.0/df)
|
||||
nblks=npts/NH - 1
|
||||
|
||||
do j=1,nblks
|
||||
ib=(j+1)*NH
|
||||
ia=ib-NFFT+1
|
||||
x=d(ia:ib)
|
||||
call four2a(x,NFFT,1,-1,0) !r2c FFT
|
||||
sqlow=0.
|
||||
do i=i1,i2
|
||||
sqlow=sqlow + real(c(i))**2 + aimag(c(i))**2
|
||||
enddo
|
||||
sqmid=0.
|
||||
do i=i2,i3
|
||||
sqmid=sqmid + real(c(i))**2 + aimag(c(i))**2
|
||||
enddo
|
||||
sqhigh=0.
|
||||
do i=i3,i4
|
||||
sqhigh=sqhigh + real(c(i))**2 + aimag(c(i))**2
|
||||
enddo
|
||||
green(j)=db(sqlow+sqmid+sqhigh)
|
||||
yellow(j)=db(sqmid/(sqlow+sqhigh))
|
||||
ty(j)=j*512.0/12000.0
|
||||
enddo
|
||||
|
||||
npct=20
|
||||
call pctile(green,nblks,npct,base)
|
||||
green(1:nblks)=green(1:nblks) - base - 0.3
|
||||
call pctile(yellow,nblks,npct,base)
|
||||
yellow(1:nblks)=yellow(1:nblks) - base - 0.6
|
||||
call indexx(yellow,nblks,indx)
|
||||
|
||||
do j=1,nblks/4
|
||||
k=indx(nblks+1-j)
|
||||
ty(j)=ty(k)
|
||||
yellow(j)=yellow(k)
|
||||
if(yellow(j).lt.1.5) exit
|
||||
enddo
|
||||
nyel=j-1
|
||||
k=1
|
||||
y2(1)=yellow(1)
|
||||
ty2(1)=ty(1)
|
||||
do j=2,nyel
|
||||
ok=.true.
|
||||
do i=1,j-1
|
||||
if(abs(ty(i)-ty(j)).lt.0.117) ok=.false.
|
||||
enddo
|
||||
if(ok) then
|
||||
k=k+1
|
||||
y2(k)=yellow(j)
|
||||
ty2(k)=ty(j)
|
||||
endif
|
||||
enddo
|
||||
nyel=k
|
||||
yellow(1:nyel)=y2(1:nyel)
|
||||
ty(1:nyel)=ty2(1:nyel)
|
||||
|
||||
return
|
||||
end subroutine mskdt
|
|
@ -11,7 +11,7 @@ subroutine pctile(x,npts,npct,xpct)
|
|||
if(npts.gt.NMAX) stop
|
||||
|
||||
tmp(1:npts)=x
|
||||
call sort(npts,tmp)
|
||||
call shell(npts,tmp)
|
||||
j=nint(npts*0.01*npct)
|
||||
if(j.lt.1) j=1
|
||||
if(j.gt.npts) j=npts
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
'FOA ','FOC ','FOM ','FP ','FR ','FRG ','FRJ ','FRT ', &
|
||||
'FT5W ','FT5X ','FT5Z ','FW ','FY ','M ','MD ','MI ', &
|
||||
'MJ ','MM ', 'MU ','MW ','H4 ','H40 ','HA ', &
|
||||
'HB ','HB0 ','HC ','HC8 ','HH ','HI ','HK ','HK0A ', &
|
||||
'HB ','HB0 ','HC ','HC8 ','HH ','HI ','HK ','HK0 ', &
|
||||
'HK0M ','HL ','HM ','HP ','HR ','HS ','HV ','HZ ', &
|
||||
'I ','IS ','IS0 ', 'J2 ','J3 ','J5 ','J6 ', &
|
||||
'J7 ','J8 ','JA ','JDM ','JDO ','JT ','JW ', &
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2)
|
|
@ -0,0 +1,75 @@
|
|||
subroutine rectify_msk(c,msg,freq2)
|
||||
|
||||
parameter (NSPM=1404)
|
||||
complex c(0:NSPM-1) !Received data
|
||||
complex cmsg(0:NSPM-1) !Message waveform
|
||||
complex c1(0:NSPM-1) !Rectified signal
|
||||
complex c2(0:NSPM-1) !Integral of rectified signal
|
||||
complex c3(0:2*NSPM-1) !FFT of rectified signal
|
||||
complex cfac,z
|
||||
character*22 msg,msgsent
|
||||
integer i4tone(234)
|
||||
|
||||
ichk=0
|
||||
call genmsk(msg,ichk,msgsent,i4tone,itype) !Get tone sequence for msg
|
||||
|
||||
twopi=8.0*atan(1.0)
|
||||
dt=1.0/12000.0
|
||||
f0=1000.0
|
||||
f1=2000.0
|
||||
phi=0.
|
||||
dphi=0.
|
||||
k=-1
|
||||
c2=0.
|
||||
do j=1,234 !Generate Tx waveform for msg
|
||||
if(i4tone(j).eq.0) dphi=twopi*f0*dt
|
||||
if(i4tone(j).eq.1) dphi=twopi*f1*dt
|
||||
do i=1,6
|
||||
k=k+1
|
||||
phi=phi+dphi
|
||||
cmsg(k)=cmplx(cos(phi),sin(phi))
|
||||
c1(k)=conjg(cmsg(k))*c(k)
|
||||
if(k.ge.1) c2(k)=c2(k-1) + c1(k)
|
||||
enddo
|
||||
enddo
|
||||
c2(0)=c2(1)
|
||||
pha=atan2(aimag(c2(NSPM-1)),real(c2(NSPM-1)))
|
||||
cfac=cmplx(cos(pha),-sin(pha))
|
||||
c1=cfac*c1
|
||||
c2=cfac*c2
|
||||
! sq=0.
|
||||
! do k=0,NSPM-1
|
||||
! pha=atan2(aimag(c2(k)),real(c2(k)))
|
||||
! write(61,3001) k,c1(k),c2(k),pha
|
||||
!3001 format(i6,7f12.3)
|
||||
! sq=sq + aimag(c1(k))**2
|
||||
! enddo
|
||||
|
||||
! z=c2(5)
|
||||
! do j=1,234
|
||||
! k=j*6 - 1
|
||||
! if(j.ge.2) z=c2(k)-c2(k-6)
|
||||
! pha=atan2(aimag(z),real(z))
|
||||
! write(62,3001) j,z,pha
|
||||
! enddo
|
||||
|
||||
nfft=2*NSPM
|
||||
c3(0:NSPM-1)=c2
|
||||
c3(NSPM:nfft-1)=0.
|
||||
df=12000.0/nfft
|
||||
call four2a(c3,nfft,1,-1,1)
|
||||
smax=0.
|
||||
do i=0,nfft-1
|
||||
f=i*df
|
||||
if(i.gt.nfft/2) f=f-12000.0
|
||||
s=1.e-10*(real(c3(i))**2 + aimag(c3(i))**2)
|
||||
if(s.gt.smax) then
|
||||
smax=s
|
||||
freq2=1500.0 + f
|
||||
endif
|
||||
! write(63,3002) f,s,db(s),c3(i)
|
||||
!3002 format(f10.1,f12.3,f10.2,2f12.1)
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine rectify_msk
|
|
@ -0,0 +1,121 @@
|
|||
subroutine sfrsd(mrsym,mrprob,mr2sym,mr2prob,ntrials,correct,indexes, &
|
||||
param,ntry)
|
||||
|
||||
integer mrsym(0:62),mrprob(0:62),mr2sym(0:62),mr2prob(0:62)
|
||||
integer correct(0:62),indexes(0:62),probs(0:62),thresh0(0:62)
|
||||
integer rxdat(0:62),rxdat2(0:62),rxprob(0:62),rxprob2(0:62)
|
||||
integer workdat(0:62),era_pos(0:50)
|
||||
integer perr(0:7,0:7)
|
||||
integer param(0:7)
|
||||
real ratio0(0:62)
|
||||
|
||||
call init_rs_int()
|
||||
do i=0,62
|
||||
rxdat(i)=mrsym(62-i)
|
||||
rxdat2(i)=mr2sym(62-i)
|
||||
rxprob(i)=mrprob(62-i)
|
||||
rxprob2(i)=mr2prob(62-i)
|
||||
enddo
|
||||
|
||||
do i=0,62
|
||||
indexes(i)=i
|
||||
probs(i)=rxprob(i)
|
||||
enddo
|
||||
|
||||
do ip=1,62
|
||||
do k=0,63-ip
|
||||
if(probs(k).lt.probs(k+1)) then
|
||||
ntmp=probs(k)
|
||||
probs(k)=probs(k+1)
|
||||
probs(k+1)=ntmp
|
||||
ntmp=indexes(k)
|
||||
indexes(k)=indexes(k+1)
|
||||
indexes(k+1)=ntmp
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
era_pos=0
|
||||
numera=0
|
||||
workdat=rxdat
|
||||
call decode_rs_int()
|
||||
if(nerr.ge.0) then
|
||||
correct=workdat
|
||||
param=0
|
||||
return
|
||||
endif
|
||||
|
||||
call random_seed()
|
||||
|
||||
ncandidates=0
|
||||
nsum=0
|
||||
do i=0,62
|
||||
nsum=nsum+rxprob(i)
|
||||
j=indexes(62-i)
|
||||
ratio0(i)=float(rxprob2(j))/(float(rxprob(j))+0.01)
|
||||
ii=int(7.999*ratio0(i))
|
||||
jj=(62-i)/8
|
||||
thresh0(i)=nint(1.3*perr(jj,ii))
|
||||
enddo
|
||||
if(nsum.eq.0) return
|
||||
|
||||
do k=0,ntrials
|
||||
era_pos=0
|
||||
workdat=rxdat
|
||||
numera=0
|
||||
do i=0,62
|
||||
j=indexes(62-i)
|
||||
thresh=thresh0(i)
|
||||
ir=rand()
|
||||
if(...) then
|
||||
era_pos(numera)=j
|
||||
numera=numera+1
|
||||
endif
|
||||
enddo
|
||||
|
||||
call decode_rs_int()
|
||||
if(nerr.ge.0) then
|
||||
ncandidates=ncandidates+1
|
||||
nhard=0
|
||||
nsoft=0
|
||||
nsofter=0
|
||||
do i=0,62
|
||||
if(workdat(i).ne.rxdat(i)) then
|
||||
nhard=nhard+1
|
||||
nsofter=nsofter+rxprob(i)
|
||||
if(workdat(i).ne.rxdat2(i)) nsoft=nsoft+rxprob(i)
|
||||
else
|
||||
nsofter=nsofter-rxprob(i)
|
||||
endif
|
||||
enddo
|
||||
nsoft=63*nsoft/nsum
|
||||
nsofter=63*nsofter/nsum
|
||||
ntotal=nsoft+nhard
|
||||
if(ntotal.lt.ntotal_min) then
|
||||
nsoft_min=nsoft
|
||||
nhard_min=nhard
|
||||
nsofter_min=nsofter
|
||||
ntotal_min=ntotal
|
||||
correct=workdat
|
||||
nera_best=numera
|
||||
ntry=k
|
||||
endif
|
||||
if(ntotal_min.lt.72 .and. nhard_min.lt.42) exit
|
||||
endif
|
||||
if(k.eq.ntrials-1) ntry=k+1
|
||||
enddo
|
||||
|
||||
if(ntotal_min.ge.76 .or. nhard.ge.44) nhard_min=-1
|
||||
|
||||
param(0)=ncandidates
|
||||
param(1)=nhard_min
|
||||
param(2)=nsoft_min
|
||||
param(3)=nera_best
|
||||
param(4)=nsofter_min
|
||||
if(param(0).eq.0) param(2)=-1
|
||||
|
||||
return
|
||||
end subroutine sfrsd
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
srcdir = .
|
||||
prefix = /usr/local
|
||||
exec_prefix=${prefix}
|
||||
CC=gcc
|
||||
|
||||
CFLAGS=-I/usr/local/include -Wall -O3
|
||||
|
||||
all: sfrsd
|
||||
|
||||
encode_rs_int.o: encode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
decode_rs_int.o: decode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
init_rs_int.o: init_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o
|
||||
gcc -g -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a sfrsd
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
srcdir = .
|
||||
prefix = /usr/local
|
||||
exec_prefix=${prefix}
|
||||
CC=gcc
|
||||
|
||||
CFLAGS=-I/usr/local/include -Wall -O3
|
||||
|
||||
all: sfrsd.exe
|
||||
|
||||
encode_rs_int.o: encode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
decode_rs_int.o: decode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
init_rs_int.o: init_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
sfrsd.exe: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o
|
||||
gcc -g -DWIN32 -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a sfrsd.exe
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* Include file to configure the RS codec for character symbols
|
||||
*
|
||||
* Copyright 2002, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
|
||||
#define DTYPE unsigned char
|
||||
|
||||
/* Reed-Solomon codec control block */
|
||||
struct rs {
|
||||
unsigned int mm; /* Bits per symbol */
|
||||
unsigned int nn; /* Symbols per block (= (1<<mm)-1) */
|
||||
unsigned char *alpha_to; /* log lookup table */
|
||||
unsigned char *index_of; /* Antilog lookup table */
|
||||
unsigned char *genpoly; /* Generator polynomial */
|
||||
unsigned int nroots; /* Number of generator roots = number of parity symbols */
|
||||
unsigned char fcr; /* First consecutive root, index form */
|
||||
unsigned char prim; /* Primitive element, index form */
|
||||
unsigned char iprim; /* prim-th root of 1, index form */
|
||||
};
|
||||
|
||||
static inline int modnn(struct rs *rs,int x){
|
||||
while (x >= rs->nn) {
|
||||
x -= rs->nn;
|
||||
x = (x >> rs->mm) + (x & rs->nn);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
#define MODNN(x) modnn(rs,x)
|
||||
|
||||
#define MM (rs->mm)
|
||||
#define NN (rs->nn)
|
||||
#define ALPHA_TO (rs->alpha_to)
|
||||
#define INDEX_OF (rs->index_of)
|
||||
#define GENPOLY (rs->genpoly)
|
||||
#define NROOTS (rs->nroots)
|
||||
#define FCR (rs->fcr)
|
||||
#define PRIM (rs->prim)
|
||||
#define IPRIM (rs->iprim)
|
||||
#define A0 (NN)
|
||||
|
||||
#define ENCODE_RS encode_rs_char
|
||||
#define DECODE_RS decode_rs_char
|
||||
#define INIT_RS init_rs_char
|
||||
#define FREE_RS free_rs_char
|
||||
|
||||
void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity);
|
||||
int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras);
|
||||
void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr,
|
||||
unsigned int prim,unsigned int nroots);
|
||||
void FREE_RS(void *p);
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
/* Reed-Solomon decoder
|
||||
* Copyright 2002 Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
* Modified by Steve Franke, K9AN, for use in a soft-symbol RS decoder
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define NULL ((void *)0)
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#ifdef FIXED
|
||||
#include "fixed.h"
|
||||
#elif defined(BIGSYM)
|
||||
#include "int.h"
|
||||
#else
|
||||
#include "char.h"
|
||||
#endif
|
||||
|
||||
int DECODE_RS(
|
||||
#ifndef FIXED
|
||||
void *p,
|
||||
#endif
|
||||
DTYPE *data, int *eras_pos, int no_eras, int calc_syn){
|
||||
|
||||
#ifndef FIXED
|
||||
struct rs *rs = (struct rs *)p;
|
||||
#endif
|
||||
int deg_lambda, el, deg_omega;
|
||||
int i, j, r,k;
|
||||
DTYPE u,q,tmp,num1,num2,den,discr_r;
|
||||
DTYPE lambda[NROOTS+1]; // Err+Eras Locator poly
|
||||
static DTYPE s[51]; // and syndrome poly
|
||||
DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1];
|
||||
DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS];
|
||||
int syn_error, count;
|
||||
|
||||
if( calc_syn ) {
|
||||
/* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
|
||||
for(i=0;i<NROOTS;i++)
|
||||
s[i] = data[0];
|
||||
|
||||
for(j=1;j<NN;j++){
|
||||
for(i=0;i<NROOTS;i++){
|
||||
if(s[i] == 0){
|
||||
s[i] = data[j];
|
||||
} else {
|
||||
s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert syndromes to index form, checking for nonzero condition */
|
||||
syn_error = 0;
|
||||
for(i=0;i<NROOTS;i++){
|
||||
syn_error |= s[i];
|
||||
s[i] = INDEX_OF[s[i]];
|
||||
}
|
||||
|
||||
|
||||
if (!syn_error) {
|
||||
/* if syndrome is zero, data[] is a codeword and there are no
|
||||
* errors to correct. So return data[] unmodified
|
||||
*/
|
||||
count = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
|
||||
lambda[0] = 1;
|
||||
|
||||
if (no_eras > 0) {
|
||||
/* Init lambda to be the erasure locator polynomial */
|
||||
lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))];
|
||||
for (i = 1; i < no_eras; i++) {
|
||||
u = MODNN(PRIM*(NN-1-eras_pos[i]));
|
||||
for (j = i+1; j > 0; j--) {
|
||||
tmp = INDEX_OF[lambda[j - 1]];
|
||||
if(tmp != A0)
|
||||
lambda[j] ^= ALPHA_TO[MODNN(u + tmp)];
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG >= 1
|
||||
/* Test code that verifies the erasure locator polynomial just constructed
|
||||
Needed only for decoder debugging. */
|
||||
|
||||
/* find roots of the erasure location polynomial */
|
||||
for(i=1;i<=no_eras;i++)
|
||||
reg[i] = INDEX_OF[lambda[i]];
|
||||
|
||||
count = 0;
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
|
||||
q = 1;
|
||||
for (j = 1; j <= no_eras; j++)
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = MODNN(reg[j] + j);
|
||||
q ^= ALPHA_TO[reg[j]];
|
||||
}
|
||||
if (q != 0)
|
||||
continue;
|
||||
/* store root and error location number indices */
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
count++;
|
||||
}
|
||||
if (count != no_eras) {
|
||||
printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras);
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
#if DEBUG >= 2
|
||||
printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
|
||||
for (i = 0; i < count; i++)
|
||||
printf("%d ", loc[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
for(i=0;i<NROOTS+1;i++)
|
||||
b[i] = INDEX_OF[lambda[i]];
|
||||
|
||||
/*
|
||||
* Begin Berlekamp-Massey algorithm to determine error+erasure
|
||||
* locator polynomial
|
||||
*/
|
||||
r = no_eras;
|
||||
el = no_eras;
|
||||
while (++r <= NROOTS) { /* r is the step number */
|
||||
/* Compute discrepancy at the r-th step in poly-form */
|
||||
discr_r = 0;
|
||||
for (i = 0; i < r; i++){
|
||||
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
|
||||
discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])];
|
||||
}
|
||||
}
|
||||
discr_r = INDEX_OF[discr_r]; /* Index form */
|
||||
if (discr_r == A0) {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
} else {
|
||||
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
|
||||
t[0] = lambda[0];
|
||||
for (i = 0 ; i < NROOTS; i++) {
|
||||
if(b[i] != A0)
|
||||
t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])];
|
||||
else
|
||||
t[i+1] = lambda[i+1];
|
||||
}
|
||||
if (2 * el <= r + no_eras - 1) {
|
||||
el = r + no_eras - el;
|
||||
/*
|
||||
* 2 lines below: B(x) <-- inv(discr_r) *
|
||||
* lambda(x)
|
||||
*/
|
||||
for (i = 0; i <= NROOTS; i++)
|
||||
b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN);
|
||||
} else {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
}
|
||||
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert lambda to index form and compute deg(lambda(x)) */
|
||||
deg_lambda = 0;
|
||||
for(i=0;i<NROOTS+1;i++){
|
||||
lambda[i] = INDEX_OF[lambda[i]];
|
||||
if(lambda[i] != A0)
|
||||
deg_lambda = i;
|
||||
}
|
||||
/* Find roots of the error+erasure locator polynomial by Chien search */
|
||||
memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0]));
|
||||
count = 0; /* Number of roots of lambda(x) */
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
|
||||
q = 1; /* lambda[0] is always 0 */
|
||||
for (j = deg_lambda; j > 0; j--){
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = MODNN(reg[j] + j);
|
||||
q ^= ALPHA_TO[reg[j]];
|
||||
}
|
||||
}
|
||||
if (q != 0)
|
||||
continue; /* Not a root */
|
||||
/* store root (index-form) and error location number */
|
||||
#if DEBUG>=2
|
||||
printf("count %d root %d loc %d\n",count,i,k);
|
||||
#endif
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
/* If we've already found max possible roots,
|
||||
* abort the search to save time
|
||||
*/
|
||||
if(++count == deg_lambda)
|
||||
break;
|
||||
}
|
||||
if (deg_lambda != count) {
|
||||
/*
|
||||
* deg(lambda) unequal to number of roots => uncorrectable
|
||||
* error detected
|
||||
*/
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/*
|
||||
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
|
||||
* x**NROOTS). in index form. Also find deg(omega).
|
||||
*/
|
||||
deg_omega = 0;
|
||||
for (i = 0; i < NROOTS;i++){
|
||||
tmp = 0;
|
||||
j = (deg_lambda < i) ? deg_lambda : i;
|
||||
for(;j >= 0; j--){
|
||||
if ((s[i - j] != A0) && (lambda[j] != A0))
|
||||
tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])];
|
||||
}
|
||||
if(tmp != 0)
|
||||
deg_omega = i;
|
||||
omega[i] = INDEX_OF[tmp];
|
||||
}
|
||||
omega[NROOTS] = A0;
|
||||
|
||||
/*
|
||||
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
||||
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
|
||||
*/
|
||||
for (j = count-1; j >=0; j--) {
|
||||
num1 = 0;
|
||||
for (i = deg_omega; i >= 0; i--) {
|
||||
if (omega[i] != A0)
|
||||
num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])];
|
||||
}
|
||||
num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)];
|
||||
den = 0;
|
||||
|
||||
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
|
||||
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
|
||||
if(lambda[i+1] != A0)
|
||||
den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])];
|
||||
}
|
||||
if (den == 0) {
|
||||
#if DEBUG >= 1
|
||||
printf("\n ERROR: denominator = 0\n");
|
||||
#endif
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/* Apply error to data */
|
||||
if (num1 != 0) {
|
||||
data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])];
|
||||
}
|
||||
}
|
||||
finish:
|
||||
if(eras_pos != NULL){
|
||||
for(i=0;i<count;i++)
|
||||
eras_pos[i] = loc[i];
|
||||
}
|
||||
return count;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* Reed-Solomon encoder
|
||||
* Copyright 2002, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FIXED
|
||||
#include "fixed.h"
|
||||
#elif defined(BIGSYM)
|
||||
#include "int.h"
|
||||
#else
|
||||
#include "char.h"
|
||||
#endif
|
||||
|
||||
void ENCODE_RS(
|
||||
#ifndef FIXED
|
||||
void *p,
|
||||
#endif
|
||||
DTYPE *data, DTYPE *bb){
|
||||
#ifndef FIXED
|
||||
struct rs *rs = (struct rs *)p;
|
||||
#endif
|
||||
int i, j;
|
||||
DTYPE feedback;
|
||||
|
||||
memset(bb,0,NROOTS*sizeof(DTYPE));
|
||||
|
||||
for(i=0;i<NN-NROOTS;i++){
|
||||
feedback = INDEX_OF[data[i] ^ bb[0]];
|
||||
if(feedback != A0){ /* feedback term is non-zero */
|
||||
#ifdef UNNORMALIZED
|
||||
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
||||
* always be for the polynomials constructed by init_rs()
|
||||
*/
|
||||
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
|
||||
#endif
|
||||
for(j=1;j<NROOTS;j++)
|
||||
bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
|
||||
}
|
||||
/* Shift */
|
||||
memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1));
|
||||
if(feedback != A0)
|
||||
bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
|
||||
else
|
||||
bb[NROOTS-1] = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* Configure the RS codec with fixed parameters for CCSDS standard
|
||||
* (255,223) code over GF(256). Note: the conventional basis is still
|
||||
* used; the dual-basis mappings are performed in [en|de]code_rs_ccsds.c
|
||||
*
|
||||
* Copyright 2002 Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#define DTYPE unsigned char
|
||||
|
||||
static inline int mod255(int x){
|
||||
while (x >= 255) {
|
||||
x -= 255;
|
||||
x = (x >> 8) + (x & 255);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
#define MODNN(x) mod255(x)
|
||||
|
||||
extern unsigned char CCSDS_alpha_to[];
|
||||
extern unsigned char CCSDS_index_of[];
|
||||
extern unsigned char CCSDS_poly[];
|
||||
|
||||
#define MM 8
|
||||
#define NN 255
|
||||
#define ALPHA_TO CCSDS_alpha_to
|
||||
#define INDEX_OF CCSDS_index_of
|
||||
#define GENPOLY CCSDS_poly
|
||||
#define NROOTS 32
|
||||
#define FCR 112
|
||||
#define PRIM 11
|
||||
#define IPRIM 116
|
||||
#define A0 (NN)
|
||||
|
||||
#define ENCODE_RS encode_rs_8
|
||||
#define DECODE_RS decode_rs_8
|
||||
|
||||
void ENCODE_RS(DTYPE *data,DTYPE *parity);
|
||||
int DECODE_RS(DTYPE *data, int *eras_pos, int no_eras);
|
|
@ -0,0 +1,121 @@
|
|||
/* Initialize a RS codec
|
||||
*
|
||||
* Copyright 2002 Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef CCSDS
|
||||
#include "ccsds.h"
|
||||
#elif defined(BIGSYM)
|
||||
#include "int.h"
|
||||
#else
|
||||
#include "char.h"
|
||||
#endif
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
void FREE_RS(void *p){
|
||||
struct rs *rs = (struct rs *)p;
|
||||
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs->genpoly);
|
||||
free(rs);
|
||||
}
|
||||
|
||||
/* Initialize a Reed-Solomon codec
|
||||
* symsize = symbol size, bits (1-8)
|
||||
* gfpoly = Field generator polynomial coefficients
|
||||
* fcr = first root of RS code generator polynomial, index form
|
||||
* prim = primitive element to generate polynomial roots
|
||||
* nroots = RS code generator polynomial degree (number of roots)
|
||||
*/
|
||||
void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim,
|
||||
unsigned int nroots){
|
||||
struct rs *rs;
|
||||
int i, j, sr,root,iprim;
|
||||
|
||||
if(symsize > 8*sizeof(DTYPE))
|
||||
return NULL; /* Need version with ints rather than chars */
|
||||
|
||||
if(fcr >= (1<<symsize))
|
||||
return NULL;
|
||||
if(prim == 0 || prim >= (1<<symsize))
|
||||
return NULL;
|
||||
if(nroots >= (1<<symsize))
|
||||
return NULL; /* Can't have more roots than symbol values! */
|
||||
|
||||
rs = (struct rs *)calloc(1,sizeof(struct rs));
|
||||
rs->mm = symsize;
|
||||
rs->nn = (1<<symsize)-1;
|
||||
|
||||
rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
|
||||
if(rs->alpha_to == NULL){
|
||||
free(rs);
|
||||
return NULL;
|
||||
}
|
||||
rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1));
|
||||
if(rs->index_of == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generate Galois field lookup tables */
|
||||
rs->index_of[0] = A0; /* log(zero) = -inf */
|
||||
rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
|
||||
sr = 1;
|
||||
for(i=0;i<rs->nn;i++){
|
||||
rs->index_of[sr] = i;
|
||||
rs->alpha_to[i] = sr;
|
||||
sr <<= 1;
|
||||
if(sr & (1<<symsize))
|
||||
sr ^= gfpoly;
|
||||
sr &= rs->nn;
|
||||
}
|
||||
if(sr != 1){
|
||||
/* field generator polynomial is not primitive! */
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Form RS code generator polynomial from its roots */
|
||||
rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1));
|
||||
if(rs->genpoly == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs);
|
||||
return NULL;
|
||||
}
|
||||
rs->fcr = fcr;
|
||||
rs->prim = prim;
|
||||
rs->nroots = nroots;
|
||||
|
||||
/* Find prim-th root of 1, used in decoding */
|
||||
for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
|
||||
;
|
||||
rs->iprim = iprim / prim;
|
||||
|
||||
rs->genpoly[0] = 1;
|
||||
for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
|
||||
rs->genpoly[i+1] = 1;
|
||||
|
||||
/* Multiply rs->genpoly[] by @**(root + x) */
|
||||
for (j = i; j > 0; j--){
|
||||
if (rs->genpoly[j] != 0)
|
||||
rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
|
||||
else
|
||||
rs->genpoly[j] = rs->genpoly[j-1];
|
||||
}
|
||||
/* rs->genpoly[0] can never be zero */
|
||||
rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
|
||||
}
|
||||
/* convert rs->genpoly[] to index form for quicker encoding */
|
||||
for (i = 0; i <= nroots; i++)
|
||||
rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
|
||||
|
||||
return rs;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* Include file to configure the RS codec for integer symbols
|
||||
*
|
||||
* Copyright 2002, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#define DTYPE int
|
||||
|
||||
/* Reed-Solomon codec control block */
|
||||
struct rs {
|
||||
unsigned int mm; /* Bits per symbol */
|
||||
unsigned int nn; /* Symbols per block (= (1<<mm)-1) */
|
||||
int *alpha_to; /* log lookup table */
|
||||
int *index_of; /* Antilog lookup table */
|
||||
int *genpoly; /* Generator polynomial */
|
||||
unsigned int nroots; /* Number of generator roots = number of parity symbols */
|
||||
unsigned int fcr; /* First consecutive root, index form */
|
||||
unsigned int prim; /* Primitive element, index form */
|
||||
unsigned int iprim; /* prim-th root of 1, index form */
|
||||
};
|
||||
|
||||
static inline int modnn(struct rs *rs,int x){
|
||||
while (x >= rs->nn) {
|
||||
x -= rs->nn;
|
||||
x = (x >> rs->mm) + (x & rs->nn);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
#define MODNN(x) modnn(rs,x)
|
||||
|
||||
#define MM (rs->mm)
|
||||
#define NN (rs->nn)
|
||||
#define ALPHA_TO (rs->alpha_to)
|
||||
#define INDEX_OF (rs->index_of)
|
||||
#define GENPOLY (rs->genpoly)
|
||||
#define NROOTS (rs->nroots)
|
||||
#define FCR (rs->fcr)
|
||||
#define PRIM (rs->prim)
|
||||
#define IPRIM (rs->iprim)
|
||||
#define A0 (NN)
|
||||
|
||||
#define ENCODE_RS encode_rs_int
|
||||
#define DECODE_RS decode_rs_int
|
||||
#define INIT_RS init_rs_int
|
||||
#define FREE_RS free_rs_int
|
||||
|
||||
void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity);
|
||||
int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras, int calc_syn);
|
||||
void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr,
|
||||
unsigned int prim,unsigned int nroots);
|
||||
void FREE_RS(void *p);
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
/* User include file for the Reed-Solomon codec
|
||||
* Copyright 2002, Phil Karn KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
|
||||
/* General purpose RS codec, integer symbols */
|
||||
void encode_rs_int(void *rs,int *data,int *parity);
|
||||
int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras, int calc_syn);
|
||||
void *init_rs_int(int symsize,int gfpoly,int fcr,
|
||||
int prim,int nroots,int pad);
|
||||
void free_rs_int(void *rs);
|
||||
|
||||
/* Tables to map from conventional->dual (Taltab) and
|
||||
* dual->conventional (Tal1tab) bases
|
||||
*/
|
||||
extern unsigned char Taltab[],Tal1tab[];
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
./jt65code "Hi there"
|
||||
Message Decoded Err? Type
|
||||
--------------------------------------------------------------------------
|
||||
1. HI THERE HI THERE 6: Free text
|
||||
|
||||
Packed message, 6-bit symbols 25 57 1 8 29 22 61 14 46 15 56 28
|
||||
|
||||
Information-carrying channel symbols
|
||||
34 27 12 48 28 59 12 38 25 47 21 40 46 9 12 24 36 7 4 15 49
|
||||
50 6 49 56 2 19 15 7 59 22 7 5 14 20 3 29 56 2 9 17 14
|
||||
45 26 43 31 17 10 50 31 2 25 57 1 8 29 22 61 14 46 15 56 28
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "rs.h"
|
||||
|
||||
static void *rs;
|
||||
|
||||
int main(){
|
||||
int hi_there[]={25,57,1,8,29,22,61,14,46,15,56,28};
|
||||
int data[12], revdat[12];
|
||||
int parity[51];
|
||||
int rxdat[63], errlocs[63];
|
||||
int era_pos[51];
|
||||
int i, numera, nerr, nn=63;
|
||||
|
||||
FILE *datfile;
|
||||
//nsec,xlambda,maxe,nads,mrsym,mrprob,mr2sym,mr2prob
|
||||
int nsec, maxe, nads;
|
||||
float xlambda;
|
||||
int mrsym[63],mrprob[63],mr2sym[63],mr2prob[63];
|
||||
int nsec2,ncount,dat4[12];
|
||||
|
||||
datfile=fopen("kvasd.dat","rb");
|
||||
if( !datfile ) {
|
||||
printf("Unable to open kvasd.dat\n");
|
||||
return 1;
|
||||
} else {
|
||||
fread(&nsec,sizeof(int),1,datfile);
|
||||
fread(&xlambda,sizeof(float),1,datfile);
|
||||
fread(&maxe,sizeof(int),1,datfile);
|
||||
fread(&nads,sizeof(int),1,datfile);
|
||||
fread(&mrsym,sizeof(int),63,datfile);
|
||||
fread(&mrprob,sizeof(int),63,datfile);
|
||||
fread(&mr2sym,sizeof(int),63,datfile);
|
||||
fread(&mr2prob,sizeof(int),63,datfile);
|
||||
fread(&nsec2,sizeof(int),1,datfile);
|
||||
fread(&ncount,sizeof(int),1,datfile);
|
||||
fread(&dat4,sizeof(int),12,datfile);
|
||||
fclose(datfile);
|
||||
printf("%d %f %d %d \n",nsec,xlambda,maxe,nads);
|
||||
for (i=0; i<63; i++) printf("%d ",mrsym[i]);
|
||||
printf("\n");
|
||||
// for (i=0; i<63; i++) printf("%d ",mrprob[i]);
|
||||
// printf("\n");
|
||||
// for (i=0; i<63; i++) printf("%d ",mr2sym[i]);
|
||||
// printf("\n");
|
||||
// for (i=0; i<63; i++) printf("%d ",mr2prob[i]);
|
||||
// printf("\n");
|
||||
// printf("%d %d \n",nsec2,ncount);
|
||||
printf("kv decode: ");
|
||||
for (i=0; i<12; i++) printf("%d ",dat4[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// initialize the ka9q reed solomon encoder/decoder
|
||||
unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51;
|
||||
rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0);
|
||||
|
||||
// copy the 'hi there' message to the data vector
|
||||
// memcpy(data,hi_there,sizeof(hi_there));
|
||||
// memcpy(data,dat4,sizeof(dat4));
|
||||
|
||||
// printf("data symbols\n");
|
||||
// for( i=0; i<12; i++) {
|
||||
// revdat[i]=data[11-i];
|
||||
// printf("%d ",data[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
// encode_rs_int(rs,revdat,parity);
|
||||
|
||||
//set up the received symbol vector
|
||||
// for( i=0; i<63; i++ ) {
|
||||
// if( i < 12 ) rxdat[i]=revdat[i];
|
||||
// if( i >=12 ) rxdat[i]=parity[i-12];
|
||||
// }
|
||||
|
||||
/*
|
||||
int errval, errloc;
|
||||
int num_errors=0;
|
||||
printf("num_errors = %d\n",num_errors);
|
||||
for( i=0; i<num_errors; i++) {
|
||||
do {
|
||||
errval = random() & nn;
|
||||
} while(errval == 0); //generate random
|
||||
|
||||
do {
|
||||
errloc = random() % nn;
|
||||
} while(errlocs[errloc]!=0);
|
||||
|
||||
errlocs[errloc] = errval;
|
||||
rxdat[errloc] ^= errval;
|
||||
}
|
||||
*/
|
||||
|
||||
numera=0;
|
||||
printf("channel symbols\n");
|
||||
for( i=0; i<63; i++ ) {
|
||||
rxdat[i]=mrsym[i];
|
||||
printf("%d ",rxdat[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
nerr=decode_rs_int(rs,rxdat,era_pos,numera);
|
||||
|
||||
printf("nerr %d\n",nerr);
|
||||
|
||||
printf("decoded data\n");
|
||||
for(i=0; i<63; i++) printf("%d ",rxdat[i]);
|
||||
printf("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
sfrsd.c
|
||||
|
||||
A soft-decision decoder for the JT65 (63,12) Reed-Solomon code.
|
||||
|
||||
This decoding scheme is built around Phil Karn's Berlekamp-Massey
|
||||
errors and erasures decoder. The approach is inspired by a number of
|
||||
publications, including the stochastic Chase decoder described
|
||||
in "Stochastic Chase Decoding of Reed-Solomon Codes", by Leroux et al.,
|
||||
IEEE Communications Letters, Vol. 14, No. 9, September 2010 and
|
||||
"Soft-Decision Decoding of Reed-Solomon Codes Using Successive Error-
|
||||
and-Erasure Decoding," by Soo-Woong Lee and B. V. K. Vijaya Kumar.
|
||||
|
||||
Steve Franke K9AN, Urbana IL, September 2015
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "rs.h"
|
||||
|
||||
static void *rs;
|
||||
|
||||
//***************************************************************************
|
||||
void usage(void)
|
||||
{
|
||||
printf("Usage: sfrsd [options...] <path to kvasd.dat>\n");
|
||||
printf(" input file should be in kvasd format\n");
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -n number of random erasure vectors to try\n");
|
||||
printf(" -v verbose\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
int rxdat[63], rxprob[63], rxdat2[63], rxprob2[63];
|
||||
int workdat[63], correct[63];
|
||||
int era_pos[51];
|
||||
int c, i, numera, nerr, nn=63, kk=12;
|
||||
char *infile;
|
||||
|
||||
FILE *datfile, *logfile;
|
||||
int nsec, maxe, nads;
|
||||
float xlambda;
|
||||
int mrsym[63],mrprob[63],mr2sym[63],mr2prob[63];
|
||||
int nsec2,ncount,dat4[12],bestdat[12];
|
||||
int ntrials=10000;
|
||||
int verbose=0;
|
||||
int nhard=0,nhard_min=32768,nsoft=0,nsoft_min=32768, ncandidates;
|
||||
|
||||
while ( (c = getopt(argc, argv, "n:qv")) !=-1 ) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
ntrials=(int)strtof(optarg,NULL);
|
||||
printf("ntrials set to %d\n",ntrials);
|
||||
break;
|
||||
case 'v':
|
||||
verbose=1;
|
||||
break;
|
||||
case 'q': //accept (and ignore) -q option for WSJT10 compatibility
|
||||
break;
|
||||
case '?':
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if( optind+1 > argc) {
|
||||
// usage();
|
||||
// exit(1);
|
||||
infile="kvasd.dat";
|
||||
} else {
|
||||
infile=argv[optind];
|
||||
}
|
||||
|
||||
logfile=fopen("/tmp/sfrsd.log","a");
|
||||
if( !logfile ) {
|
||||
printf("Unable to open sfrsd.log\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
datfile=fopen(infile,"rb");
|
||||
if( !datfile ) {
|
||||
printf("Unable to open kvasd.dat\n");
|
||||
exit(1);
|
||||
} else {
|
||||
fread(&nsec,sizeof(int),1,datfile);
|
||||
fread(&xlambda,sizeof(float),1,datfile);
|
||||
fread(&maxe,sizeof(int),1,datfile);
|
||||
fread(&nads,sizeof(int),1,datfile);
|
||||
fread(&mrsym,sizeof(int),63,datfile);
|
||||
fread(&mrprob,sizeof(int),63,datfile);
|
||||
fread(&mr2sym,sizeof(int),63,datfile);
|
||||
fread(&mr2prob,sizeof(int),63,datfile);
|
||||
fread(&nsec2,sizeof(int),1,datfile);
|
||||
fread(&ncount,sizeof(int),1,datfile);
|
||||
// printf("ncount %d\n",ncount);
|
||||
fread(&dat4,sizeof(int),12,datfile);
|
||||
fclose(datfile);
|
||||
}
|
||||
|
||||
// initialize the ka9q reed solomon encoder/decoder
|
||||
unsigned int symsize=6, gfpoly=0x43, fcr=3, prim=1, nroots=51;
|
||||
rs=init_rs_int(symsize, gfpoly, fcr, prim, nroots, 0);
|
||||
|
||||
/* // debug
|
||||
int revdat[12], parity[51], correct[63];
|
||||
for (i=0; i<12; i++) {
|
||||
revdat[i]=dat4[11-i];
|
||||
printf("%d ",revdat[i]);
|
||||
}
|
||||
printf("\n");
|
||||
encode_rs_int(rs,revdat,parity);
|
||||
for (i=0; i<63; i++) {
|
||||
if( i<12 ) {
|
||||
correct[i]=revdat[i];
|
||||
printf("%d ",parity[i]);
|
||||
} else {
|
||||
correct[i]=parity[i-12];
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
// reverse the received symbol vector for bm decoder
|
||||
for (i=0; i<63; i++) {
|
||||
rxdat[i]=mrsym[62-i];
|
||||
rxprob[i]=mrprob[62-i];
|
||||
rxdat2[i]=mr2sym[62-i];
|
||||
rxprob2[i]=mr2prob[62-i];
|
||||
}
|
||||
|
||||
// sort the mrsym probabilities to find the least reliable symbols
|
||||
int k, pass, tmp, nsym=63;
|
||||
int probs[63], indexes[63];
|
||||
for (i=0; i<63; i++) {
|
||||
indexes[i]=i;
|
||||
probs[i]=rxprob[i]; // must un-comment sfrsd metrics in demod64a
|
||||
|
||||
}
|
||||
for (pass = 1; pass <= nsym-1; pass++) {
|
||||
for (k = 0; k < nsym - pass; k++) {
|
||||
if( probs[k] < probs[k+1] ) {
|
||||
tmp = probs[k];
|
||||
probs[k] = probs[k+1];
|
||||
probs[k+1] = tmp;
|
||||
tmp = indexes[k];
|
||||
indexes[k] = indexes[k+1];
|
||||
indexes[k+1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// see if we can decode using BM HDD (and calculate the syndrome vector)
|
||||
memset(era_pos,0,51*sizeof(int));
|
||||
numera=0;
|
||||
memcpy(workdat,rxdat,sizeof(rxdat));
|
||||
nerr=decode_rs_int(rs,workdat,era_pos,numera,1);
|
||||
if( nerr >= 0 ) {
|
||||
fprintf(logfile," BM decode nerrors= %3d : ",nerr);
|
||||
for(i=0; i<12; i++) printf("%2d ",workdat[11-i]);
|
||||
fprintf(logfile,"\n");
|
||||
fclose(logfile);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// generate random erasure-locator vectors and see if any of them
|
||||
// decode. This will generate a list of potential codewords. The
|
||||
// "soft" distance between each codeword and the received word is
|
||||
// used to decide which codeword is "best".
|
||||
//
|
||||
// srandom(time(NULL));
|
||||
#ifdef WIN32
|
||||
srand(0xdeadbeef);
|
||||
#else
|
||||
srandom(0xdeadbeef);
|
||||
#endif
|
||||
float p_erase;
|
||||
int thresh, nsum;
|
||||
ncandidates=0;
|
||||
|
||||
|
||||
for( k=0; k<ntrials; k++) {
|
||||
memset(era_pos,0,51*sizeof(int));
|
||||
memcpy(workdat,rxdat,sizeof(rxdat));
|
||||
|
||||
// mark a subset of the symbols as erasures
|
||||
numera=0;
|
||||
for (i=0; i<nn; i++) {
|
||||
p_erase=0.0;
|
||||
if( probs[62-i] >= 255 ) {
|
||||
p_erase = 0.5;
|
||||
} else if ( probs[62-i] >= 196 ) {
|
||||
p_erase = 0.6;
|
||||
} else if ( probs[62-i] >= 128 ) {
|
||||
p_erase = 0.6;
|
||||
} else if ( probs[62-i] >= 32 ) {
|
||||
p_erase = 0.6;
|
||||
} else {
|
||||
p_erase = 0.8;
|
||||
}
|
||||
thresh = p_erase*100;
|
||||
long int ir;
|
||||
#ifdef WIN32
|
||||
ir=rand();
|
||||
#else
|
||||
ir=random();
|
||||
#endif
|
||||
if( ((ir % 100) < thresh ) && numera < 51 ) {
|
||||
era_pos[numera]=indexes[62-i];
|
||||
numera=numera+1;
|
||||
}
|
||||
}
|
||||
|
||||
nerr=decode_rs_int(rs,workdat,era_pos,numera,0);
|
||||
|
||||
if( nerr >= 0 ) {
|
||||
ncandidates=ncandidates+1;
|
||||
for(i=0; i<12; i++) dat4[i]=workdat[11-i];
|
||||
// fprintf(logfile,"loop1 decode nerr= %3d : ",nerr);
|
||||
// for(i=0; i<12; i++) fprintf(logfile, "%2d ",dat4[i]);
|
||||
// fprintf(logfile,"\n");
|
||||
nhard=0;
|
||||
nsoft=0;
|
||||
nsum=0;
|
||||
for (i=0; i<63; i++) {
|
||||
nsum=nsum+rxprob[i];
|
||||
if( workdat[i] != rxdat[i] ) {
|
||||
nhard=nhard+1;
|
||||
nsoft=nsoft+rxprob[i];
|
||||
}
|
||||
}
|
||||
if( nsum != 0 ) {
|
||||
nsoft=63*nsoft/nsum;
|
||||
if( (nsoft < nsoft_min) ) {
|
||||
nsoft_min=nsoft;
|
||||
nhard_min=nhard;
|
||||
memcpy(bestdat,dat4,12*sizeof(int));
|
||||
memcpy(correct,workdat,63*sizeof(int));
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(logfile,"error - nsum %d nsoft %d nhard %d\n",nsum,nsoft,nhard);
|
||||
}
|
||||
// if( ncandidates >= 5000 ) {
|
||||
if( ncandidates >= ntrials/2 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(logfile,"%d candidates after stochastic loop\n",ncandidates);
|
||||
|
||||
// do Forney Generalized Minimum Distance pattern
|
||||
for (k=0; k<25; k++) {
|
||||
memset(era_pos,0,51*sizeof(int));
|
||||
numera=2*k;
|
||||
for (i=0; i<numera; i++) {
|
||||
era_pos[i]=indexes[62-i];
|
||||
}
|
||||
|
||||
memcpy(workdat,rxdat,sizeof(rxdat));
|
||||
nerr=decode_rs_int(rs,workdat,era_pos,numera,0);
|
||||
|
||||
if( nerr >= 0 ) {
|
||||
ncandidates=ncandidates+1;
|
||||
for(i=0; i<12; i++) dat4[i]=workdat[11-i];
|
||||
// fprintf(logfile,"GMD decode nerr= %3d : ",nerr);
|
||||
// for(i=0; i<12; i++) fprintf(logfile, "%2d ",dat4[i]);
|
||||
// fprintf(logfile,"\n");
|
||||
nhard=0;
|
||||
nsoft=0;
|
||||
nsum=0;
|
||||
for (i=0; i<63; i++) {
|
||||
nsum=nsum+rxprob[i];
|
||||
if( workdat[i] != rxdat[i] ) {
|
||||
nhard=nhard+1;
|
||||
nsoft=nsoft+rxprob[i];
|
||||
}
|
||||
}
|
||||
if( nsum != 0 ) {
|
||||
nsoft=63*nsoft/nsum;
|
||||
if( (nsoft < nsoft_min) ) {
|
||||
nsoft_min=nsoft;
|
||||
nhard_min=nhard;
|
||||
memcpy(bestdat,dat4,12*sizeof(int));
|
||||
memcpy(correct,workdat,63*sizeof(int));
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(logfile,"error - nsum %d nsoft %d nhard %d\n",nsum,nsoft,nhard);
|
||||
}
|
||||
// if( ncandidates >=5000 ) {
|
||||
if( ncandidates >= ntrials/2 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(logfile,"%d candidates after GMD\n",ncandidates);
|
||||
|
||||
if( (ncandidates >= 0) && (nsoft_min < 36) && (nhard_min < 44) ) {
|
||||
for (i=0; i<63; i++) {
|
||||
fprintf(logfile,"%3d %3d %3d %3d %3d %3d\n",i,correct[i],rxdat[i],rxprob[i],rxdat2[i],rxprob2[i]);
|
||||
// fprintf(logfile,"%3d %3d %3d %3d %3d\n",i,workdat[i],rxdat[i],rxprob[i],rxdat2[i],rxprob2[i]);
|
||||
}
|
||||
|
||||
fprintf(logfile,"**** ncandidates %d nhard %d nsoft %d nsum %d\n",ncandidates,nhard_min,nsoft_min,nsum);
|
||||
} else {
|
||||
nhard_min=-1;
|
||||
memset(bestdat,0,12*sizeof(int));
|
||||
}
|
||||
datfile=fopen(infile,"wb");
|
||||
if( !datfile ) {
|
||||
printf("Unable to open kvasd.dat\n");
|
||||
return 1;
|
||||
} else {
|
||||
fwrite(&nsec,sizeof(int),1,datfile);
|
||||
fwrite(&xlambda,sizeof(float),1,datfile);
|
||||
fwrite(&maxe,sizeof(int),1,datfile);
|
||||
fwrite(&nads,sizeof(int),1,datfile);
|
||||
fwrite(&mrsym,sizeof(int),63,datfile);
|
||||
fwrite(&mrprob,sizeof(int),63,datfile);
|
||||
fwrite(&mr2sym,sizeof(int),63,datfile);
|
||||
fwrite(&mr2prob,sizeof(int),63,datfile);
|
||||
fwrite(&nsec2,sizeof(int),1,datfile);
|
||||
fwrite(&nhard_min,sizeof(int),1,datfile);
|
||||
fwrite(&bestdat,sizeof(int),12,datfile);
|
||||
fclose(datfile);
|
||||
}
|
||||
|
||||
fprintf(logfile,"exiting sfrsd\n");
|
||||
fflush(logfile);
|
||||
fclose(logfile);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
# Makefile for Windows in JTSDK-PY environment
|
||||
|
||||
# Re-direct stdout and stderr: cmd.exe bash
|
||||
# make > junk 2>&1 make &> junk
|
||||
|
||||
CC = gcc
|
||||
FC = gfortran
|
||||
|
||||
FFLAGS = -O2 -DWIN32 -fbounds-check -fno-second-underscore -Wall \
|
||||
-Wno-conversion -Wno-character-truncation
|
||||
CFLAGS = -I. -DWIN32 -DWin32 -DBIGSYM -DHAVE_STRUCT_TIMESPEC
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: libsfrsd.a
|
||||
|
||||
OBJS1 = extract2.o sfrsd2.o init_rs_int.o encode_rs_int.o decode_rs_int.o
|
||||
libsfrsd.a: $(OBJS1)
|
||||
ar cr libsfrsd.a $(OBJS1)
|
||||
ranlib libsfrsd.a
|
||||
cp libsfrsd.a ..
|
||||
|
||||
# Build rsdtest
|
||||
OBJS2 = rsdtest.o
|
||||
rsdtest: $(OBJS2) ../libjt.a
|
||||
$(FC) -o rsdtest $(OBJS2) libsfrsd.a ../libjt.a ../libpthreadGC2.a
|
||||
|
||||
sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o
|
||||
gcc -g -o $@ $^
|
||||
|
||||
encode_rs_int.o: encode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
decode_rs_int.o: decode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
init_rs_int.o: init_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
rm -rf *.o libjt.a rsdtest sfrsd
|
|
@ -0,0 +1,30 @@
|
|||
srcdir = .
|
||||
prefix = /usr/local
|
||||
exec_prefix=${prefix}
|
||||
CC=gcc
|
||||
|
||||
CFLAGS=-I/usr/local/include -Wall -O2
|
||||
|
||||
all: encode_rs_int.o decode_rs_int.o init_rs_int.o sfrsd2.o sfrsd.o sfrsd
|
||||
|
||||
encode_rs_int.o: encode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
decode_rs_int.o: decode_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
init_rs_int.o: init_rs.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
sfrsd2.o: sfrsd2.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
sfrsd.o: sfrsd.c
|
||||
gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^
|
||||
|
||||
sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o sfrsd2.o
|
||||
gcc -g -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a sfrsd
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Makefile for Windows in JTSDK-PY environment
|
||||
|
||||
# Re-direct stdout and stderr: cmd.exe bash
|
||||
# make > junk 2>&1 make &> junk
|
||||
|
||||
CC = gcc
|
||||
FC = gfortran
|
||||
|
||||
FFLAGS = -O2 -DWIN32 -fbounds-check -fno-second-underscore -Wall \
|
||||
-Wno-conversion -Wno-character-truncation
|
||||
CFLAGS = -I. -DWIN32 -DWin32 -DBIGSYM -DHAVE_STRUCT_TIMESPEC
|
||||
|
||||
# Default rules
|
||||
%.o: %.c
|
||||
${CC} ${CFLAGS} -c $<
|
||||
%.o: %.f
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.f90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
%.o: %.F90
|
||||
${FC} ${FFLAGS} -c $<
|
||||
|
||||
all: rsdtest
|
||||
|
||||
# Build rsdtest
|
||||
OBJS2 = rsdtest.o extract2.o demod64b.o sfrsd3.o
|
||||
rsdtest: $(OBJS2) ../libjt.a
|
||||
$(FC) -o rsdtest $(OBJS2) ../libjt.a ../libpthreadGC2.a
|
||||
|
||||
sfrsd: sfrsd.o encode_rs_int.o decode_rs_int.o init_rs_int.o
|
||||
gcc -g -o $@ $^
|
||||
|
||||
.PHONY : clean
|
||||
|
||||
clean:
|
||||
rm -rf *.o libjt.a rsdtest sfrsd
|
|
@ -0,0 +1,268 @@
|
|||
/* Reed-Solomon decoder
|
||||
* Copyright 2002 Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
* Modified by Steve Franke, K9AN, for use in a soft-symbol RS decoder
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define NULL ((void *)0)
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#ifdef FIXED
|
||||
#include "fixed.h"
|
||||
#elif defined(BIGSYM)
|
||||
#include "int.h"
|
||||
#else
|
||||
#include "char.h"
|
||||
#endif
|
||||
|
||||
int DECODE_RS(
|
||||
#ifndef FIXED
|
||||
void *p,
|
||||
#endif
|
||||
DTYPE *data, int *eras_pos, int no_eras, int calc_syn){
|
||||
|
||||
#ifndef FIXED
|
||||
struct rs *rs = (struct rs *)p;
|
||||
#endif
|
||||
int deg_lambda, el, deg_omega;
|
||||
int i, j, r,k;
|
||||
DTYPE u,q,tmp,num1,num2,den,discr_r;
|
||||
DTYPE lambda[NROOTS+1]; // Err+Eras Locator poly
|
||||
static DTYPE s[51]; // and syndrome poly
|
||||
DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1];
|
||||
DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS];
|
||||
int syn_error, count;
|
||||
|
||||
if( calc_syn ) {
|
||||
/* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
|
||||
for(i=0;i<NROOTS;i++)
|
||||
s[i] = data[0];
|
||||
|
||||
for(j=1;j<NN;j++){
|
||||
for(i=0;i<NROOTS;i++){
|
||||
if(s[i] == 0){
|
||||
s[i] = data[j];
|
||||
} else {
|
||||
s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert syndromes to index form, checking for nonzero condition */
|
||||
syn_error = 0;
|
||||
for(i=0;i<NROOTS;i++){
|
||||
syn_error |= s[i];
|
||||
s[i] = INDEX_OF[s[i]];
|
||||
}
|
||||
|
||||
|
||||
if (!syn_error) {
|
||||
/* if syndrome is zero, data[] is a codeword and there are no
|
||||
* errors to correct. So return data[] unmodified
|
||||
*/
|
||||
count = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset(&lambda[1],0,NROOTS*sizeof(lambda[0]));
|
||||
lambda[0] = 1;
|
||||
|
||||
if (no_eras > 0) {
|
||||
/* Init lambda to be the erasure locator polynomial */
|
||||
lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))];
|
||||
for (i = 1; i < no_eras; i++) {
|
||||
u = MODNN(PRIM*(NN-1-eras_pos[i]));
|
||||
for (j = i+1; j > 0; j--) {
|
||||
tmp = INDEX_OF[lambda[j - 1]];
|
||||
if(tmp != A0)
|
||||
lambda[j] ^= ALPHA_TO[MODNN(u + tmp)];
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG >= 1
|
||||
/* Test code that verifies the erasure locator polynomial just constructed
|
||||
Needed only for decoder debugging. */
|
||||
|
||||
/* find roots of the erasure location polynomial */
|
||||
for(i=1;i<=no_eras;i++)
|
||||
reg[i] = INDEX_OF[lambda[i]];
|
||||
|
||||
count = 0;
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
|
||||
q = 1;
|
||||
for (j = 1; j <= no_eras; j++)
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = MODNN(reg[j] + j);
|
||||
q ^= ALPHA_TO[reg[j]];
|
||||
}
|
||||
if (q != 0)
|
||||
continue;
|
||||
/* store root and error location number indices */
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
count++;
|
||||
}
|
||||
if (count != no_eras) {
|
||||
printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras);
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
#if DEBUG >= 2
|
||||
printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
|
||||
for (i = 0; i < count; i++)
|
||||
printf("%d ", loc[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
for(i=0;i<NROOTS+1;i++)
|
||||
b[i] = INDEX_OF[lambda[i]];
|
||||
|
||||
/*
|
||||
* Begin Berlekamp-Massey algorithm to determine error+erasure
|
||||
* locator polynomial
|
||||
*/
|
||||
r = no_eras;
|
||||
el = no_eras;
|
||||
while (++r <= NROOTS) { /* r is the step number */
|
||||
/* Compute discrepancy at the r-th step in poly-form */
|
||||
discr_r = 0;
|
||||
for (i = 0; i < r; i++){
|
||||
if ((lambda[i] != 0) && (s[r-i-1] != A0)) {
|
||||
discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])];
|
||||
}
|
||||
}
|
||||
discr_r = INDEX_OF[discr_r]; /* Index form */
|
||||
if (discr_r == A0) {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
} else {
|
||||
/* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
|
||||
t[0] = lambda[0];
|
||||
for (i = 0 ; i < NROOTS; i++) {
|
||||
if(b[i] != A0)
|
||||
t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])];
|
||||
else
|
||||
t[i+1] = lambda[i+1];
|
||||
}
|
||||
if (2 * el <= r + no_eras - 1) {
|
||||
el = r + no_eras - el;
|
||||
/*
|
||||
* 2 lines below: B(x) <-- inv(discr_r) *
|
||||
* lambda(x)
|
||||
*/
|
||||
for (i = 0; i <= NROOTS; i++)
|
||||
b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN);
|
||||
} else {
|
||||
/* 2 lines below: B(x) <-- x*B(x) */
|
||||
memmove(&b[1],b,NROOTS*sizeof(b[0]));
|
||||
b[0] = A0;
|
||||
}
|
||||
memcpy(lambda,t,(NROOTS+1)*sizeof(t[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert lambda to index form and compute deg(lambda(x)) */
|
||||
deg_lambda = 0;
|
||||
for(i=0;i<NROOTS+1;i++){
|
||||
lambda[i] = INDEX_OF[lambda[i]];
|
||||
if(lambda[i] != A0)
|
||||
deg_lambda = i;
|
||||
}
|
||||
/* Find roots of the error+erasure locator polynomial by Chien search */
|
||||
memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0]));
|
||||
count = 0; /* Number of roots of lambda(x) */
|
||||
for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) {
|
||||
q = 1; /* lambda[0] is always 0 */
|
||||
for (j = deg_lambda; j > 0; j--){
|
||||
if (reg[j] != A0) {
|
||||
reg[j] = MODNN(reg[j] + j);
|
||||
q ^= ALPHA_TO[reg[j]];
|
||||
}
|
||||
}
|
||||
if (q != 0)
|
||||
continue; /* Not a root */
|
||||
/* store root (index-form) and error location number */
|
||||
#if DEBUG>=2
|
||||
printf("count %d root %d loc %d\n",count,i,k);
|
||||
#endif
|
||||
root[count] = i;
|
||||
loc[count] = k;
|
||||
/* If we've already found max possible roots,
|
||||
* abort the search to save time
|
||||
*/
|
||||
if(++count == deg_lambda)
|
||||
break;
|
||||
}
|
||||
if (deg_lambda != count) {
|
||||
/*
|
||||
* deg(lambda) unequal to number of roots => uncorrectable
|
||||
* error detected
|
||||
*/
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/*
|
||||
* Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
|
||||
* x**NROOTS). in index form. Also find deg(omega).
|
||||
*/
|
||||
deg_omega = 0;
|
||||
for (i = 0; i < NROOTS;i++){
|
||||
tmp = 0;
|
||||
j = (deg_lambda < i) ? deg_lambda : i;
|
||||
for(;j >= 0; j--){
|
||||
if ((s[i - j] != A0) && (lambda[j] != A0))
|
||||
tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])];
|
||||
}
|
||||
if(tmp != 0)
|
||||
deg_omega = i;
|
||||
omega[i] = INDEX_OF[tmp];
|
||||
}
|
||||
omega[NROOTS] = A0;
|
||||
|
||||
/*
|
||||
* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
|
||||
* inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form
|
||||
*/
|
||||
for (j = count-1; j >=0; j--) {
|
||||
num1 = 0;
|
||||
for (i = deg_omega; i >= 0; i--) {
|
||||
if (omega[i] != A0)
|
||||
num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])];
|
||||
}
|
||||
num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)];
|
||||
den = 0;
|
||||
|
||||
/* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
|
||||
for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) {
|
||||
if(lambda[i+1] != A0)
|
||||
den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])];
|
||||
}
|
||||
if (den == 0) {
|
||||
#if DEBUG >= 1
|
||||
printf("\n ERROR: denominator = 0\n");
|
||||
#endif
|
||||
count = -1;
|
||||
goto finish;
|
||||
}
|
||||
/* Apply error to data */
|
||||
if (num1 != 0) {
|
||||
data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])];
|
||||
}
|
||||
}
|
||||
finish:
|
||||
if(eras_pos != NULL){
|
||||
for(i=0;i<count;i++)
|
||||
eras_pos[i] = loc[i];
|
||||
}
|
||||
return count;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* Reed-Solomon encoder
|
||||
* Copyright 2002, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU General Public License (GPL)
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#ifdef FIXED
|
||||
#include "fixed.h"
|
||||
#elif defined(BIGSYM)
|
||||
#include "int.h"
|
||||
#else
|
||||
#include "char.h"
|
||||
#endif
|
||||
|
||||
void ENCODE_RS(
|
||||
#ifndef FIXED
|
||||
void *p,
|
||||
#endif
|
||||
DTYPE *data, DTYPE *bb){
|
||||
#ifndef FIXED
|
||||
struct rs *rs = (struct rs *)p;
|
||||
#endif
|
||||
int i, j;
|
||||
DTYPE feedback;
|
||||
|
||||
memset(bb,0,NROOTS*sizeof(DTYPE));
|
||||
|
||||
for(i=0;i<NN-NROOTS;i++){
|
||||
feedback = INDEX_OF[data[i] ^ bb[0]];
|
||||
if(feedback != A0){ /* feedback term is non-zero */
|
||||
#ifdef UNNORMALIZED
|
||||
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
||||
* always be for the polynomials constructed by init_rs()
|
||||
*/
|
||||
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
|
||||
#endif
|
||||
for(j=1;j<NROOTS;j++)
|
||||
bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
|
||||
}
|
||||
/* Shift */
|
||||
memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1));
|
||||
if(feedback != A0)
|
||||
bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
|
||||
else
|
||||
bb[NROOTS-1] = 0;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue