Merge branch 'feat-a7-UR' into develop

This commit is contained in:
Steven Franke 2022-04-25 07:23:06 -05:00
commit 062f3a8037
27 changed files with 1995 additions and 598 deletions

View File

@ -71,7 +71,7 @@ message (STATUS "******************************************************")
include (set_build_type) include (set_build_type)
# RC 0 or omitted is a development build, GA is a General Availability release build # RC 0 or omitted is a development build, GA is a General Availability release build
set_build_type (RC 1) set_build_type (RC 0)
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}") set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
# #
@ -126,7 +126,8 @@ option (WSJT_GENERATE_DOCS "Generate documentation files." ON)
option (WSJT_RIG_NONE_CAN_SPLIT "Allow split operation with \"None\" as rig.") option (WSJT_RIG_NONE_CAN_SPLIT "Allow split operation with \"None\" as rig.")
option (WSJT_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.") option (WSJT_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.")
option (WSJT_BUILD_UTILS "Build simulators and code demonstrators." ON) option (WSJT_BUILD_UTILS "Build simulators and code demonstrators." ON)
CMAKE_DEPENDENT_OPTION (WSJT_QDEBUG_IN_RELEASE "Leave Qt debugging statements in Release configuration." OFF
"NOT is_debug_build" OFF)
CMAKE_DEPENDENT_OPTION (WSJT_ENABLE_EXPERIMENTAL_FEATURES "Enable features not fully ready for public releases." ON CMAKE_DEPENDENT_OPTION (WSJT_ENABLE_EXPERIMENTAL_FEATURES "Enable features not fully ready for public releases." ON
is_debug_build OFF) is_debug_build OFF)
CMAKE_DEPENDENT_OPTION (WSJT_CREATE_WINMAIN CMAKE_DEPENDENT_OPTION (WSJT_CREATE_WINMAIN
@ -336,6 +337,7 @@ set (wsjt_FSRCS
lib/timer_module.f90 lib/timer_module.f90
lib/wavhdr.f90 lib/wavhdr.f90
lib/qra/q65/q65_encoding_modules.f90 lib/qra/q65/q65_encoding_modules.f90
lib/ft8/ft8_a7.f90
# remaining non-module sources # remaining non-module sources
lib/addit.f90 lib/addit.f90
@ -461,7 +463,6 @@ set (wsjt_FSRCS
lib/inter_wspr.f90 lib/inter_wspr.f90
lib/jplsubs.f lib/jplsubs.f
lib/jt9fano.f90 lib/jt9fano.f90
lib/jtmsg.f90
lib/libration.f90 lib/libration.f90
lib/lorentzian.f90 lib/lorentzian.f90
lib/fst4/lorentzian_fading.f90 lib/fst4/lorentzian_fading.f90
@ -1448,7 +1449,7 @@ set_target_properties (wsjtx PROPERTIES
) )
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS}) target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
if (APPLE) if ((NOT ${OPENMP_FOUND}) OR APPLE)
target_link_libraries (wsjtx wsjt_fort) target_link_libraries (wsjtx wsjt_fort)
else () else ()
target_link_libraries (wsjtx wsjt_fort_omp) target_link_libraries (wsjtx wsjt_fort_omp)

View File

@ -593,6 +593,7 @@ private:
bool highlight_by_mode_; bool highlight_by_mode_;
bool highlight_only_fields_; bool highlight_only_fields_;
bool include_WAE_entities_; bool include_WAE_entities_;
bool highlight_73_;
int LotW_days_since_upload_; int LotW_days_since_upload_;
TransceiverFactory::ParameterPack rig_params_; TransceiverFactory::ParameterPack rig_params_;
@ -670,6 +671,10 @@ private:
bool bLowSidelobes_; bool bLowSidelobes_;
bool pwrBandTxMemory_; bool pwrBandTxMemory_;
bool pwrBandTuneMemory_; bool pwrBandTuneMemory_;
bool highlight_DXcall_;
bool clear_DXcall_;
bool highlight_DXgrid_;
bool clear_DXgrid_;
QAudioDeviceInfo audio_input_device_; QAudioDeviceInfo audio_input_device_;
QAudioDeviceInfo next_audio_input_device_; QAudioDeviceInfo next_audio_input_device_;
@ -787,6 +792,11 @@ DecodeHighlightingModel const& Configuration::decode_highlighting () const {retu
bool Configuration::highlight_by_mode () const {return m_->highlight_by_mode_;} bool Configuration::highlight_by_mode () const {return m_->highlight_by_mode_;}
bool Configuration::highlight_only_fields () const {return m_->highlight_only_fields_;} bool Configuration::highlight_only_fields () const {return m_->highlight_only_fields_;}
bool Configuration::include_WAE_entities () const {return m_->include_WAE_entities_;} bool Configuration::include_WAE_entities () const {return m_->include_WAE_entities_;}
bool Configuration::highlight_73 () const {return m_->highlight_73_;}
bool Configuration::highlight_DXcall () const {return m_->highlight_DXcall_;}
bool Configuration::clear_DXcall () const {return m_->clear_DXcall_;}
bool Configuration::highlight_DXgrid () const {return m_->highlight_DXgrid_;}
bool Configuration::clear_DXgrid () const {return m_->clear_DXgrid_;}
void Configuration::set_calibration (CalibrationParams params) void Configuration::set_calibration (CalibrationParams params)
{ {
@ -920,6 +930,30 @@ void Configuration::set_location (QString const& grid_descriptor)
m_->dynamic_grid_ = grid_descriptor.trimmed (); m_->dynamic_grid_ = grid_descriptor.trimmed ();
} }
void Configuration::setSpecial_Hound()
{
m_->bSpecialOp_=true;
m_->ui_->gbSpecialOpActivity->setChecked(m_->bSpecialOp_);
m_->ui_->rbHound->setChecked(true);
m_->SelectedActivity_ = static_cast<int> (SpecialOperatingActivity::HOUND);
m_->write_settings();
}
void Configuration::setSpecial_Fox()
{
m_->bSpecialOp_=true;
m_->ui_->gbSpecialOpActivity->setChecked(m_->bSpecialOp_);
m_->ui_->rbFox->setChecked(true);
m_->SelectedActivity_ = static_cast<int> (SpecialOperatingActivity::FOX);
m_->write_settings();
}
void Configuration::setSpecial_None()
{
m_->bSpecialOp_=false;
m_->ui_->gbSpecialOpActivity->setChecked(m_->bSpecialOp_);
m_->write_settings();
}
namespace namespace
{ {
#if defined (Q_OS_MAC) #if defined (Q_OS_MAC)
@ -984,6 +1018,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
, highlight_by_mode_ {false} , highlight_by_mode_ {false}
, highlight_only_fields_ {false} , highlight_only_fields_ {false}
, include_WAE_entities_ {false} , include_WAE_entities_ {false}
, highlight_73_ {false}
, LotW_days_since_upload_ {0} , LotW_days_since_upload_ {0}
, last_port_type_ {TransceiverFactory::Capabilities::none} , last_port_type_ {TransceiverFactory::Capabilities::none}
, rig_is_dummy_ {false} , rig_is_dummy_ {false}
@ -1397,7 +1432,12 @@ void Configuration::impl::initialize_models ()
ui_->highlight_by_mode_check_box->setChecked (highlight_by_mode_); ui_->highlight_by_mode_check_box->setChecked (highlight_by_mode_);
ui_->only_fields_check_box->setChecked (highlight_only_fields_); ui_->only_fields_check_box->setChecked (highlight_only_fields_);
ui_->include_WAE_check_box->setChecked (include_WAE_entities_); ui_->include_WAE_check_box->setChecked (include_WAE_entities_);
ui_->highlight_73_check_box->setChecked (highlight_73_);
ui_->LotW_days_since_upload_spin_box->setValue (LotW_days_since_upload_); ui_->LotW_days_since_upload_spin_box->setValue (LotW_days_since_upload_);
ui_->cbHighlightDXcall->setChecked(highlight_DXcall_);
ui_->cbClearDXcall->setChecked(clear_DXcall_);
ui_->cbHighlightDXgrid->setChecked(highlight_DXgrid_);
ui_->cbClearDXgrid->setChecked(clear_DXgrid_);
set_rig_invariants (); set_rig_invariants ();
} }
@ -1492,6 +1532,7 @@ void Configuration::impl::read_settings ()
highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool (); highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool ();
highlight_only_fields_ = settings_->value("OnlyFieldsSought", false).toBool (); highlight_only_fields_ = settings_->value("OnlyFieldsSought", false).toBool ();
include_WAE_entities_ = settings_->value("IncludeWAEEntities", false).toBool (); include_WAE_entities_ = settings_->value("IncludeWAEEntities", false).toBool ();
highlight_73_ = settings_->value("Highlight73", false).toBool ();
LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt (); LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt ();
lotw_users_.set_age_constraint (LotW_days_since_upload_); lotw_users_.set_age_constraint (LotW_days_since_upload_);
@ -1554,6 +1595,10 @@ void Configuration::impl::read_settings ()
calibration_.slope_ppm = settings_->value ("CalibrationSlopePPM", 0.).toDouble (); calibration_.slope_ppm = settings_->value ("CalibrationSlopePPM", 0.).toDouble ();
pwrBandTxMemory_ = settings_->value("pwrBandTxMemory",false).toBool (); pwrBandTxMemory_ = settings_->value("pwrBandTxMemory",false).toBool ();
pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool (); pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool ();
highlight_DXcall_ = settings_->value("highlight_DXcall",false).toBool ();
clear_DXcall_ = settings_->value("clear_DXcall",false).toBool ();
highlight_DXgrid_ = settings_->value("highlight_DXgrid",false).toBool ();
clear_DXgrid_ = settings_->value("clear_DXgrid",false).toBool ();
} }
void Configuration::impl::find_audio_devices () void Configuration::impl::find_audio_devices ()
@ -1626,6 +1671,7 @@ void Configuration::impl::write_settings ()
settings_->setValue ("HighlightByMode", highlight_by_mode_); settings_->setValue ("HighlightByMode", highlight_by_mode_);
settings_->setValue ("OnlyFieldsSought", highlight_only_fields_); settings_->setValue ("OnlyFieldsSought", highlight_only_fields_);
settings_->setValue ("IncludeWAEEntities", include_WAE_entities_); settings_->setValue ("IncludeWAEEntities", include_WAE_entities_);
settings_->setValue ("Highlight73", highlight_73_);
settings_->setValue ("LotWDaysSinceLastUpload", LotW_days_since_upload_); settings_->setValue ("LotWDaysSinceLastUpload", LotW_days_since_upload_);
settings_->setValue ("toRTTY", log_as_RTTY_); settings_->setValue ("toRTTY", log_as_RTTY_);
settings_->setValue ("dBtoComments", report_in_comments_); settings_->setValue ("dBtoComments", report_in_comments_);
@ -1685,6 +1731,10 @@ void Configuration::impl::write_settings ()
settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_); settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
settings_->setValue ("Region", QVariant::fromValue (region_)); settings_->setValue ("Region", QVariant::fromValue (region_));
settings_->setValue ("AutoGrid", use_dynamic_grid_); settings_->setValue ("AutoGrid", use_dynamic_grid_);
settings_->setValue ("highlight_DXcall", highlight_DXcall_);
settings_->setValue ("clear_DXcall", clear_DXcall_);
settings_->setValue ("highlight_DXgrid", highlight_DXgrid_);
settings_->setValue ("clear_DXgrid", clear_DXgrid_);
settings_->sync (); settings_->sync ();
} }
@ -2163,6 +2213,7 @@ void Configuration::impl::accept ()
highlight_by_mode_ = ui_->highlight_by_mode_check_box->isChecked (); highlight_by_mode_ = ui_->highlight_by_mode_check_box->isChecked ();
highlight_only_fields_ = ui_->only_fields_check_box->isChecked (); highlight_only_fields_ = ui_->only_fields_check_box->isChecked ();
include_WAE_entities_ = ui_->include_WAE_check_box->isChecked (); include_WAE_entities_ = ui_->include_WAE_check_box->isChecked ();
highlight_73_ = ui_->highlight_73_check_box->isChecked ();
LotW_days_since_upload_ = ui_->LotW_days_since_upload_spin_box->value (); LotW_days_since_upload_ = ui_->LotW_days_since_upload_spin_box->value ();
lotw_users_.set_age_constraint (LotW_days_since_upload_); lotw_users_.set_age_constraint (LotW_days_since_upload_);
@ -2172,6 +2223,10 @@ void Configuration::impl::accept ()
dynamic_grid_.clear (); dynamic_grid_.clear ();
} }
use_dynamic_grid_ = ui_->use_dynamic_grid->isChecked(); use_dynamic_grid_ = ui_->use_dynamic_grid->isChecked();
highlight_DXcall_ = ui_->cbHighlightDXcall->isChecked();
clear_DXcall_ = ui_->cbClearDXcall->isChecked();
highlight_DXgrid_ = ui_->cbHighlightDXgrid->isChecked();
clear_DXgrid_ = ui_->cbClearDXgrid->isChecked();
write_settings (); // make visible to all write_settings (); // make visible to all
} }

View File

