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:
Bill Somerville 2015-11-18 01:28:12 +00:00
parent 1be194efdd
commit 1a23757b26
148 changed files with 10084 additions and 1574 deletions

View File

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

View File

@ -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
@ -1003,7 +1021,9 @@ void Configuration::impl::initialize_models ()
ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name()));
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_->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 ();

View File

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

View File

@ -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 &quot;CQ nnn ...&quot;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;User-selectable parameters for JT65 decoding.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Maximum number of erasure patterns for stochastic soft-decision Reed Solomon decoder is 10^(n/2).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Test codewords corresponding to messages of the form &amp;quot;MyCall DxCall Dxgrid&amp;quot;, &amp;quot;MyCall DxCall rpt&amp;quot;. &amp;quot;MyCall DxCall RRR&amp;quot;. and &amp;quot;MyCall DxCall 73&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Test codewords corresponding to messages of the form &amp;quot;CQ Call Grid&amp;quot; and &amp;quot;MyCall Call Grid&amp;quot; for all Call/Grid combinations selected from the list of known calls.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Test codewords corresponding to messages of the form &amp;quot;Call DxCall DxGrid OOO&amp;quot; for all Call/Grid combinations selected from the list of known calls.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Test codewords corresponding to messages of the form &amp;quot;Call1 Call2 Grid2&amp;quot;for all Call/Grid combinations selected from the list of known calls.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select Call/Grid combinations from list of known calls only if marked as active on EME.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Higher levels will increase the probability of decoding, but will also increase probability of a false decode.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>

View File

@ -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);
} 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)
{
value = value * 26 + text[index - 1].toLatin1 () - (lowercase_ ? 'a' : 'A');
};
for (int index = text.size (); index > 0; --index) {
value = value * 26 + text[index - 1].toLatin1 () - (lowercase_ ? 'a' : 'A');
}
return value;
}
*/

View File

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

View File

@ -8,14 +8,16 @@
namespace
{
char const * const mode_names[] =
{
"",
"JT65",
"JT9",
"JT4",
"WSPR",
"Echo",
};
{
"",
"JT65",
"JT9",
"JT4",
"WSPR",
"Echo",
"ISCAT",
"JTMSK"
};
}
Modes::Modes (QObject * parent)

View File

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

View File

@ -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,8 +160,9 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
case Active:
{
unsigned isym (m_tuning ? 0 : m_ic / (4.0 * m_nsps)); // Actual fsample=48000
if (isym >= m_symbolsLength && icw[0] > 0) { // start CW condition
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;
unsigned const ic0 = m_symbolsLength * 4 * m_nsps;
@ -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; //???

View File

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

View File

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

View File

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

View File

@ -23,8 +23,8 @@ CAboutDlg::CAboutDlg(QWidget *parent) :
"Amateur Radio communication. <br><br>"
"&copy; 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>");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
painter2D.fillRect(tmp,Qt::black);
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();}

View File

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

105
fastgraph.cpp Normal file
View File

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

47
fastgraph.h Normal file
View File

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

254
fastgraph.ui Normal file
View File

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

235
fastplot.cpp Normal file
View File

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

80
fastplot.h Normal file
View File

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

View File