@ -181,6 +181,14 @@ public:
bool highlight_by_mode () const; bool highlight_by_mode () const;
bool highlight_only_fields () const; bool highlight_only_fields () const;
bool include_WAE_entities () const; bool include_WAE_entities () const;
bool highlight_73 () const;
void setSpecial_Hound();
void setSpecial_Fox();
void setSpecial_None();
bool highlight_DXcall () const;
bool clear_DXcall () const;
bool highlight_DXgrid () const;
bool clear_DXgrid () const;
enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, WW_DIGI, FOX, HOUND}; enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, WW_DIGI, FOX, HOUND};
SpecialOperatingActivity special_op_id () const; SpecialOperatingActivity special_op_id () const;

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>554</width> <width>554</width>
<height>560</height> <height>599</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -181,29 +181,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="DXCC_check_box">
<property name="toolTip">
<string>Show if decoded stations are new DXCC entities or worked before.</string>
</property>
<property name="text">
<string>Show &amp;DXCC, grid, and worked-before status</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="decodes_from_top_check_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to have decodes for a new period start at the top of the Band Activity window and not scroll off the top when the window is full.&lt;/p&gt;&lt;p&gt;This is to aid selecting decodes to double-click while decoding is still in progress. Use the Band Activity vertical scroll bar to reveal decodes past the bottom of the window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Start new period decodes at top</string>
</property>
</widget>
</item>
<item row="4" column="1"> <item row="4" column="1">
<widget class="QCheckBox" name="ppfx_check_box"> <widget class="QCheckBox" name="ppfx_check_box">
<property name="text"> <property name="text">
@ -265,13 +242,10 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="0"> <item row="5" column="0">
<widget class="QCheckBox" name="insert_blank_check_box"> <widget class="QCheckBox" name="cbHighlightDXcall">
<property name="toolTip">
<string>Include a separator line between periods in the band activity window.</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Blank line between decoding periods</string> <string>Highlight DX Call in message</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -285,6 +259,60 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="DXCC_check_box">
<property name="toolTip">
<string>Show if decoded stations are new DXCC entities or worked before.</string>
</property>
<property name="text">
<string>Show &amp;DXCC, grid, and worked-before status</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="decodes_from_top_check_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to have decodes for a new period start at the top of the Band Activity window and not scroll off the top when the window is full.&lt;/p&gt;&lt;p&gt;This is to aid selecting decodes to double-click while decoding is still in progress. Use the Band Activity vertical scroll bar to reveal decodes past the bottom of the window.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Start new period decodes at top</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="cbClearDXgrid">
<property name="text">
<string>Clear DX Grid after QSO</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="insert_blank_check_box">
<property name="toolTip">
<string>Include a separator line between periods in the band activity window.</string>
</property>
<property name="text">
<string>&amp;Blank line between decoding periods</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="cbHighlightDXgrid">
<property name="text">
<string>Highlight DX Grid in message</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="cbClearDXcall">
<property name="text">
<string>Clear DX Call after QSO</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -2302,6 +2330,23 @@ Right click for insert and delete options.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="include_WAE_check_box">
<property name="text">
<string>Include extra WAE entities</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="only_fields_check_box">
<property name="toolTip">
<string>Check to for grid highlighting to only apply to unworked grid fields</string>
</property>
<property name="text">
<string>Only grid Fields sought</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="DecodeHighlightingListView" name="highlighting_list_view"> <widget class="DecodeHighlightingListView" name="highlighting_list_view">
<property name="sizePolicy"> <property name="sizePolicy">
@ -2349,20 +2394,10 @@ Right click for insert and delete options.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QCheckBox" name="include_WAE_check_box"> <widget class="QCheckBox" name="highlight_73_check_box">
<property name="text"> <property name="text">
<string>Include extra WAE entities</string> <string>Highlight also messages with 73 or RR73</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="only_fields_check_box">
<property name="toolTip">
<string>Check to for grid highlighting to only apply to unworked grid fields</string>
</property>
<property name="text">
<string>Only grid Fields sought</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -3233,13 +3268,13 @@ Right click for insert and delete options.</string>
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="special_op_activity_button_group"/>
<buttongroup name="TX_audio_source_button_group"/> <buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/> <buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="TX_mode_button_group"/> <buttongroup name="TX_mode_button_group"/>
<buttongroup name="special_op_activity_button_group"/> <buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/> <buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="split_mode_button_group"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -54,7 +54,7 @@ namespace Radio
value *= std::pow (10., scale); value *= std::pow (10., scale);
if (ok) if (ok)
{ {
if (value < 0. || value > std::numeric_limits<Frequency>::max ()) if (value < 0. || value > static_cast<double>(std::numeric_limits<Frequency>::max ()))
{ {
value = 0.; value = 0.;
*ok = false; *ok = false;
@ -91,8 +91,8 @@ namespace Radio
value *= std::pow (10., scale); value *= std::pow (10., scale);
if (ok) if (ok)
{ {
if (value < -std::numeric_limits<Frequency>::max () if (value < static_cast<double>(std::numeric_limits<Frequency>::min ())
|| value > std::numeric_limits<Frequency>::max ()) || value > static_cast<double>(std::numeric_limits<Frequency>::max ()))
{ {
value = 0.; value = 0.;
*ok = false; *ok = false;

View File

@ -2445,7 +2445,7 @@ Corsica: 15: 28: EU: 42.00: -9.00: -1.0: TK:
Central African Republic: 36: 47: AF: 6.75: -20.33: -1.0: TL: Central African Republic: 36: 47: AF: 6.75: -20.33: -1.0: TL:
TL; TL;
Republic of the Congo: 36: 52: AF: -1.02: -15.37: -1.0: TN: Republic of the Congo: 36: 52: AF: -1.02: -15.37: -1.0: TN:
TN; TN0,TN1,TN2,TN3,TN4,TN5,TN6,TN7,TN8,TN9;
Gabon: 36: 52: AF: -0.37: -11.73: -1.0: TR: Gabon: 36: 52: AF: -0.37: -11.73: -1.0: TR:
TR; TR;
Chad: 36: 47: AF: 15.80: -18.17: -1.0: TT: Chad: 36: 47: AF: 15.80: -18.17: -1.0: TT:
@ -3376,7 +3376,7 @@ Indonesia: 28: 51: OC: -7.30: -109.88: -7.0: YB:
8D8[54],8E8[54],8F8[54],8G8[54],8H8[54],8I8[54],YB8[54],YC8[54],YD8[54],YE8[54],YF8[54],YG8[54], 8D8[54],8E8[54],8F8[54],8G8[54],8H8[54],8I8[54],YB8[54],YC8[54],YD8[54],YE8[54],YF8[54],YG8[54],
YH8[54]; YH8[54];
Iraq: 21: 39: AS: 33.92: -42.78: -3.0: YI: Iraq: 21: 39: AS: 33.92: -42.78: -3.0: YI:
HN,YI,=K4CY/M,=YI1IRQ/ND; HN0,HN1,HN2,HN3,HN4,HN5,HN6,HN7,HN8,HN9,YI,=K4CY/M,=YI1IRQ/ND;
Vanuatu: 32: 56: OC: -17.67: -168.38: -11.0: YJ: Vanuatu: 32: 56: OC: -17.67: -168.38: -11.0: YJ:
YJ; YJ;
Syria: 20: 39: AS: 35.38: -38.20: -2.0: YK: Syria: 20: 39: AS: 35.38: -38.20: -2.0: YK:

View File

@ -144,7 +144,7 @@ station's log and not the supposed QSO partner's. To avoid Not-in-Log
(NIL) penalties for yourself and others, we recommend the following (NIL) penalties for yourself and others, we recommend the following
guidelines for contest logging with FT4, FT8, and MSK144: guidelines for contest logging with FT4, FT8, and MSK144:
- Activate and learn to use the alternate F1-F6 bindings selectable - Activate and learn to use the *Alternate F1-F6 bindings* selectable
on the *Settings | General* tab. on the *Settings | General* tab.
- Always log a QSO when you have received RRR, RR73, or 73 from a - Always log a QSO when you have received RRR, RR73, or 73 from a
@ -153,8 +153,9 @@ guidelines for contest logging with FT4, FT8, and MSK144:
- Log a QSO when you send RR73 or 73 if you are reasonably confident - Log a QSO when you send RR73 or 73 if you are reasonably confident
it will be copied. But be sure to watch for any indication that it it will be copied. But be sure to watch for any indication that it
was not copied, and then take appropriate action. For example, if was not copied, and then take appropriate action. For example, if
you receive the Tx3 message (R plus contest exchange) again, hit F4 you receive the Tx3 message (R plus contest exchange) again, and if
to re-send your RR73. you have activated the *Alternate F1-F6 bindings*, hit *F4* to
re-send your RR73.
[[COMP-CALL]] [[COMP-CALL]]
=== Nonstandard Callsigns === Nonstandard Callsigns

View File

@ -830,7 +830,9 @@ subroutine split77(msg,nwords,nw,w)
iz=j !Message length iz=j !Message length
nwords=k !Number of words in msg nwords=k !Number of words in msg
if(nwords.le.0) go to 900 if(nwords.le.0) go to 900
nw(k)=len(trim(w(k))) do i=1,nwords
nw(i)=len(trim(w(i)))
enddo
msg(iz+1:)=' ' msg(iz+1:)=' '
if(nwords.lt.3) go to 900 if(nwords.lt.3) go to 900
call chkcall(w(3),bcall_1,ok1) call chkcall(w(3),bcall_1,ok1)
@ -839,7 +841,7 @@ subroutine split77(msg,nwords,nw,w)
w(2:12)=w(3:13) !Move all remaining words down by one w(2:12)=w(3:13) !Move all remaining words down by one
nwords=nwords-1 nwords=nwords-1
endif endif
900 return 900 return
end subroutine split77 end subroutine split77

View File

@ -34,7 +34,9 @@ subroutine chkcall(w,bc,cok)
! One of first two characters (c1 or c2) must be a letter ! One of first two characters (c1 or c2) must be a letter
if((.not.isletter(bc(1:1))) .and. (.not.isletter(bc(2:2)))) go to 100 if((.not.isletter(bc(1:1))) .and. (.not.isletter(bc(2:2)))) go to 100
if(bc(1:1).eq.'Q') go to 100 !Calls don't start with Q ! Real calls don't start with Q, but we'll allow the placeholder
! callsign QU1RK to be considered a standard call:
if(bc(1:1).eq.'Q' .and. bc(1:5).ne.'QU1RK') go to 100
! Must have a digit in 2nd or 3rd position ! Must have a digit in 2nd or 3rd position
i1=0 i1=0

161
lib/ft8/chkdec.f90 Normal file
View File

@ -0,0 +1,161 @@
program chkdec
parameter(NMAX=100)
character*88 line
character*37 msg(NMAX),msg0,msg1
character*2 c2(NMAX)
character*1 c1(NMAX)
character*1 only
integer nsnr(NMAX,0:1),nf(NMAX,0:1)
real dt(NMAX,0:1)
logical found,eof
! These files are sorted by freq within each Rx sequence
open(10,file='all.wsjtx',status='old')
open(11,file='all.jtdx',status='old')
write(20,1030)
1030 format(' iseq B w j W W+ J E B w j W', &
' W+ J E'/80('-'))
nutc0=-1
nbt=0 !Both
nwt=0 !WSJT-X only
njt=0 !JTDX only
net=0 !Either
n7t=0 !a7
eof=.false.
do iseq=1,9999
j=0
msg=' '
nsnr=-99
nf=-99
dt=-99
c1=' '
c2=' '
do i=1,NMAX
read(10,'(a88)',end=8) line !Read from the WSJT-X file
if(line(25:30).ne.'Rx FT8') cycle !Ignore any line not an FT8 decode
read(line(8:13),*) nutc
if(nutc0.lt.0) nutc0=nutc !First time only
if(nutc.ne.nutc0) then
backspace(10)
go to 10 !Finished WSJT-X for this sequence
endif
j=j+1
if(j.eq.1) then
nf(j,0)=-1
j=j+1
endif
read(line,1001) nsnr(j,0),dt(j,0),nf(j,0),msg(j),c2(j)
1001 format(30x,i7,f5.1,i5,1x,a36,2x,a2)
! if(nutc.eq.180215 .and. c2(j).eq.'a7') print*,'aaa',j,nf(j,0),c2(j)
nutc0=nutc
enddo ! i
8 eof=.true.
10 jz=j
do i=1,NMAX
read(11,'(a88)',end=20) line !Read from the JTDX file
if(line(31:31).ne.'~') cycle !Ignore any line not an FT8 decode
read(line(10:15),*) nutc
if(nutc.ne.nutc0) then
backspace(11)
go to 20 !Finished JTDX for this sequence
endif
msg1=line(33:58)
read(line(25:29),*) nf1
found=.false.
do j=1,jz
if(msg(j).eq.msg1) then
read(line,1002) nsnr(j,1),dt(j,1),nf(j,1),c1(j)
1002 format(15x,i4,f5.1,i5,29x,a1)
found=.true.
exit
endif
i1=index(msg(j),'<')
if(i1.gt.0) then
i2=index(msg(j),'>')
msg0=msg(j)(1:i1-1)//msg(j)(i1+1:i2-1)//msg(j)(i2+1:)
if(msg0.eq.msg1) then
read(line,1002) nsnr(j,1),dt(j,1),nf(j,1),c1(j)
found=.true.
exit
endif
endif
enddo ! j
if(.not.found) then !Insert this one as a new message
do j=1,jz
if(nf1.ge.nf(j,0) .and. nf1.lt.nf(j+1,0)) then
jj=j+1
exit
endif
enddo
do j=jz+1,jj+1,-1
nsnr(j,0)=nsnr(j-1,0)
dt(j,0)=dt(j-1,0)
nf(j,0)=nf(j-1,0)
msg(j)=msg(j-1)
c1(j)=c1(j-1)
c2(j)=c2(j-1)
enddo ! j
read(line,1004) nsnr(jj,1),dt(jj,1),nf(jj,1),msg(jj),c1(jj)
1004 format(15x,i4,f5.1,i5,3x,a26,a1)
c2(jj)=' '
nsnr(jj,0)=-99
dt(jj,0)=-99.0
nf(jj,0)=-99
jz=jz+1
endif
enddo ! i
20 nb=0
nw=0
nj=0
ne=0
n7=0
do j=2,jz
write(line,1020) nutc0,j,nsnr(j,:),dt(j,:),nf(j,:),msg(j)(1:26), &
c2(j),c1(j)
1020 format(i6.6,i3,1x,2i4,1x,2f6.1,1x,2i5,1x,a26,1x,a2,1x,a1)
if(c2(j).eq.'a7') n7=n7+1
only=' '
if(line(12:14).eq.'-99') then
line(12:14)=' '
only='j'
nj=nj+1
! if(c2(j).eq.'a7') print*,'aaa ',trim(line)
endif
if(line(16:18).eq.'-99') then
line(16:18)=' '
only='w'
nw=nw+1
endif
if(line(12:14).ne.' ' .or. line(16:19).ne.' ') ne=ne+1
if(line(12:14).ne.' ' .and. line(16:19).ne.' ') nb=nb+1
if(line(21:25).eq.'-99.0') line(21:25)=' '
if(line(27:31).eq.'-99.0') line(27:31)=' '
if(line(35:37).eq.'-99') line(35:37)=' '
if(line(40:42).eq.'-99') line(40:42)=' '
! if(line(12:14).ne.' ') nw=nw+1
! if(line(16:18).ne.' ') nj=nj+1
write(*,'(a74,1x,a1)') line(1:74),only
enddo ! j
nbt=nbt+nb
nwt=nwt+nw
n7t=n7t+n7
njt=njt+nj
net=net+ne
nutc0=nutc
write(*,*)
write(20,1031) iseq,nb,nw,nj,nb+nw-n7,nb+nw,nb+nj,ne,nbt,nwt,njt, &
nbt+nwt-n7t,nbt+nwt,nbt+njt,net
1031 format(i5,2x,7i4,2x,7i6)
if(eof) exit
! if(iseq.eq.2) exit
enddo ! iseq
end program chkdec

378
lib/ft8/ft8_a7.f90 Normal file
View File

@ -0,0 +1,378 @@
module ft8_a7
parameter(MAXDEC=100)
! For the following three arrays
! First index i=decode number in this sequence
! Second index j=0 or 1 for even or odd sequence
! Third index k=0 or 1 for previous or current tally for this j
real dt0(MAXDEC,0:1,0:1) !dt0(i,j,k)
real f0(MAXDEC,0:1,0:1) !f0(i,j,k)
character*37 msg0(MAXDEC,0:1,0:1) !msg0(i,j,k)
integer itone_a7(79)
integer jseq !even=0, odd=1
integer ndec(0:1,0:1) !ndec(j,k)
data ndec/4*0/,jseq/0/
contains
subroutine ft8_a7_save(nutc,dt,f,msg)
use packjt77
character*37 msg,msg1
character*13 w(19)
character*4 g4
integer nw(19)
logical isgrid4
! Statement function:
isgrid4(g4)=(len_trim(g4).eq.4 .and. &
ichar(g4(1:1)).ge.ichar('A') .and. ichar(g4(1:1)).le.ichar('R') .and. &
ichar(g4(2:2)).ge.ichar('A') .and. ichar(g4(2:2)).le.ichar('R') .and. &
ichar(g4(3:3)).ge.ichar('0') .and. ichar(g4(3:3)).le.ichar('9') .and. &
ichar(g4(4:4)).ge.ichar('0') .and. ichar(g4(4:4)).le.ichar('9'))
if(index(msg,'/').ge.1 .or. index(msg,'<').ge.1) go to 999
call split77(msg,nwords,nw,w) !Parse msg into words
if(nwords.lt.1) go to 999
if(w(1)(1:3).eq.'CQ_') go to 999
j=mod(nutc/5,2) !j is 0 or 1 for odd/even sequence
jseq=j
! Add this decode to current table for this sequence
ndec(j,1)=ndec(j,1)+1 !Number of decodes in this sequence
i=ndec(j,1) !i is index of a new table entry
if(i.ge.MAXDEC-1) return !Prevent table overflow
dt0(i,j,1)=dt !Save dt in table
f0(i,j,1)=f !Save f in table
msg0(i,j,1)=trim(w(1))//' '//trim(w(2)) !Save "call_1 call_2"
if(w(1)(1:3).eq.'CQ ' .and. nw(2).le.2) then
msg0(i,j,1)='CQ '//trim(w(2))//' '//trim(w(3)) !Save "CQ DX Call_2"
endif
msg1=msg0(i,j,1) !Message without grid
nn=len(trim(msg1)) !Message length without grid
! Include grid as part of message
if(isgrid4(w(nwords))) msg0(i,j,1)=trim(msg0(i,j,1))//' '//trim(w(nwords))
! If a transmission at this frequency with message fragment "call_1 call_2"
! was decoded in the previous sequence, flag it as "DO NOT USE" because
! we have already decoded and subtracted that station's next transmission.
call split77(msg0(i,j,1),nwords,nw,w) !Parse msg into words
do i=1,ndec(j,0)
if(f0(i,j,0).le.-98.0) cycle
i2=index(msg0(i,j,0),' '//trim(w(2)))
if(abs(f-f0(i,j,0)).le.3.0 .and. i2.ge.3) then
f0(i,j,0)=-98.0 !Flag as "do not use" for a potential a7 decode
endif
enddo
999 return
end subroutine ft8_a7_save
subroutine ft8_a7d(dd0,newdat,call_1,call_2,grid4,xdt,f1,xbase,nharderrors,dmin, &
msg37,xsnr)
! Examine the raw data in dd0() for possible "a7" decodes.
use crc
use timer_module, only: timer
use packjt77
include 'ft8_params.f90'
parameter(NP2=2812)
character*37 msg37,msg,msgsent,msgbest
character*12 call_1,call_2
character*4 grid4
real a(5)
real s8(0:7,NN)
real s2(0:511)
real dmm(206)
real bmeta(174),bmetb(174),bmetc(174),bmetd(174)
real llra(174),llrb(174),llrc(174),llrd(174) !Soft symbols
real dd0(15*12000)
real ss(9)
real rcw(174)
integer*1 cw(174)
integer*1 msgbits(77)
integer*1 nxor(174),hdec(174)
integer itone(NN)
integer icos7(0:6),ip(1)
logical one(0:511,0:8)
integer graymap(0:7)
integer iloc(1)
complex cd0(0:3199)
complex ctwk(32)
complex csymb(32)
complex cs(0:7,NN)
logical std_1,std_2
logical first,newdat
data icos7/3,1,4,0,6,5,2/ !Sync array
data first/.true./
data graymap/0,1,3,2,5,6,4,7/
save one
if(first) then
one=.false.
do i=0,511
do j=0,8
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
first=.false.
endif
call stdcall(call_1,std_1)
if(call_1(1:3).eq.'CQ ') std_1=.true.
call stdcall(call_2,std_2)
fs2=12000.0/NDOWN
dt2=1.0/fs2
twopi=8.0*atan(1.0)
delfbest=0.
ibest=0
call timer('ft8_down',0)
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
call timer('ft8_down',1)
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
smax=0.0
do idt=i0-10,i0+10 !Search over +/- one quarter symbol
call sync8d(cd0,idt,ctwk,0,sync) !NB: ctwk not used here
if(sync.gt.smax) then
smax=sync
ibest=idt
endif
enddo
! Peak up in frequency
smax=0.0
do ifr=-5,5 !Search over +/- 2.5 Hz
delf=ifr*0.5
dphi=twopi*delf*dt2
phi=0.0
do i=1,32
ctwk(i)=cmplx(cos(phi),sin(phi))
phi=mod(phi+dphi,twopi)
enddo
call sync8d(cd0,ibest,ctwk,1,sync)
if( sync .gt. smax ) then
smax=sync
delfbest=delf
endif
enddo
a=0.0
a(1)=-delfbest
call twkfreq1(cd0,NP2,fs2,a,cd0)
f1=f1+delfbest !Improved estimate of DF
call timer('ft8_down',0)
call ft8_downsample(dd0,.false.,f1,cd0) !Mix f1 to baseband and downsample
call timer('ft8_down',1)
smax=0.0
do idt=-4,4 !Search over +/- one quarter symbol
call sync8d(cd0,ibest+idt,ctwk,0,sync)
ss(idt+5)=sync
enddo
smax=maxval(ss)
iloc=maxloc(ss)
ibest=iloc(1)-5+ibest
xdt=(ibest-1)*dt2 - 0.5
sync=smax
do k=1,NN
i1=ibest+(k-1)*32
csymb=cmplx(0.0,0.0)
if( i1.ge.0 .and. i1+31 .le. NP2-1 ) csymb=cd0(i1:i1+31)
call four2a(csymb,32,1,-1,1)
cs(0:7,k)=csymb(1:8)/1e3
s8(0:7,k)=abs(csymb(1:8))
enddo
! sync quality check
is1=0
is2=0
is3=0
do k=1,7
ip=maxloc(s8(:,k))
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
ip=maxloc(s8(:,k+36))
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
ip=maxloc(s8(:,k+72))
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
enddo
! hard sync sum - max is 21
nsync=is1+is2+is3
! if(nsync .le. 6) return ! bail out
do nsym=1,3
nt=2**(3*nsym)
do ihalf=1,2
do k=1,29,nsym
if(ihalf.eq.1) ks=k+7
if(ihalf.eq.2) ks=k+43
amax=-1.0
do i=0,nt-1
i1=i/64
i2=iand(i,63)/8
i3=iand(i,7)
if(nsym.eq.1) then
s2(i)=abs(cs(graymap(i3),ks))
elseif(nsym.eq.2) then
s2(i)=abs(cs(graymap(i2),ks)+cs(graymap(i3),ks+1))
elseif(nsym.eq.3) then
s2(i)=abs(cs(graymap(i1),ks)+cs(graymap(i2),ks+1)+cs(graymap(i3),ks+2))
else
print*,"Error - nsym must be 1, 2, or 3."
endif
enddo
i32=1+(k-1)*3+(ihalf-1)*87
if(nsym.eq.1) ibmax=2
if(nsym.eq.2) ibmax=5
if(nsym.eq.3) ibmax=8
do ib=0,ibmax
bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
if(i32+ib .gt.174) cycle
if(nsym.eq.1) then
bmeta(i32+ib)=bm
den=max(maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)), &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib)))
if(den.gt.0.0) then
cm=bm/den
else ! erase it
cm=0.0
endif
bmetd(i32+ib)=cm
elseif(nsym.eq.2) then
bmetb(i32+ib)=bm
elseif(nsym.eq.3) then
bmetc(i32+ib)=bm
endif
enddo
enddo
enddo
enddo
call normalizebmet(bmeta,174)
call normalizebmet(bmetb,174)
call normalizebmet(bmetc,174)
call normalizebmet(bmetd,174)
scalefac=2.83
llra=scalefac*bmeta
llrb=scalefac*bmetb
llrc=scalefac*bmetc
llrd=scalefac*bmetd
! apmag=maxval(abs(llra))*1.01
MAXMSG=206
pbest=0.
dmin=1.e30
nharderrors=-1
do imsg=1,MAXMSG
msg=trim(call_1)//' '//trim(call_2)
i=imsg
if(call_1(1:3).eq.'CQ ' .and. i.ne.5) msg='QU1RK '//trim(call_2)
if(.not.std_1) then
if(i.eq.1 .or. i.ge.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.2 .and. i.le.4) msg=trim(call_1)//' <'//trim(call_2)//'>'
else if(.not.std_2) then
if(i.le.4 .or. i.eq.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.7) msg=trim(call_1)//' <'//trim(call_2)//'>'
endif
j0=len(trim(msg))+2
if(i.eq.2) msg(j0:j0+2)='RRR'
if(i.eq.3) msg(j0:j0+3)='RR73'
if(i.eq.4) msg(j0:j0+1)='73'
if(i.eq.5) then
if(std_2) then
msg='CQ '//trim(call_2)
if(call_1(3:3).eq.'_') msg=trim(call_1)//' '//trim(call_2)
if(grid4.ne.'RR73') msg=trim(msg)//' '//grid4
endif
if(.not.std_2) msg='CQ '//trim(call_2)
endif
if(i.eq.6 .and. std_2) msg(j0:j0+3)=grid4
if(i.ge.7) then
isnr = -50 + (i-7)/2
if(iand(i,1).eq.1) then
write(msg(j0:j0+2),'(i3.2)') isnr
if(msg(j0:j0).eq.' ') msg(j0:j0)='+'
else
write(msg(j0:j0+3),'("R",i3.2)') isnr
if(msg(j0+1:j0+1).eq.' ') msg(j0+1:j0+1)='+'
endif
endif
i3=-1
n3=-1
call genft8(msg,i3,n3,msgsent,msgbits,itone) !Source-encode this message
call encode174_91(msgbits,cw) !Get codeword for this message
rcw=2*cw-1
pow=0.0
do i=1,79
pow=pow+s8(itone(i),i)**2
enddo
hdec=0
where(llra.ge.0.0) hdec=1
nxor=ieor(hdec,cw)
da=sum(nxor*abs(llra))
hdec=0
where(llrb.ge.0.0) hdec=1
nxor=ieor(hdec,cw)
dbb=sum(nxor*abs(llrb))
hdec=0
where(llrc.ge.0.0) hdec=1
nxor=ieor(hdec,cw)
dc=sum(nxor*abs(llrc))
hdec=0
where(llrd.ge.0.0) hdec=1
nxor=ieor(hdec,cw)
dd=sum(nxor*abs(llrd))
dm=min(da,dbb,dc,dd)
dmm(imsg)=dm
if(dm.lt.dmin) then
dmin=dm
msgbest=msgsent
pbest=pow
if(dm.eq.da) then
nharderrors=count((2*cw-1)*llra.lt.0.0)
else if(dm.eq.dbb) then
nharderrors=count((2*cw-1)*llrb.lt.0.0)
else if(dm.eq.dc) then
nharderrors=count((2*cw-1)*llrc.lt.0.0)
else if(dm.eq.dd) then
nharderrors=count((2*cw-1)*llrd.lt.0.0)
endif
endif
enddo ! imsg
iloc=minloc(dmm)
dmm(iloc(1))=1.e30
iloc=minloc(dmm)
dmin2=dmm(iloc(1))
xsnr=-24.
arg=pbest/xbase/3.0e6-1.0
if(arg.gt.0.0) xsnr=db(arg)-27.0
! write(41,3041) nharderrors,dmin,dmin2,dmin2/dmin,xsnr,trim(msgbest)
!3041 format(i3,2f7.1,f7.2,f7.1,1x,a)
if(dmin.gt.100.0 .or. dmin2/dmin.lt.1.3) nharderrors=-1
msg37=msgbest
if(msg37(1:3).eq.'CQ ' .and. std_2 .and. grid4.eq.' ') nharderrors=-1
if(msg37(1:6).eq.'QU1RK ') nharderrors=-1
return
end subroutine ft8_a7d
end module ft8_a7

261
lib/ft8/ft8c.f90 Normal file
View File

@ -0,0 +1,261 @@
subroutine ft8c(dd0,newdat,call_1,call_2,grid4,xdt,f1,nharderrors,dmin, &
msg37,xsnr)
use crc
use timer_module, only: timer
use packjt77
include 'ft8_params.f90'
parameter(NP2=2812)
character*37 msg37,msg,msgsent,msgbest
character*12 call_1,call_2
character*4 grid4
real a(5)
real s8(0:7,NN)
real s2(0:511)
real bmeta(174),bmetb(174),bmetc(174),bmetd(174)
real llra(174),llrb(174),llrc(174),llrd(174),llrbest(174) !Soft symbols
real dd0(15*12000)
real ss(9)
real rcw(174)
integer*1 cw(174)
integer*1 msgbits(77)
integer*1 nxor(174),hdec(174)
integer itone(NN)
integer icos7(0:6),ip(1)
logical one(0:511,0:8)
integer graymap(0:7)
integer iloc(1)
complex cd0(0:3199)
complex ctwk(32)
complex csymb(32)
complex cs(0:7,NN)
logical std_1,std_2
logical first,newdat
data icos7/3,1,4,0,6,5,2/ ! Flipped w.r.t. original FT8 sync array
data first/.true./
data graymap/0,1,3,2,5,6,4,7/
save one
if(first) then
one=.false.
do i=0,511
do j=0,8
if(iand(i,2**j).ne.0) one(i,j)=.true.
enddo
enddo
first=.false.
endif
call stdcall(call_1,std_1)
if(call_1(1:3).eq.'CQ ') std_1=.true.
call stdcall(call_2,std_2)
nharderrors=-1
fs2=12000.0/NDOWN
dt2=1.0/fs2
twopi=8.0*atan(1.0)
delfbest=0.
ibest=0
call timer('ft8_down',0)
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
call timer('ft8_down',1)
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
smax=0.0
do idt=i0-10,i0+10 !Search over +/- one quarter symbol
call sync8d(cd0,idt,ctwk,0,sync)
if(sync.gt.smax) then
smax=sync
ibest=idt
endif
enddo
! Now peak up in frequency
smax=0.0
do ifr=-5,5 !Search over +/- 2.5 Hz
delf=ifr*0.5
dphi=twopi*delf*dt2
phi=0.0
do i=1,32
ctwk(i)=cmplx(cos(phi),sin(phi))
phi=mod(phi+dphi,twopi)
enddo
call sync8d(cd0,ibest,ctwk,1,sync)
if( sync .gt. smax ) then
smax=sync
delfbest=delf
endif
enddo
a=0.0
a(1)=-delfbest
call twkfreq1(cd0,NP2,fs2,a,cd0)
f1=f1+delfbest !Improved estimate of DF
call timer('ft8_down',0)
call ft8_downsample(dd0,.false.,f1,cd0) !Mix f1 to baseband and downsample
call timer('ft8_down',1)
smax=0.0
do idt=-4,4 !Search over +/- one quarter symbol
call sync8d(cd0,ibest+idt,ctwk,0,sync)
ss(idt+5)=sync
enddo
smax=maxval(ss)
iloc=maxloc(ss)
ibest=iloc(1)-5+ibest
xdt=(ibest-1)*dt2 - 0.5
sync=smax
do k=1,NN
i1=ibest+(k-1)*32
csymb=cmplx(0.0,0.0)
if( i1.ge.0 .and. i1+31 .le. NP2-1 ) csymb=cd0(i1:i1+31)
call four2a(csymb,32,1,-1,1)
cs(0:7,k)=csymb(1:8)/1e3
s8(0:7,k)=abs(csymb(1:8))
enddo
! sync quality check
is1=0
is2=0
is3=0
do k=1,7
ip=maxloc(s8(:,k))
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
ip=maxloc(s8(:,k+36))
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
ip=maxloc(s8(:,k+72))
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
enddo
! hard sync sum - max is 21
nsync=is1+is2+is3
! if(nsync .le. 6) return ! bail out
do nsym=1,3
nt=2**(3*nsym)
do ihalf=1,2
do k=1,29,nsym
if(ihalf.eq.1) ks=k+7
if(ihalf.eq.2) ks=k+43
amax=-1.0
do i=0,nt-1
i1=i/64
i2=iand(i,63)/8
i3=iand(i,7)
if(nsym.eq.1) then
s2(i)=abs(cs(graymap(i3),ks))
elseif(nsym.eq.2) then
s2(i)=abs(cs(graymap(i2),ks)+cs(graymap(i3),ks+1))
elseif(nsym.eq.3) then
s2(i)=abs(cs(graymap(i1),ks)+cs(graymap(i2),ks+1)+cs(graymap(i3),ks+2))
else
print*,"Error - nsym must be 1, 2, or 3."
endif
enddo
i32=1+(k-1)*3+(ihalf-1)*87
if(nsym.eq.1) ibmax=2
if(nsym.eq.2) ibmax=5
if(nsym.eq.3) ibmax=8
do ib=0,ibmax
bm=maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)) - &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib))
if(i32+ib .gt.174) cycle
if(nsym.eq.1) then
bmeta(i32+ib)=bm
den=max(maxval(s2(0:nt-1),one(0:nt-1,ibmax-ib)), &
maxval(s2(0:nt-1),.not.one(0:nt-1,ibmax-ib)))
if(den.gt.0.0) then
cm=bm/den
else ! erase it
cm=0.0
endif
bmetd(i32+ib)=cm
elseif(nsym.eq.2) then
bmetb(i32+ib)=bm
elseif(nsym.eq.3) then
bmetc(i32+ib)=bm
endif
enddo
enddo
enddo
enddo
call normalizebmet(bmeta,174)
call normalizebmet(bmetb,174)
call normalizebmet(bmetc,174)
call normalizebmet(bmetd,174)
scalefac=2.83
llra=scalefac*bmeta
llrb=scalefac*bmetb
llrc=scalefac*bmetc
llrd=scalefac*bmetd
! apmag=maxval(abs(llra))*1.01
MAXMSG=206
pbest=0.
do imsg=1,MAXMSG
msg=trim(call_1)//' '//trim(call_2)
i=imsg
if(call_1(1:3).eq.'CQ ' .and. i.ne.5) msg='QQ0XYZ '//trim(call_2)
if(.not.std_1) then
if(i.eq.1 .or. i.ge.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.2 .and. i.le.4) msg=trim(call_1)//' <'//trim(call_2)//'>'
else if(.not.std_2) then
if(i.le.4 .or. i.eq.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.7) msg=trim(call_1)//' <'//trim(call_2)//'>'
endif
j0=len(trim(msg))+2
if(i.eq.2) msg(j0:j0+2)='RRR'
if(i.eq.3) msg(j0:j0+3)='RR73'
if(i.eq.4) msg(j0:j0+1)='73'
if(i.eq.5) then
if(std_2) then
msg='CQ '//trim(call_2)
if(call_1(3:3).eq.'_') msg=trim(call_1)//' '//trim(call_2)
if(grid4.ne.'RR73') msg=trim(msg)//' '//grid4
endif
if(.not.std_2) msg='CQ '//trim(call_2)
endif
if(i.eq.6 .and. std_2) msg(j0:j0+3)=grid4
if(i.ge.7) then
isnr = -50 + (i-7)/2
if(iand(i,1).eq.1) then
write(msg(j0:j0+2),'(i3.2)') isnr
if(msg(j0:j0).eq.' ') msg(j0:j0)='+'
else
write(msg(j0:j0+3),'("R",i3.2)') isnr
if(msg(j0+1:j0+1).eq.' ') msg(j0+1:j0+1)='+'
endif
endif
! Source-encode, then get codeword
i3=-1
n3=-1
call genft8(msg,i3,n3,msgsent,msgbits,itone)
call encode174_91(msgbits,cw)
rcw=2*cw-1
pa=sum(llra*rcw)
pb=sum(llrb*rcw)
pc=sum(llrc*rcw)
pd=sum(llrd*rcw)
if(pa.gt.pbest) then
pbest=pa
msgbest=msgsent
llrbest=llra
nharderrors=count((2*cw-1)*llra.lt.0.0)
hdec=0
where(llra.ge.0.0) hdec=1
nxor=ieor(hdec,cw)
dmin=sum(nxor*abs(llra))
endif
enddo ! imsg
! write(*,4001) pbest,nharderrors,dmin,trim(msgbest)
!4001 format('$$$',f7.1,i4,f7.1,2x,a)
msg37=msgbest
return
end subroutine ft8c

109
lib/ft8/ft8q3.f90 Normal file
View File

@ -0,0 +1,109 @@
subroutine ft8q3(cd,xdt,f0,call_1,call_2,grid4,msgbest,snr)
! Get q3-style decodes for FT8.
use packjt77
parameter(NN=79,NSPS=32)
parameter(NWAVE=NN*NSPS) !2528
parameter(NZ=3200,NLAGS=NZ-NWAVE)
character*12 call_1,call_2
character*4 grid4
character*37 msg,msgbest,msgsent
character c77*77
complex cwave(0:NWAVE-1)
complex cd(0:NZ-1)
complex z
real xjunk(NWAVE)
real ccf(0:NLAGS-1)
real ccfmsg(206)
integer itone(NN)
integer*1 msgbits(77)
logical std_1,std_2
if(xdt.eq.-99.0) return !Silence compiler warning
call stdcall(call_1,std_1)
call stdcall(call_2,std_2)
fs=200.0 !Sample rate (Hz)
dt=1.0/fs !Sample interval (s)
bt=2.0
ccfbest=0.
lagbest=-1
do imsg=1,206
msg=trim(call_1)//' '//trim(call_2)
i=imsg
if(.not.std_1) then
if(i.eq.1 .or. i.ge.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.2 .and. i.le.4) msg=trim(call_1)//' <'//trim(call_2)//'>'
else if(.not.std_2) then
if(i.le.4 .or. i.eq.6) msg='<'//trim(call_1)//'> '//trim(call_2)
if(i.ge.7) msg=trim(call_1)//' <'//trim(call_2)//'>'
endif
j0=len(trim(msg))+2
if(i.eq.2) msg(j0:j0+2)='RRR'
if(i.eq.3) msg(j0:j0+3)='RR73'
if(i.eq.4) msg(j0:j0+1)='73'
if(i.eq.5) then
if(std_2) msg='CQ '//trim(call_2)//' '//grid4
if(.not.std_2) msg='CQ '//trim(call_2)
endif
if(i.eq.6 .and. std_2) msg(j0:j0+3)=grid4
if(i.ge.7 .and. i.le.206) then
isnr = -50 + (i-7)/2
if(iand(i,1).eq.1) then
write(msg(j0:j0+2),'(i3.2)') isnr
if(msg(j0:j0).eq.' ') msg(j0:j0)='+'
else
write(msg(j0:j0+3),'("R",i3.2)') isnr
if(msg(j0+1:j0+1).eq.' ') msg(j0+1:j0+1)='+'
endif
endif
! Source-encode, then get itone()
i3=-1
n3=-1
call pack77(msg,i3,n3,c77)
call genft8(msg,i3,n3,msgsent,msgbits,itone)
! Generate complex cwave
call gen_ft8wave(itone,NN,NSPS,bt,fs,f0,cwave,xjunk,1,NWAVE)
lagmax=-1
ccfmax=0.
nsum=32*2
do lag=0,nlags-1
z=0.
s=0.
do i=0,NWAVE-1
z=z + cd(i+lag)*conjg(cwave(i))
if(mod(i,nsum).eq.nsum-1 .or. i.eq.NWAVE-1) then
s=s + abs(z)
z=0.
endif
enddo
ccf(lag)=s
if(ccf(lag).gt.ccfmax) then
ccfmax=ccf(lag)
lagmax=lag
endif
enddo ! lag
ccfmsg(imsg)=ccfmax
if(ccfmax.gt.ccfbest) then
ccfbest=ccfmax
lagbest=lagmax
msgbest=msg
endif
enddo ! imsg
call pctile(ccfmsg,207,50,base)
call pctile(ccfmsg,207,67,sigma)
sigma=sigma-base
ccfmsg=(ccfmsg-base)/sigma
! do imsg=1,207
! write(44,3044) imsg,ccfmsg(imsg)
!3044 format(i5,f10.3)
! enddo
snr=maxval(ccfmsg)
return
end subroutine ft8q3

View File

@ -9,11 +9,12 @@ subroutine gen_ft8wave(itone,nsym,nsps,bt,fsample,f0,cwave,wave,icmplx,nwave)
real pulse(23040) real pulse(23040)
real dphi(0:(nsym+2)*nsps-1) real dphi(0:(nsym+2)*nsps-1)
integer itone(nsym) integer itone(nsym)
data ibt0/0/ data fchk0/0.0/
save pulse,twopi,dt,hmod,ibt0,ctab save pulse,twopi,dt,hmod,fchk0,ctab
ibt=nint(10*bt) ibt=nint(10*bt)
if(ibt0.ne.ibt) then fchk=nsym+nsps+bt+fsample
if(fchk.ne.fchk0) then
twopi=8.0*atan(1.0) twopi=8.0*atan(1.0)
dt=1.0/fsample dt=1.0/fsample
hmod=1.0 hmod=1.0
@ -22,11 +23,11 @@ subroutine gen_ft8wave(itone,nsym,nsps,bt,fsample,f0,cwave,wave,icmplx,nwave)
tt=(i-1.5*nsps)/real(nsps) tt=(i-1.5*nsps)/real(nsps)
pulse(i)=gfsk_pulse(bt,tt) pulse(i)=gfsk_pulse(bt,tt)
enddo enddo
ibt0=nint(10*bt)
do i=0,NTAB-1 do i=0,NTAB-1
phi=i*twopi/NTAB phi=i*twopi/NTAB
ctab(i)=cmplx(cos(phi),sin(phi)) ctab(i)=cmplx(cos(phi),sin(phi))
enddo enddo
fchk0=fchk
endif endif
! Compute the smoothed frequency waveform. ! Compute the smoothed frequency waveform.

View File

@ -58,6 +58,8 @@ subroutine subtractft8(dd0,itone,f0,dt,lrefinedt)
sq0=sqf(0) !Do the subtraction with idt=0 sq0=sqf(0) !Do the subtraction with idt=0
endif endif
dd0=dd !Return dd0 with this signal subtracted dd0=dd !Return dd0 with this signal subtracted
! write(44,3044) nint(f0),dt-0.5,1.e-8*sum(dd*dd)
!3044 format(i4,f7.2,f10.6)
return return
contains contains

41
lib/ft8/test_ft8q3.f90 Normal file
View File

@ -0,0 +1,41 @@
program test_ft8q3
! Test q3-style decodes for FT8.
use packjt77
parameter(NN=79,NSPS=32)
parameter(NWAVE=NN*NSPS) !2528
parameter(NZ=3200,NLAGS=NZ-NWAVE)
character arg*12
character*37 msg
character*12 call_1,call_2
character*4 grid4
complex cd(0:NZ-1)
! Get command-line argument(s)
nargs=iargc()
if(nargs.ne.4 .and. nargs.ne.5) then
print*,'Usage: ft8q3 DT f0 call_1 call_2 [grid4]'
go to 999
endif
call getarg(1,arg)
read(arg,*) xdt !Time offset from nominal (s)
call getarg(2,arg)
read(arg,*) f0 !Frequency (Hz)
call getarg(3,call_1) !First callsign
call getarg(4,call_2) !Second callsign
grid4=' '
if(nargs.eq.5) call getarg(5,grid4) !Locator for call_2
do i=0,NZ-1
read(40,3040) cd(i)
3040 format(17x,2f10.3)
enddo
call sec0(0,t)
call ft8q3(cd,xdt,f0,call_1,call_2,grid4,msg,snr)
call sec0(1,t)
write(*,1100) t,snr,trim(msg)
1100 format('Time:',f6.2,' S/N:',f6.1,' msg: ',a)
999 end program test_ft8q3

View File

@ -38,6 +38,7 @@ contains
use iso_c_binding, only: c_bool, c_int use iso_c_binding, only: c_bool, c_int
use timer_module, only: timer use timer_module, only: timer
use shmem, only: shmem_lock, shmem_unlock use shmem, only: shmem_lock, shmem_unlock
use ft8_a7
include 'ft8/ft8_params.f90' include 'ft8/ft8_params.f90'
@ -53,7 +54,8 @@ contains
logical newdat,lsubtract,ldupe,lrefinedt logical newdat,lsubtract,ldupe,lrefinedt
logical*1 ldiskdat logical*1 ldiskdat
logical lsubtracted(MAX_EARLY) logical lsubtracted(MAX_EARLY)
character*12 mycall12,hiscall12 character*12 mycall12,hiscall12,call_1,call_2
character*4 grid4
integer*2 iwave(15*12000) integer*2 iwave(15*12000)
integer apsym2(58),aph10(10) integer apsym2(58),aph10(10)
character datetime*13,msg37*37 character datetime*13,msg37*37
@ -64,13 +66,33 @@ contains
integer itone_save(NN,MAX_EARLY) integer itone_save(NN,MAX_EARLY)
real f1_save(MAX_EARLY) real f1_save(MAX_EARLY)
real xdt_save(MAX_EARLY) real xdt_save(MAX_EARLY)
data nutc0/-1/
save s,dd,dd1,ndec_early,itone_save,f1_save,xdt_save,lsubtracted,allmessages save s,dd,dd1,nutc0,ndec_early,itone_save,f1_save,xdt_save,lsubtracted,&
allmessages
this%callback => callback this%callback => callback
write(datetime,1001) nutc !### TEMPORARY ### write(datetime,1001) nutc !### TEMPORARY ###
1001 format("000000_",i6.6) 1001 format("000000_",i6.6)
if(nutc0.eq.-1) then
msg0=' '
dt0=0.
f0=0.
endif
if(nutc.ne.nutc0) then
! New UTC. Move previously saved 'a7' data from k=1 to k=0
iz=ndec(jseq,1)
dt0(1:iz,jseq,0) = dt0(1:iz,jseq,1)
f0(1:iz,jseq,0) = f0(1:iz,jseq,1)
msg0(1:iz,jseq,0) = msg0(1:iz,jseq,1)
ndec(jseq,0)=iz
ndec(jseq,1)=0
nutc0=nutc
dt0(:,jseq,1)=0.
f0(:,jseq,1)=0.
endif
if(ndepth.eq.1 .and. nzhsym.lt.50) then if(ndepth.eq.1 .and. nzhsym.lt.50) then
ndec_early=0 ndec_early=0
return return
@ -178,7 +200,7 @@ contains
hiscall12,f1,xdt,xbase,apsym2,aph10,nharderrors,dmin, & hiscall12,f1,xdt,xbase,apsym2,aph10,nharderrors,dmin, &
nbadcrc,iappass,msg37,xsnr,itone) nbadcrc,iappass,msg37,xsnr,itone)
call timer('ft8b ',1) call timer('ft8b ',1)
nsnr=nint(xsnr) nsnr=nint(xsnr)
xdt=xdt-0.5 xdt=xdt-0.5
hd=nharderrors+dmin hd=nharderrors+dmin
if(nbadcrc.eq.0) then if(nbadcrc.eq.0) then
@ -198,6 +220,11 @@ contains
qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0] qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0]
if(emedelay.ne.0) xdt=xdt+2.0 if(emedelay.ne.0) xdt=xdt+2.0
call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual) call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual)
call ft8_a7_save(nutc,xdt,f1,msg37) !Enter decode in table
! ii=ndec(jseq,1)
! write(41,3041) jseq,ii,nint(f0(ii,jseq,0)),msg0(ii,jseq,0)(1:22),&
! nint(f0(ii,jseq,1)),msg0(ii,jseq,1)(1:22)
!3041 format(3i5,2x,a22,i5,2x,a22)
endif endif
endif endif
call timestamp(tsec,tseq,ctime) call timestamp(tsec,tseq,ctime)
@ -209,7 +236,43 @@ contains
800 ndec_early=0 800 ndec_early=0
if(nzhsym.lt.50) ndec_early=ndecodes if(nzhsym.lt.50) ndec_early=ndecodes
900 return 900 continue
if(nzhsym.eq.50 .and. ndec(jseq,0).ge.1) then
newdat=.true.
do i=1,ndec(jseq,0)
if(f0(i,jseq,0).eq.-99.0) exit
if(f0(i,jseq,0).eq.-98.0) cycle
if(index(msg0(i,jseq,0),'<').ge.1) cycle !### Temporary ###
msg37=msg0(i,jseq,0)
i1=index(msg37,' ')
i2=index(msg37(i1+1:),' ') + i1
call_1=msg37(1:i1-1)
call_2=msg37(i1+1:i2-1)
grid4=msg37(i2+1:i2+4)
if(grid4.eq.'RR73' .or. index(grid4,'+').gt.0 .or. &
index(grid4,'-').gt.0) grid4=' '
xdt=dt0(i,jseq,0)
f1=f0(i,jseq,0)
xbase=10.0**(0.1*(sbase(max(1,nint(f1/3.125)))-40.0))
msg37=' '
call timer('ft8_a7d ',0)
call ft8_a7d(dd,newdat,call_1,call_2,grid4,xdt,f1,xbase,nharderrors, &
dmin,msg37,xsnr)
call timer('ft8_a7d ',1)
if(nharderrors.ge.0) then
if(associated(this%callback)) then
nsnr=xsnr
iaptype=7
qual=1.0
call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual)
call ft8_a7_save(nutc,xdt,f1,msg37) !Enter decode in table
endif
endif
enddo
endif
return
end subroutine decode end subroutine decode
subroutine timestamp(tsec,tseq,ctime) subroutine timestamp(tsec,tseq,ctime)

View File

@ -1,9 +1,10 @@
subroutine gen65(msg0,ichk,msgsent,itone,itype) subroutine gen65(msg00,ichk,msgsent0,itone,itype) BIND(c)
! Encodes a JT65 message to yieild itone(1:126) ! Encodes a JT65 message to yieild itone(1:126)
! Temporarily, does not implement EME shorthands ! Temporarily, does not implement EME shorthands
use packjt use packjt
character*1 msg00(23),msgsent0(23)
character*22 msg0 character*22 msg0
character*22 message !Message to be generated character*22 message !Message to be generated
character*22 msgsent !Message as it will be received character*22 msgsent !Message as it will be received
@ -21,6 +22,10 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype)
1,1,1,1,1,1/ 1,1,1,1,1,1/
save save
do i=1,22
msg0(i:i)=msg00(i)
enddo
if(msg0(1:1).eq.'@') then if(msg0(1:1).eq.'@') then
read(msg0(2:5),*,end=1,err=1) nfreq read(msg0(2:5),*,end=1,err=1) nfreq
go to 2 go to 2
@ -48,7 +53,7 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype)
call unpackmsg(dgen,msgsent) !Unpack to get message sent call unpackmsg(dgen,msgsent) !Unpack to get message sent
msgsent(20:22)=cok msgsent(20:22)=cok
call fmtmsg(msgsent,iz) call fmtmsg(msgsent,iz)
if(ichk.ne.0) go to 999 !Return if checking only if(ichk.ne.0) go to 900 !Return if checking only
call rs_encode(dgen,sent) !Apply Reed-Solomon code call rs_encode(dgen,sent) !Apply Reed-Solomon code
call interleave63(sent,1) !Apply interleaving call interleave63(sent,1) !Apply interleaving
@ -79,5 +84,10 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype)
endif endif
endif endif
999 return 900 do i=1,22
msgsent0(i)=msgsent(i:i)
enddo
msgsent0(23)=char(0)
return
end subroutine gen65 end subroutine gen65