@ -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()
{

39
lib/CQnnnCAT.txt Normal file
View File

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

395
lib/Fast_Modes.txt Normal file
View File

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

123
lib/JTMSKcode.f90 Normal file
View File

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

131
lib/JTMSKsim.f90 Normal file
View File

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

54
lib/Makefile Normal file
View File

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

76
lib/Makefile.jt65 Normal file
View File

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

63
lib/Makefile.jt65.win Normal file
View File

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

67
lib/Makefile.msk Normal file
View File

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

69
lib/Makefile.mskWin Normal file
View File

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

View File

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

21
lib/ana932.f90 Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,62 +1,66 @@
subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
! Parameters
! nadd number of spectra already summed
! mrsym most reliable symbol value
! mr2sym second most likely symbol value
! mrprob probability that mrsym was the transmitted value
! mr2prob probability that mr2sym was the transmitted value
implicit real*8 (a-h,o-z)
real*4 s3(64,63),afac1
real*8 fs(64)
integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63)
if(nadd.eq.-999) return
afac=afac1 * float(nadd)**0.64
scale=255.999
! Compute average spectral value
ave=sum(s3)/(64.*63.)
i1=1 !Silence warning
i2=1
! Compute probabilities for most reliable symbol values
do j=1,63
s1=-1.e30
fsum=0.
do i=1,64
x=min(afac*s3(i,j)/ave,50.d0)
fs(i)=exp(x)
fsum=fsum+fs(i)
if(s3(i,j).gt.s1) then
s1=s3(i,j)
i1=i !Most reliable
endif
enddo
s2=-1.e30
do i=1,64
if(i.ne.i1 .and. s3(i,j).gt.s2) then
s2=s3(i,j)
i2=i !Second most reliable
endif
enddo
p1=fs(i1)/fsum !Normalized probabilities
p2=fs(i2)/fsum
mrsym(j)=i1-1
mr2sym(j)=i2-1
mrprob(j)=scale*p1
mr2prob(j)=scale*p2
enddo
nlow=0
do j=1,63
if(mrprob(j).le.5) nlow=nlow+1
enddo
ntest=sum(mrprob)/63.0
return
end subroutine demod64a
subroutine demod64a(s3,nadd,afac1,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow)
! Demodulate the 64-bin spectra for each of 63 symbols in a frame.
! Parameters
! nadd number of spectra already summed
! mrsym most reliable symbol value
! mr2sym second most likely symbol value
! mrprob probability that mrsym was the transmitted value
! mr2prob probability that mr2sym was the transmitted value
implicit real*8 (a-h,o-z)
real*4 s3(64,63),afac1
real*8 fs(64)
integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63)
if(nadd.eq.-999) return
afac=afac1 * float(nadd)**0.64
scale=255.999
! Compute average spectral value
ave=sum(s3)/(64.*63.)
i1=1 !Silence warning
i2=1
! Compute probabilities for most reliable symbol values
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)
i1=i !Most reliable
endif
enddo
s2=-1.e30
do i=1,64
if(i.ne.i1 .and. s3(i,j).gt.s2) then
s2=s3(i,j)
i2=i !Second most reliable
endif
enddo
! 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
mr2prob(j)=scale*p2
enddo
nlow=0
do j=1,63
if(mrprob(j).le.5) nlow=nlow+1
enddo
ntest=sum(mrprob)
return
end subroutine demod64a

View File

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

View File

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

View File

@ -9,14 +9,14 @@ subroutine fano232(symbol,nbits,mettab,ndelta,maxcycles,dat, &
parameter (MAXBYTES=(MAXBITS+7)/8)
integer*1 symbol(0:2*MAXBITS-1) !Soft symbols (as unsigned i*1)
integer*1 dat(MAXBYTES) !Decoded user data, 8 bits per byte
integer mettab(-128:127,0:1) !Metric table
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))

191
lib/fast9.f90 Normal file
View File

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

79
lib/fast_decode.f90 Normal file
View File

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

View File

@ -17,7 +17,7 @@ real function fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
nout=ndiv*npts/nsps
dtstep=1.0/(ndiv*baud) !Time per output step
if(a(1).ne.a1 .or. a(2).ne.a2 .or. a(3).ne.a3) then
if(a(1).ne.a1 .or. a(2).ne.a2 .or. a(3).ne.a3) then
a1=a(1)
a2=a(2)
a3=a(3)
@ -32,37 +32,35 @@ real function fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax)
if(mod(i,100).eq.1) then
p2=1.5*x*x - 0.5
dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample)
wstep=cmplx(cos(dphi),sin(dphi))
wstep=cmplx(cos(dphi),sin(dphi))
endif
w=w*wstep
csx(i)=csx(i-1) + w*cx(i)
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

66
lib/fixwav.f90 Normal file
View File

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

View File

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

30
lib/foldspec9f.f90 Normal file
View File

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

55
lib/geniscat.f90 Normal file
View File

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

100
lib/genmsk.f90 Normal file
View File

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

View File

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

10
lib/hashing.f90 Normal file
View File

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

59
lib/hspec.f90 Normal file
View File

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

View File

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