View File

@ -62,6 +62,7 @@ contains
character(len=12) :: mycall, hiscall !Used for AP decoding character(len=12) :: mycall, hiscall !Used for AP decoding
character(len=6) :: hisgrid character(len=6) :: hisgrid
character*37 decoded !Decoded message character*37 decoded !Decoded message
character*37 decodes(100)
character*77 c77 character*77 c77
character*78 c78 character*78 c78
character*6 cutc character*6 cutc
@ -80,6 +81,8 @@ contains
! Start by setting some parameters and allocating storage for large arrays ! Start by setting some parameters and allocating storage for large arrays
call sec0(0,tdecode) call sec0(0,tdecode)
ndecodes=0
decodes=' '
nfa=nfa0 nfa=nfa0
nfb=nfb0 nfb=nfb0
nqd=nqd0 nqd=nqd0
@ -166,8 +169,8 @@ contains
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno) emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
call timer('q65_dec0',1) call timer('q65_dec0',1)
! write(*,3001) '=a',sum(abs(float(iwave))),nfqso,ntol,ndepth,xdt,f0,idec ! write(*,3001) '=a',nfqso,ntol,ndepth,xdt,f0,idec
!3001 format(a2,f15.0,3i5,f7.2,f7.1,i5) !3001 format(a2,3i5,f7.2,f7.1,i5)
if(idec.ge.0) then if(idec.ge.0) then
dtdec=xdt !We have a q3 or q0 decode at nfqso dtdec=xdt !We have a q3 or q0 decode at nfqso
@ -201,6 +204,7 @@ contains
call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, & call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, &
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec) xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
call timer('q65loops',1) call timer('q65loops',1)
! write(*,3001) '=b',nfqso,ntol,ndepth,xdt,f0,idec
if(idec.ge.0) then if(idec.ge.0) then
dtdec=xdt1 dtdec=xdt1
f0dec=f1 f0dec=f1
@ -268,33 +272,41 @@ contains
! Unpack decoded message for display to user ! Unpack decoded message for display to user
write(c77,1000) dat4(1:12),dat4(13)/2 write(c77,1000) dat4(1:12),dat4(13)/2
1000 format(12b6.6,b5.5) 1000 format(12b6.6,b5.5)
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get msgsent call unpack77(c77,1,decoded,unpk77_success) !Unpack to get decoded
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2) idupe=0
nsnr=nint(snr2) do i=1,ndecodes
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & if(decodes(i).eq.decoded) idupe=1
idec,nused,ntrperiod) enddo
call q65_hist(nint(f0dec),msg0=decoded) if(idupe.eq.0) then
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & ndecodes=min(ndecodes+1,100)
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg decodes(ndecodes)=decoded
call sec0(1,tdecode) call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & nsnr=nint(snr2)
position='append',iostat=ios) call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
if(ios.eq.0) then idec,nused,ntrperiod)
call q65_hist(nint(f0dec),msg0=decoded)
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios)
if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis. ! Save decoding parameters to q65_decoded.dat, for later analysis.
write(cmode,'(i3)') ntrperiod write(cmode,'(i3)') ntrperiod
cmode(4:4)=char(ichar('A')+nsubmode) cmode(4:4)=char(ichar('A')+nsubmode)
c6=hiscall(1:6) c6=hiscall(1:6)
if(c6.eq.' ') c6='<b> ' if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4) c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> ' if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// & fmt='(i6.4,1x,a4,i5,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, & write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded) tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) close(22)
endif
endif endif
endif endif
navg0=1000*navg(0) + navg(1) navg0=1000*navg(0) + navg(1)
@ -333,6 +345,7 @@ contains
call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, & call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, &
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec) xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
call timer('q65loops',1) call timer('q65loops',1)
! write(*,3001) '=e',nfqso,ntol,ndepth,xdt,f0,idec
if(idec.ge.0) then if(idec.ge.0) then
dtdec=xdt1 dtdec=xdt1
f0dec=f1 f0dec=f1
@ -344,33 +357,41 @@ contains
if(idec.ge.0) then if(idec.ge.0) then
! Unpack decoded message for display to user ! Unpack decoded message for display to user
write(c77,1000) dat4(1:12),dat4(13)/2 write(c77,1000) dat4(1:12),dat4(13)/2
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get msgsent call unpack77(c77,1,decoded,unpk77_success) !Unpack to get decoded
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2) idupe=0
nsnr=nint(snr2) do i=1,ndecodes
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & if(decodes(i).eq.decoded) idupe=1
idec,nused,ntrperiod) enddo
call q65_hist(nint(f0dec),msg0=decoded) if(idupe.eq.0) then
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & ndecodes=min(ndecodes+1,100)
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg decodes(ndecodes)=decoded
call sec0(1,tdecode) call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & nsnr=nint(snr2)
position='append',iostat=ios) call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
if(ios.eq.0) then idec,nused,ntrperiod)
call q65_hist(nint(f0dec),msg0=decoded)
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios)
if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis. ! Save decoding parameters to q65_decoded.dat, for later analysis.
write(cmode,'(i3)') ntrperiod write(cmode,'(i3)') ntrperiod
cmode(4:4)=char(ichar('A')+nsubmode) cmode(4:4)=char(ichar('A')+nsubmode)
c6=hiscall(1:6) c6=hiscall(1:6)
if(c6.eq.' ') c6='<b> ' if(c6.eq.' ') c6='<b> '
c4=hisgrid(1:4) c4=hisgrid(1:4)
if(c4.eq.' ') c4='<b> ' if(c4.eq.' ') c4='<b> '
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// & fmt='(i6.4,1x,a4,i5,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, & write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded) tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) close(22)
endif
endif endif
endif endif
enddo ! icand enddo ! icand

View File

@ -171,8 +171,6 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call timer('list_dec',0) call timer('list_dec',0)
call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
call timer('list_dec',1) call timer('list_dec',1)
! if(idec.ge.0) write(70,3070) idec,mode_q65,better,trim(decoded)
!3070 format(i3,i5,f8.2,2x,a)
endif endif
! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting. ! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting.
endif endif
@ -250,16 +248,15 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call q65_ccf_85(s1w,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best, & call q65_ccf_85(s1w,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best, &
better,ccf1) better,ccf1)
call timer('ccf_85 ',1) call timer('ccf_85 ',1)
! nsubmode is Tone-spacing indicator, 0-4 for A-E: a 0; b 1; c 2; d 3; e 4.
! and mode_q65=2**nsubmode ! nsubmode is Tone-spacing indicator, 0-4 for A-E: a 0; b 1; c 2; d 3; e 4.
! and mode_q65=2**nsubmode
if(better.ge.1.10) then if(better.ge.1.10) then
! if(better.ge.1.04 .or. mode_q65.ge.8) then ! if(better.ge.1.04 .or. mode_q65.ge.8) then
! if(better.ge.1.10 .or. mode_q65.ge.8) then ORIGINAL ! if(better.ge.1.10 .or. mode_q65.ge.8) then ORIGINAL
call timer('list_dec',0) call timer('list_dec',0)
call q65_dec_q3(s1w,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) call q65_dec_q3(s1w,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
call timer('list_dec',1) call timer('list_dec',1)
! if(idec.ge.0) write(70,3070) idec,mode_q65,better,trim(decoded)
!3070 format(i3,i5,f8.2,2x,a)
endif ! if(better.ge.1.10) endif ! if(better.ge.1.10)
endif ! if(ncw.gt.0 .and. iavg.le.1) endif ! if(ncw.gt.0 .and. iavg.le.1)
! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting. ! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting.
@ -570,7 +567,6 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
i=indx(k)+ia-1 i=indx(k)+ia-1
if(ccf2(i).lt.3.3) exit !Candidate limit if(ccf2(i).lt.3.3) exit !Candidate limit
f=i*df f=i*df
if(f.ge.(nfqso-ftol) .and. f.le.(nfqso+ftol)) cycle !Looked here already
i3=max(1, i-mode_q65) i3=max(1, i-mode_q65)
i4=min(iz,i+mode_q65) i4=min(iz,i+mode_q65)
biggest=maxval(ccf2(i3:i4)) biggest=maxval(ccf2(i3:i4))
@ -785,9 +781,9 @@ subroutine q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
sig_area=sum(spec(ia+nsum:ib-nsum)-1.0) sig_area=sum(spec(ia+nsum:ib-nsum)-1.0)
w_equiv=sig_area/(smax-1.0) w_equiv=sig_area/(smax-1.0)
snr2=db(max(1.0,sig_area)) - db(2500.0/df) snr2=db(max(1.0,sig_area)) - db(2500.0/df)
if(nused.eq.2) snr2=snr2 - 2.0 if(nused.eq.2) snr2=snr2 - 1.5
if(nused.eq.3) snr2=snr2 - 2.9 if(nused.eq.3) snr2=snr2 - 2.4
if(nused.ge.4) snr2=snr2 - 3.5 if(nused.ge.4) snr2=snr2 - 3.0
return return
end subroutine q65_snr end subroutine q65_snr

View File

@ -39,8 +39,8 @@ namespace
FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent) FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent)
: QLineEdit (parent) : QLineEdit (parent)
{ {
setValidator (new MHzValidator {-std::numeric_limits<FrequencyDelta>::max () / 10.e6, setValidator (new MHzValidator {static_cast<double>(std::numeric_limits<FrequencyDelta>::min ()) / 10.e6,
std::numeric_limits<FrequencyDelta>::max () / 10.e6, this}); static_cast<double>(std::numeric_limits<FrequencyDelta>::max ()) / 10.e6, this});
} }
auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta

View File

@ -39,7 +39,7 @@ namespace
FrequencyLineEdit::FrequencyLineEdit (QWidget * parent) FrequencyLineEdit::FrequencyLineEdit (QWidget * parent)
: QLineEdit (parent) : QLineEdit (parent)
{ {
setValidator (new MHzValidator {0., std::numeric_limits<Radio::Frequency>::max () / 10.e6, this}); setValidator (new MHzValidator {0., static_cast<double>(std::numeric_limits<Radio::Frequency>::max ()) / 10.e6, this});
} }
auto FrequencyLineEdit::frequency () const -> Frequency auto FrequencyLineEdit::frequency () const -> Frequency

View File

@ -404,6 +404,7 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
QColor bg; QColor bg;
QColor fg; QColor fg;
bool CQcall = false; bool CQcall = false;
auto is_73 = decodedText.messageWords().filter (QRegularExpression {"^(73|RR73)$"}).size();
if (decodedText.string ().contains (" CQ ") if (decodedText.string ().contains (" CQ ")
|| decodedText.string ().contains (" CQDX ") || decodedText.string ().contains (" CQDX ")
|| decodedText.string ().contains (" QRZ ")) || decodedText.string ().contains (" QRZ "))
@ -413,19 +414,6 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
else else
{ {
if (bCQonly) return; if (bCQonly) return;
if (myCall.size ())
{
QString regexp {"[ <]" + myCall + "[ >]"};
if (Radio::is_compound_callsign (myCall))
{
regexp = "(?:" + regexp + "|[ <]" + Radio::base_callsign (myCall) + "[ >])";
}
if ((decodedText.clean_string () + " ").contains (QRegularExpression {regexp}))
{
highlight_types types {Highlight::MyCall};
set_colours (m_config, &bg, &fg, types);
}
}
} }
auto message = decodedText.string(); auto message = decodedText.string();
QString dxCall; QString dxCall;
@ -446,14 +434,14 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
message = message.left (ap_pos).trimmed (); message = message.left (ap_pos).trimmed ();
} }
m_CQPriority=""; m_CQPriority="";
if (CQcall) if (CQcall || (is_73 && (m_config->highlight_73 ())))
{ {
if (displayDXCCEntity) if (displayDXCCEntity)
{ {
// if enabled add the DXCC entity and B4 status to the end of the // if enabled add the DXCC entity and B4 status to the end of the
// preformated text line t1 // preformated text line t1
auto currentMode = mode; auto currentMode = mode;
message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg message = appendWorkedB4 (message, dxCall, dxGrid, &bg, &fg
, logBook, currentBand, currentMode, extra); , logBook, currentBand, currentMode, extra);
} }
else else
@ -472,6 +460,20 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
message = leftJustifyAppendage (message, extra); message = leftJustifyAppendage (message, extra);
} }
if (myCall.size ())
{
QString regexp {"[ <]" + myCall + "[ >]"};
if (Radio::is_compound_callsign (myCall))
{
regexp = "(?:" + regexp + "|[ <]" + Radio::base_callsign (myCall) + "[ >])";
}
if ((decodedText.clean_string () + " ").contains (QRegularExpression {regexp}))
{
highlight_types types {Highlight::MyCall};
set_colours (m_config, &bg, &fg, types);
}
}
appendText (message.trimmed (), bg, fg, decodedText.call (), dxCall); appendText (message.trimmed (), bg, fg, decodedText.call (), dxCall);
} }

View File