204
lib/iscat.f90 Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -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
! endif
nfa=nf1
nfb=nf2
! nfa=max(200,nfqso-ntol)
! nfb=min(4000,nfqso+ntol)
df=12000.0/NFFT !df = 12000.0/16384 = 0.732 Hz
ftol=16.0 !Frequency tolerance (Hz)
mode65=2**nsubmode
done=.false.
freq0=-999.
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)
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))
thresh0=1.5
! 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
do i=ia,ib !Search over freq range
freq=i*df
if(savg(i).lt.thresh0 .or. done(i)) cycle
df=12000.0/NFFT !df = 12000.0/8192 = 1.465 Hz
mode65=2**nsubmode
nflip=1 !### temporary ###
nqd=0
decoded0=""
call timer('ccf65 ',0)
call ccf65(ss(1,i),nhsym,savg(i),sync1,dt,flipk,syncshort,snr2,dt2)
call timer('ccf65 ',1)
do icand=1,ncand
freq=ca(icand)%freq
dtx=ca(icand)%dt
sync1=ca(icand)%sync
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
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,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
nflip=nint(flipk)
call timer('decod65a',0)
call decode65a(dd,npts,newdat,nqd,freq,nflip,mode65,sync2,a,dt, &
nbmkv,nhist,decoded)
call timer('decod65a',1)
ftest=abs(freq+a(1)-freq0)
if(ftest.lt.ftol) cycle
if(decoded.ne.' ') then
ndecoded=1
nfreq=nint(freq+a(1))
ndrift=nint(2.0*a(2))
s2db=10.0*log10(sync2) - 32 !### empirical (was 40) ###
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
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) - 35 !### empirical ###
nsnr=nint(s2db)
if(nsnr.lt.-30) nsnr=-30
if(nsnr.gt.-1) nsnr=-1
! Serialize writes - see also decjt9.f90
!$omp critical(decode_results)
write(*,1010) nutc,nsnr,dt,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
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.
!$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,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)
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

131
lib/jt65sim.f90 Normal file
View File

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

View File

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

113
lib/jtmsk.f90 Normal file
View File

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

View File

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

78
lib/mskdt.f90 Normal file
View File

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

View File

@ -10,8 +10,8 @@ subroutine pctile(x,npts,npct,xpct)
endif
if(npts.gt.NMAX) stop
tmp(1:npts)=x
call sort(npts,tmp)
tmp(1:npts)=x
call shell(npts,tmp)
j=nint(npts*0.01*npct)
if(j.lt.1) j=1
if(j.gt.npts) j=npts

View File

@ -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 ', &

1
lib/prcom.f90 Normal file
View File

@ -0,0 +1 @@
common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2)

75
lib/rectify_msk.f90 Normal file
View File

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

121
lib/sfrsd.f90 Normal file
View File

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

24
lib/sfrsd/Makefile Normal file
View File

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

24
lib/sfrsd/Makefile.win32 Normal file
View File

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

56
lib/sfrsd/char.h Normal file
View File

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

268
lib/sfrsd/decode_rs.c Normal file
View File

@ -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(&reg[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;
}

47
lib/sfrsd/encode_rs.c Normal file
View File

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

38
lib/sfrsd/fixed.h Normal file
View File

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

121
lib/sfrsd/init_rs.c Normal file
View File

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

54
lib/sfrsd/int.h Normal file
View File

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

BIN
lib/sfrsd/kvasd.dat Normal file

Binary file not shown.

BIN
lib/sfrsd/kvasd7.dat Normal file

Binary file not shown.

BIN
lib/sfrsd/kvasd_bmfail.dat Normal file

Binary file not shown.

BIN
lib/sfrsd/kvasd_sample.dat Normal file

Binary file not shown.

16
lib/sfrsd/rs.h Normal file
View File

@ -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[];

130
lib/sfrsd/rstest.c Normal file
View File

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

344
lib/sfrsd/sfrsd.c Normal file
View File

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

53
lib/sfrsd2/Makefile Normal file
View File

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

30
lib/sfrsd2/Makefile.sfrsd Normal file
View File

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

View File

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

268
lib/sfrsd2/decode_rs.c Normal file
View File

@ -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(&reg[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;
}

47
lib/sfrsd2/encode_rs.c Normal file
View File

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