@ -90,6 +90,8 @@
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "moc_mainwindow.cpp" #include "moc_mainwindow.cpp"
#define FCL fortran_charlen_t
extern "C" { extern "C" {
//----------------------------------------------------- C and Fortran routines //----------------------------------------------------- C and Fortran routines
void symspec_(struct dec_data *, int* k, double* trperiod, int* nsps, int* ingain, void symspec_(struct dec_data *, int* k, double* trperiod, int* nsps, int* ingain,
@ -133,8 +135,7 @@ extern "C" {
void genmsk_128_90_(char* msg, int* ichk, char* msgsent, int itone[], int* itype, void genmsk_128_90_(char* msg, int* ichk, char* msgsent, int itone[], int* itype,
fortran_charlen_t, fortran_charlen_t); fortran_charlen_t, fortran_charlen_t);
void gen65_(char* msg, int* ichk, char* msgsent, int itone[], void gen65(char* msg, int* ichk, char msgsent[], int itone[], int* itext);
int* itext, fortran_charlen_t, fortran_charlen_t);
void genq65_(char* msg, int* ichk, char* msgsent, int itone[], void genq65_(char* msg, int* ichk, char* msgsent, int itone[],
int* i3, int* n3, fortran_charlen_t, fortran_charlen_t); int* i3, int* n3, fortran_charlen_t, fortran_charlen_t);
@ -147,8 +148,6 @@ extern "C" {
void morse_(char* msg, int* icw, int* ncw, fortran_charlen_t); void morse_(char* msg, int* icw, int* ncw, fortran_charlen_t);
int ptt_(int nport, int ntx, int* iptt, int* nopen);
void wspr_downsample_(short int d2[], int* k); void wspr_downsample_(short int d2[], int* k);
int savec2_(char const * fname, int* TR_seconds, double* dial_freq, fortran_charlen_t); int savec2_(char const * fname, int* TR_seconds, double* dial_freq, fortran_charlen_t);
@ -170,8 +169,6 @@ extern "C" {
void freqcal_(short d2[], int* k, int* nkhz,int* noffset, int* ntol, void freqcal_(short d2[], int* k, int* nkhz,int* noffset, int* ntol,
char line[], fortran_charlen_t); char line[], fortran_charlen_t);
void fix_contest_msg_(char* MyGrid, char* msg, fortran_charlen_t, fortran_charlen_t);
void calibrate_(char const * data_dir, int* iz, double* a, double* b, double* rms, void calibrate_(char const * data_dir, int* iz, double* a, double* b, double* rms,
double* sigmaa, double* sigmab, int* irc, fortran_charlen_t); double* sigmaa, double* sigmab, int* irc, fortran_charlen_t);
@ -179,13 +176,9 @@ extern "C" {
void plotsave_(float swide[], int* m_w , int* m_h1, int* irow); void plotsave_(float swide[], int* m_w , int* m_h1, int* irow);
void chkcall_(char* w, char* basc_call, bool cok, int len1, int len2);
void get_ft4msg_(int* idecode, char* line, int len);
void chk_samples_(int* m_ihsym,int* k, int* m_hsymStop); void chk_samples_(int* m_ihsym,int* k, int* m_hsymStop);
void save_dxbase_(char* dxbase, int len); void save_dxbase_(char* dxbase, FCL len);
} }
int volatile itone[MAX_NUM_SYMBOLS]; //Audio tones for all Tx symbols int volatile itone[MAX_NUM_SYMBOLS]; //Audio tones for all Tx symbols
@ -604,6 +597,12 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->actionSave_decoded->setActionGroup(saveGroup); ui->actionSave_decoded->setActionGroup(saveGroup);
ui->actionSave_all->setActionGroup(saveGroup); ui->actionSave_all->setActionGroup(saveGroup);
QActionGroup* alltxtGroup = new QActionGroup(this);
ui->actionDon_t_split_ALL_TXT->setActionGroup(alltxtGroup);
ui->actionSplit_ALL_TXT_yearly->setActionGroup(alltxtGroup);
ui->actionSplit_ALL_TXT_monthly->setActionGroup(alltxtGroup);
ui->actionDisable_writing_of_ALL_TXT->setActionGroup(alltxtGroup);
QActionGroup* DepthGroup = new QActionGroup(this); QActionGroup* DepthGroup = new QActionGroup(this);
ui->actionQuickDecode->setActionGroup(DepthGroup); ui->actionQuickDecode->setActionGroup(DepthGroup);
ui->actionMediumDecode->setActionGroup(DepthGroup); ui->actionMediumDecode->setActionGroup(DepthGroup);
@ -954,7 +953,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->txFirstCheckBox->setChecked(m_txFirst); ui->txFirstCheckBox->setChecked(m_txFirst);
morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData()), morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData()),
const_cast<int *> (icw), &m_ncw, m_config.my_callsign ().length()); const_cast<int *> (icw), &m_ncw, (FCL)m_config.my_callsign().length());
on_actionWide_Waterfall_triggered(); on_actionWide_Waterfall_triggered();
ui->cbShMsgs->setChecked(m_bShMsgs); ui->cbShMsgs->setChecked(m_bShMsgs);
ui->cbSWL->setChecked(m_bSWL); ui->cbSWL->setChecked(m_bSWL);
@ -1188,6 +1187,10 @@ void MainWindow::writeSettings()
} }
m_settings->setValue ("PhaseEqualizationCoefficients", QVariant {coeffs}); m_settings->setValue ("PhaseEqualizationCoefficients", QVariant {coeffs});
} }
m_settings->setValue ("actionDontSplitALLTXT", ui->actionDon_t_split_ALL_TXT->isChecked() );
m_settings->setValue ("splitAllTxtYearly", ui->actionSplit_ALL_TXT_yearly->isChecked() );
m_settings->setValue ("splitAllTxtMonthly", ui->actionSplit_ALL_TXT_monthly->isChecked() );
m_settings->setValue ("disableWritingOfAllTxt", ui->actionDisable_writing_of_ALL_TXT->isChecked() );
m_settings->endGroup(); m_settings->endGroup();
} }
@ -1230,6 +1233,10 @@ void MainWindow::readSettings()
ui->actionAstronomical_data->setChecked (displayAstro); ui->actionAstronomical_data->setChecked (displayAstro);
m_settings->beginGroup("Common"); m_settings->beginGroup("Common");
ui->actionDon_t_split_ALL_TXT->setChecked(m_settings->value("actionDontSplitALLTXT", true).toBool());
ui->actionSplit_ALL_TXT_yearly->setChecked(m_settings->value("splitAllTxtYearly", false).toBool());
ui->actionSplit_ALL_TXT_monthly->setChecked(m_settings->value("splitAllTxtMonthly", false).toBool());
ui->actionDisable_writing_of_ALL_TXT->setChecked(m_settings->value("disableWritingOfAllTxt", false).toBool());
m_mode=m_settings->value("Mode","JT9").toString(); m_mode=m_settings->value("Mode","JT9").toString();
ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool()); ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
ui->actionSave_decoded->setChecked(m_settings->value("SaveDecoded",false).toBool()); ui->actionSave_decoded->setChecked(m_settings->value("SaveDecoded",false).toBool());
@ -1306,7 +1313,7 @@ void MainWindow::readSettings()
// use these initialisation settings to tune the audio o/p buffer // use these initialisation settings to tune the audio o/p buffer
// size and audio thread priority // size and audio thread priority
m_settings->beginGroup ("Tune"); m_settings->beginGroup ("Tune");
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8); m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::TimeCriticalPriority).toInt () % 8);
m_settings->endGroup (); m_settings->endGroup ();
checkMSK144ContestType(); checkMSK144ContestType();
@ -1440,7 +1447,7 @@ void MainWindow::dataSink(qint64 frames)
m_bUseRef=m_wideGraph->useRef(); m_bUseRef=m_wideGraph->useRef();
if(!m_diskData) { if(!m_diskData) {
refspectrum_(&dec_data.d2[k-m_nsps/2],&m_bClearRefSpec,&m_bRefSpec, refspectrum_(&dec_data.d2[k-m_nsps/2],&m_bClearRefSpec,&m_bRefSpec,
&m_bUseRef, fname.constData (), fname.size ()); &m_bUseRef, fname.constData (), (FCL)fname.size ());
} }
m_bClearRefSpec=false; m_bClearRefSpec=false;
@ -1480,7 +1487,7 @@ void MainWindow::dataSink(qint64 frames)
int RxFreq=ui->RxFreqSpinBox->value (); int RxFreq=ui->RxFreqSpinBox->value ();
int nkhz=(m_freqNominal+RxFreq)/1000; int nkhz=(m_freqNominal+RxFreq)/1000;
int ftol = ui->sbFtol->value (); int ftol = ui->sbFtol->value ();
freqcal_(&dec_data.d2[0],&k,&nkhz,&RxFreq,&ftol,&line[0],80); freqcal_(&dec_data.d2[0], &k, &nkhz, &RxFreq, &ftol, &line[0], (FCL)80);
QString t=QString::fromLatin1(line); QString t=QString::fromLatin1(line);
DecodedText decodedtext {t}; DecodedText decodedtext {t};
ui->decodedTextBrowser->displayDecodedText (decodedtext, m_config.my_callsign (), m_mode, m_config.DXCC (), ui->decodedTextBrowser->displayDecodedText (decodedtext, m_config.my_callsign (), m_mode, m_config.DXCC (),
@ -1599,7 +1606,7 @@ void MainWindow::dataSink(qint64 frames)
int nsec=120; int nsec=120;
int nbfo=1500; int nbfo=1500;
double f0m1500=m_freqNominal/1000000.0 + nbfo - 1500; double f0m1500=m_freqNominal/1000000.0 + nbfo - 1500;
int err = savec2_(c2name.constData (),&nsec,&f0m1500, c2name.size ()); int err = savec2_(c2name.constData (),&nsec,&f0m1500, (FCL)c2name.size());
if (err!=0) MessageBox::warning_message (this, tr ("Error saving c2 file"), c2name); if (err!=0) MessageBox::warning_message (this, tr ("Error saving c2 file"), c2name);
} }
} }
@ -1720,9 +1727,10 @@ void MainWindow::fastSink(qint64 frames)
float rmsNoGain = 0; float rmsNoGain = 0;
int ftol = ui->sbFtol->value (); int ftol = ui->sbFtol->value ();
hspec_(dec_data.d2,&k,&nutc0,&nTRpDepth,&RxFreq,&ftol,&bmsk144, hspec_(dec_data.d2,&k,&nutc0,&nTRpDepth,&RxFreq,&ftol,&bmsk144,
&m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0], &m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0],
&dec_data.params.hiscall[0],&bshmsg,&bswl, &dec_data.params.hiscall[0],&bshmsg,&bswl,
data_dir.constData (),fast_green,fast_s,&fast_jh,&pxmax,&rmsNoGain,&line[0],12,12,data_dir.size (),80); data_dir.constData (),fast_green,fast_s,&fast_jh,&pxmax,&rmsNoGain,&line[0],(FCL)12,
(FCL)12,(FCL)data_dir.size (),(FCL)80);
float px = fast_green[fast_jh]; float px = fast_green[fast_jh];
QString t; QString t;
t = t.asprintf(" Rx noise: %5.1f ",px); t = t.asprintf(" Rx noise: %5.1f ",px);
@ -1824,7 +1832,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
m_baseCall = Radio::base_callsign (m_config.my_callsign ()); m_baseCall = Radio::base_callsign (m_config.my_callsign ());
ui->tx1->setEnabled (elide_tx1_not_allowed () || ui->tx1->isEnabled ()); ui->tx1->setEnabled (elide_tx1_not_allowed () || ui->tx1->isEnabled ());
morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData()), morse_(const_cast<char *> (m_config.my_callsign ().toLatin1().constData()),
const_cast<int *> (icw), &m_ncw, m_config.my_callsign ().length()); const_cast<int *> (icw), &m_ncw, (FCL)m_config.my_callsign().length());
} }
if (m_config.my_callsign () != callsign || m_config.my_grid () != my_grid) { if (m_config.my_callsign () != callsign || m_config.my_grid () != my_grid) {
statusUpdate (); statusUpdate ();
@ -2537,7 +2545,7 @@ void MainWindow::on_actionSolve_FreqCal_triggered()
auto data_dir {QDir::toNativeSeparators(m_config.writeable_data_dir().absolutePath()).toLocal8Bit ()}; auto data_dir {QDir::toNativeSeparators(m_config.writeable_data_dir().absolutePath()).toLocal8Bit ()};
int iz,irc; int iz,irc;
double a,b,rms,sigmaa,sigmab; double a,b,rms,sigmaa,sigmab;
calibrate_(data_dir.constData (),&iz,&a,&b,&rms,&sigmaa,&sigmab,&irc,data_dir.size ()); calibrate_(data_dir.constData(), &iz, &a, &b, &rms, &sigmaa, &sigmab, &irc, (FCL)data_dir.size());
QString t2; QString t2;
if(irc==-1) t2="Cannot open " + data_dir + "/fmt.all"; if(irc==-1) t2="Cannot open " + data_dir + "/fmt.all";
if(irc==-2) t2="Cannot open " + data_dir + "/fcal2.out"; if(irc==-2) t2="Cannot open " + data_dir + "/fcal2.out";
@ -2582,7 +2590,7 @@ void MainWindow::on_actionCopyright_Notice_triggered()
"\"The algorithms, source code, look-and-feel of WSJT-X and related " "\"The algorithms, source code, look-and-feel of WSJT-X and related "
"programs, and protocol specifications for the modes FSK441, FST4, FT8, " "programs, and protocol specifications for the modes FSK441, FST4, FT8, "
"JT4, JT6M, JT9, JT65, JTMS, QRA64, Q65, MSK144 are Copyright (C) " "JT4, JT6M, JT9, JT65, JTMS, QRA64, Q65, MSK144 are Copyright (C) "
"2001-2021 by one or more of the following authors: Joseph Taylor, " "2001-2022 by one or more of the following authors: Joseph Taylor, "
"K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, " "K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, "
"IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; " "IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; "
"Philip Karn, KA9Q; and other members of the WSJT Development Group.\""); "Philip Karn, KA9Q; and other members of the WSJT Development Group.\"");
@ -3211,9 +3219,9 @@ void MainWindow::decode() //decode()
narg[13]=-1; narg[13]=-1;
narg[14]=m_config.aggressive(); narg[14]=m_config.aggressive();
memcpy(d2b,dec_data.d2,2*360000); memcpy(d2b,dec_data.d2,2*360000);
watcher3.setFuture (QtConcurrent::run (std::bind (fast_decode_,&d2b[0], watcher3.setFuture (QtConcurrent::run (std::bind (fast_decode_, &d2b[0],
&narg[0],&m_TRperiod,&m_msg[0][0], &narg[0],&m_TRperiod, &m_msg[0][0], dec_data.params.mycall,
dec_data.params.mycall,dec_data.params.hiscall,8000,12,12))); dec_data.params.hiscall, (FCL)8000, (FCL)12, (FCL)12)));
} else { } else {
mem_jt9->lock (); mem_jt9->lock ();
memcpy(to, from, qMin(mem_jt9->size(), size)); memcpy(to, from, qMin(mem_jt9->size(), size));
@ -3457,6 +3465,15 @@ void MainWindow::readFromStdout() //readFromStdout
ui->cbCQonly->isVisible() && ui->cbCQonly->isChecked(), ui->cbCQonly->isVisible() && ui->cbCQonly->isChecked(),
haveFSpread, fSpread); haveFSpread, fSpread);
if (m_config.highlight_DXcall () && (m_hisCall!="") && ((decodedtext.string().contains(QRegularExpression {"(\\w+) " + m_hisCall}))
|| (decodedtext.string().contains(QRegularExpression {"(\\w+) <" + m_hisCall +">"}))
|| (decodedtext.string().contains(QRegularExpression {"<(\\w+)> " + m_hisCall})))) {
ui->decodedTextBrowser->highlight_callsign(m_hisCall, QColor(255,0,0), QColor(255,255,255), true); // highlight dxCallEntry
}
if (m_config.highlight_DXgrid () && (m_hisGrid!="") && (decodedtext.string().contains(m_hisGrid))) {
ui->decodedTextBrowser->highlight_callsign(m_hisGrid, QColor(0,0,255), QColor(255,255,255), true); // highlight dxGridEntry
}
if(m_bBestSPArmed && m_mode=="FT4" && CALLING == m_QSOProgress) { if(m_bBestSPArmed && m_mode=="FT4" && CALLING == m_QSOProgress) {
QString messagePriority=ui->decodedTextBrowser->CQPriority(); QString messagePriority=ui->decodedTextBrowser->CQPriority();
if(messagePriority!="") { if(messagePriority!="") {
@ -3709,7 +3726,8 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
void MainWindow::pskPost (DecodedText const& decodedtext) void MainWindow::pskPost (DecodedText const& decodedtext)
{ {
if (m_diskData || !m_config.spot_to_psk_reporter() || decodedtext.isLowConfidence ()) return; if (m_diskData || !m_config.spot_to_psk_reporter() || decodedtext.isLowConfidence ()
|| (decodedtext.string().contains(m_baseCall) && decodedtext.string().contains(m_config.my_grid().left(4)))) return; // prevent self-spotting when running multiple instances
QString msgmode=m_mode; QString msgmode=m_mode;
QString deCall; QString deCall;
@ -4019,18 +4037,18 @@ void MainWindow::guiUpdate()
if(m_QSOProgress==REPORT || m_QSOProgress==ROGER_REPORT) m_bSentReport=true; if(m_QSOProgress==REPORT || m_QSOProgress==ROGER_REPORT) m_bSentReport=true;
if(m_bSentReport and (m_QSOProgress<REPORT or m_QSOProgress>ROGER_REPORT)) m_bSentReport=false; if(m_bSentReport and (m_QSOProgress<REPORT or m_QSOProgress>ROGER_REPORT)) m_bSentReport=false;
if(m_mode=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone), if(m_mode=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22); &m_currentMessageType, (FCL)22, (FCL)22);
if(m_mode=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone), if(m_mode=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22); &m_currentMessageType, (FCL)22, (FCL)22);
if(m_mode=="JT65") gen65_(message, &ichk, msgsent, const_cast<int *> (itone), if(m_mode=="JT65") gen65(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22); &m_currentMessageType);
if(m_mode=="WSPR") genwspr_(message, msgsent, const_cast<int *> (itone), if(m_mode=="WSPR") genwspr_(message, msgsent, const_cast<int *> (itone),
22, 22); (FCL)22, (FCL)22);
if(m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4" if(m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4"
or m_mode=="FST4" or m_mode=="FST4W" || "Q65" == m_mode) { or m_mode=="FST4" or m_mode=="FST4W" || "Q65" == m_mode) {
if(m_mode=="MSK144") { if(m_mode=="MSK144") {
genmsk_128_90_(message, &ichk, msgsent, const_cast<int *> (itone), genmsk_128_90_(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 37, 37); &m_currentMessageType, (FCL)37, (FCL)37);
if(m_restart) { if(m_restart) {
int nsym=144; int nsym=144;
if(itone[40]==-40) nsym=40; if(itone[40]==-40) nsym=40;
@ -4046,7 +4064,7 @@ void MainWindow::guiUpdate()
int n3=0; int n3=0;
char ft8msgbits[77]; char ft8msgbits[77];
genft8_(message, &i3, &n3, msgsent, const_cast<char *> (ft8msgbits), genft8_(message, &i3, &n3, msgsent, const_cast<char *> (ft8msgbits),
const_cast<int *> (itone), 37, 37); const_cast<int *> (itone), (FCL)37, (FCL)37);
int nsym=79; int nsym=79;
int nsps=4*1920; int nsps=4*1920;
float fsample=48000.0; float fsample=48000.0;
@ -4073,7 +4091,7 @@ void MainWindow::guiUpdate()
int ichk=0; int ichk=0;
char ft4msgbits[77]; char ft4msgbits[77];
genft4_(message, &ichk, msgsent, const_cast<char *> (ft4msgbits), genft4_(message, &ichk, msgsent, const_cast<char *> (ft4msgbits),
const_cast<int *>(itone), 37, 37); const_cast<int *>(itone), (FCL)37, (FCL)37);
int nsym=103; int nsym=103;
int nsps=4*576; int nsps=4*576;
float fsample=48000.0; float fsample=48000.0;
@ -4095,7 +4113,7 @@ void MainWindow::guiUpdate()
ba2msg(ba,message); ba2msg(ba,message);
} }
genfst4_(message,&ichk,msgsent,const_cast<char *> (fst4msgbits), genfst4_(message,&ichk,msgsent,const_cast<char *> (fst4msgbits),
const_cast<int *>(itone), &iwspr, 37, 37); const_cast<int *>(itone), &iwspr, (FCL)37, (FCL)37);
int hmod=1; int hmod=1;
if(m_config.x2ToneSpacing()) hmod=2; if(m_config.x2ToneSpacing()) hmod=2;
if(m_config.x4ToneSpacing()) hmod=4; if(m_config.x4ToneSpacing()) hmod=4;
@ -4122,7 +4140,7 @@ void MainWindow::guiUpdate()
if(m_mode=="Q65") { if(m_mode=="Q65") {
int i3=-1; int i3=-1;
int n3=-1; int n3=-1;
genq65_(message,&ichk,msgsent,const_cast<int *>(itone),&i3,&n3,37,37); genq65_(message, &ichk,msgsent, const_cast<int *>(itone), &i3, &n3, (FCL)37, (FCL)37);
int nsps=1800; int nsps=1800;
if(m_TRperiod==30) nsps=3600; if(m_TRperiod==30) nsps=3600;
if(m_TRperiod==60) nsps=7200; if(m_TRperiod==60) nsps=7200;
@ -5374,7 +5392,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
auto is_type_one = !is77BitMode () && is_compound && shortList (my_callsign); auto is_type_one = !is77BitMode () && is_compound && shortList (my_callsign);
auto const& my_grid = m_config.my_grid ().left (4); auto const& my_grid = m_config.my_grid ().left (4);
auto const& hisBase = Radio::base_callsign (hisCall); auto const& hisBase = Radio::base_callsign (hisCall);
save_dxbase_(const_cast <char *> ((hisBase + " ").left (6).toLatin1().constData()),6); save_dxbase_(const_cast <char *> ((hisBase + " ").left(6).toLatin1().constData()), (FCL)6);
auto eme_short_codes = m_config.enable_VHF_features () && ui->cbShMsgs->isChecked () auto eme_short_codes = m_config.enable_VHF_features () && ui->cbShMsgs->isChecked ()
&& m_mode == "JT65"; && m_mode == "JT65";
@ -5761,7 +5779,7 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
QByteArray s=t.toUpper().toLocal8Bit(); QByteArray s=t.toUpper().toLocal8Bit();
ba2msg(s,message); ba2msg(s,message);
int ichk=1,itype=0; int ichk=1,itype=0;
gen65_(message,&ichk,msgsent,const_cast<int*>(itone0),&itype,22,22); gen65(message, &ichk,msgsent, const_cast<int*>(itone0), &itype);
msgsent[22]=0; msgsent[22]=0;
bool text=false; bool text=false;
bool shortMsg=false; bool shortMsg=false;
@ -5859,7 +5877,7 @@ void MainWindow::on_dxCallEntry_textChanged (QString const& call)
void MainWindow::on_dxCallEntry_editingFinished() void MainWindow::on_dxCallEntry_editingFinished()
{ {
auto const& dxBase = Radio::base_callsign (m_hisCall); auto const& dxBase = Radio::base_callsign (m_hisCall);
save_dxbase_(const_cast <char *> ((dxBase + " ").left (6).toLatin1().constData()),6); save_dxbase_(const_cast <char *> ((dxBase + " ").left (6).toLatin1().constData()), (FCL)6);
} }
@ -5880,7 +5898,7 @@ void MainWindow::on_dxGridEntry_textChanged (QString const& grid)
int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter; int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1().constData()), azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1().constData()),
const_cast <char *> ((m_hisGrid + " ").left (6).toLatin1().constData()),&utch, const_cast <char *> ((m_hisGrid + " ").left (6).toLatin1().constData()),&utch,
&nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6); &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,(FCL)6,(FCL)6);
QString t; QString t;
int nd=nDkm; int nd=nDkm;
if(m_config.miles()) nd=nDmiles; if(m_config.miles()) nd=nDmiles;
@ -6012,6 +6030,8 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call,
m_xSent.clear (); m_xSent.clear ();
m_xRcvd.clear (); m_xRcvd.clear ();
if (m_config.clear_DXcall ()) ui->dxCallEntry->clear ();
if (m_config.clear_DXgrid ()) ui->dxGridEntry->clear ();
} }
qint64 MainWindow::nWidgets(QString t) qint64 MainWindow::nWidgets(QString t)
@ -6221,7 +6241,6 @@ void MainWindow::on_actionFT8_triggered()
m_bFast9=false; m_bFast9=false;
m_bFastMode=false; m_bFastMode=false;
WSPR_config(false); WSPR_config(false);
switch_mode (Modes::FT8);
m_nsps=6912; m_nsps=6912;
m_FFTSize = m_nsps / 2; m_FFTSize = m_nsps / 2;
Q_EMIT FFTSize (m_FFTSize); Q_EMIT FFTSize (m_FFTSize);
@ -6272,6 +6291,8 @@ void MainWindow::on_actionFT8_triggered()
on_fox_log_action_triggered(); on_fox_log_action_triggered();
} }
if(SpecOp::HOUND == m_config.special_op_id()) { if(SpecOp::HOUND == m_config.special_op_id()) {
ui->houndButton->setChecked(true);
ui->houndButton->setStyleSheet("background-color: #ff0000;");
ui->txFirstCheckBox->setChecked(false); ui->txFirstCheckBox->setChecked(false);
ui->txFirstCheckBox->setEnabled(false); ui->txFirstCheckBox->setEnabled(false);
ui->cbAutoSeq->setEnabled(false); ui->cbAutoSeq->setEnabled(false);
@ -6289,6 +6310,8 @@ void MainWindow::on_actionFT8_triggered()
ui->txb4->setEnabled(false); ui->txb4->setEnabled(false);
ui->txb5->setEnabled(false); ui->txb5->setEnabled(false);
ui->txb6->setEnabled(false); ui->txb6->setEnabled(false);
} else {
switch_mode (Modes::FT8);
} }
if (SpecOp::NONE < m_config.special_op_id () && SpecOp::FOX > m_config.special_op_id ()) { if (SpecOp::NONE < m_config.special_op_id () && SpecOp::FOX > m_config.special_op_id ()) {
@ -7034,6 +7057,7 @@ void MainWindow::on_rptSpinBox_valueChanged(int n)
void MainWindow::on_tuneButton_clicked (bool checked) void MainWindow::on_tuneButton_clicked (bool checked)
{ {
tuneATU_Timer.start (120000); // tune watchdog (120s)
static bool lastChecked = false; static bool lastChecked = false;
if (lastChecked == checked) return; if (lastChecked == checked) return;
lastChecked = checked; lastChecked = checked;
@ -7814,7 +7838,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
showNormal (); showNormal ();
raise (); raise ();
} }
if (text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) { if ((text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) || (ui->cbHoldTxFreq->isChecked ())) {
// a message we are willing to accept and auto reply to // a message we are willing to accept and auto reply to
m_bDoubleClicked = true; m_bDoubleClicked = true;
} }
@ -8010,7 +8034,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter; int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1 ().constData ()), azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1 ().constData ()),
const_cast <char *> ((grid + " ").left (6).toLatin1 ().constData ()),&utch, const_cast <char *> ((grid + " ").left (6).toLatin1 ().constData ()),&utch,
&nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6); &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,(FCL)6,(FCL)6);
QString t1; QString t1;
if(m_config.miles()) { if(m_config.miles()) {
t1 = t1.asprintf("%7d",nDmiles); t1 = t1.asprintf("%7d",nDmiles);
@ -9221,6 +9245,7 @@ void MainWindow::foxTest()
void MainWindow::write_all(QString txRx, QString message) void MainWindow::write_all(QString txRx, QString message)
{ {
if (!(ui->actionDisable_writing_of_ALL_TXT->isChecked())) {
QString line; QString line;
QString t; QString t;
QString msg; QString msg;
@ -9261,6 +9286,8 @@ void MainWindow::write_all(QString txRx, QString message)
} }
QString file_name="ALL.TXT"; QString file_name="ALL.TXT";
if (ui->actionSplit_ALL_TXT_yearly->isChecked()) file_name=(time.toString("yyyy") + "-" + "ALL.TXT");
if (ui->actionSplit_ALL_TXT_monthly->isChecked()) file_name=(time.toString("yyyy-MM") + "-" + "ALL.TXT");
if (m_mode=="WSPR") file_name="ALL_WSPR.TXT"; if (m_mode=="WSPR") file_name="ALL_WSPR.TXT";
QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)}; QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)};
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) { if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
@ -9279,6 +9306,7 @@ void MainWindow::write_all(QString txRx, QString message)
QTimer::singleShot (0, [=] { // don't block guiUpdate QTimer::singleShot (0, [=] { // don't block guiUpdate
MessageBox::warning_message(this, tr ("Log File Error"), message2); }); MessageBox::warning_message(this, tr ("Log File Error"), message2); });
} }
}
} }
void MainWindow::chkFT4() void MainWindow::chkFT4()
@ -9443,3 +9471,55 @@ QString MainWindow::WSPR_message()
} }
return msg2; return msg2;
} }
void MainWindow::on_houndButton_clicked (bool checked)
{
if (checked) {
ui->houndButton->setStyleSheet("background-color: #ff0000;");
m_config.setSpecial_Hound();
} else {
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
}
on_actionFT8_triggered();
}
void MainWindow::on_ft8Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
on_actionFT8_triggered();
}
void MainWindow::on_ft4Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
on_actionFT4_triggered();
}
void MainWindow::on_msk144Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
on_actionMSK144_triggered();
}
void MainWindow::on_q65Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
on_actionQ65_triggered();
}
void MainWindow::on_jt65Button_clicked()
{
ui->houndButton->setChecked(false);
ui->houndButton->setStyleSheet("");
m_config.setSpecial_None();
on_actionJT65_triggered();
}

View File

@ -141,6 +141,12 @@ private:
private slots: private slots:
void initialize_fonts (); void initialize_fonts ();
void on_houndButton_clicked(bool checked);
void on_ft8Button_clicked();
void on_ft4Button_clicked();
void on_msk144Button_clicked();
void on_q65Button_clicked();
void on_jt65Button_clicked();
void on_tx1_editingFinished(); void on_tx1_editingFinished();
void on_tx2_editingFinished(); void on_tx2_editingFinished();
void on_tx3_editingFinished(); void on_tx3_editingFinished();

File diff suppressed because it is too large Load Diff

View File

@ -77,7 +77,7 @@ SignalMeter::SignalMeter (QWidget * parent)
outer_layout->setSpacing (0); outer_layout->setSpacing (0);
auto inner_layout = new QHBoxLayout; auto inner_layout = new QHBoxLayout;
inner_layout->setContentsMargins (9, 0, 9, 0); inner_layout->setContentsMargins (1, 0, 1, 0);
inner_layout->setSpacing (0); inner_layout->setSpacing (0);
m_meter = new MeterWidget; m_meter = new MeterWidget;