mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-21 19:55:20 -05:00
Merge branch 'feat-a7-UR' into develop
This commit is contained in:
commit
062f3a8037
@ -71,7 +71,7 @@ message (STATUS "******************************************************")
|
||||
|
||||
include (set_build_type)
|
||||
# RC 0 or omitted is a development build, GA is a General Availability release build
|
||||
set_build_type (RC 1)
|
||||
set_build_type (RC 0)
|
||||
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_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.")
|
||||
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
|
||||
is_debug_build OFF)
|
||||
CMAKE_DEPENDENT_OPTION (WSJT_CREATE_WINMAIN
|
||||
@ -336,6 +337,7 @@ set (wsjt_FSRCS
|
||||
lib/timer_module.f90
|
||||
lib/wavhdr.f90
|
||||
lib/qra/q65/q65_encoding_modules.f90
|
||||
lib/ft8/ft8_a7.f90
|
||||
|
||||
# remaining non-module sources
|
||||
lib/addit.f90
|
||||
@ -461,7 +463,6 @@ set (wsjt_FSRCS
|
||||
lib/inter_wspr.f90
|
||||
lib/jplsubs.f
|
||||
lib/jt9fano.f90
|
||||
lib/jtmsg.f90
|
||||
lib/libration.f90
|
||||
lib/lorentzian.f90
|
||||
lib/fst4/lorentzian_fading.f90
|
||||
@ -1448,7 +1449,7 @@ set_target_properties (wsjtx PROPERTIES
|
||||
)
|
||||
|
||||
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
|
||||
if (APPLE)
|
||||
if ((NOT ${OPENMP_FOUND}) OR APPLE)
|
||||
target_link_libraries (wsjtx wsjt_fort)
|
||||
else ()
|
||||
target_link_libraries (wsjtx wsjt_fort_omp)
|
||||
|
@ -593,6 +593,7 @@ private:
|
||||
bool highlight_by_mode_;
|
||||
bool highlight_only_fields_;
|
||||
bool include_WAE_entities_;
|
||||
bool highlight_73_;
|
||||
int LotW_days_since_upload_;
|
||||
|
||||
TransceiverFactory::ParameterPack rig_params_;
|
||||
@ -670,6 +671,10 @@ private:
|
||||
bool bLowSidelobes_;
|
||||
bool pwrBandTxMemory_;
|
||||
bool pwrBandTuneMemory_;
|
||||
bool highlight_DXcall_;
|
||||
bool clear_DXcall_;
|
||||
bool highlight_DXgrid_;
|
||||
bool clear_DXgrid_;
|
||||
|
||||
QAudioDeviceInfo 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_only_fields () const {return m_->highlight_only_fields_;}
|
||||
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)
|
||||
{
|
||||
@ -920,6 +930,30 @@ void Configuration::set_location (QString const& grid_descriptor)
|
||||
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
|
||||
{
|
||||
#if defined (Q_OS_MAC)
|
||||
@ -984,6 +1018,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
||||
, highlight_by_mode_ {false}
|
||||
, highlight_only_fields_ {false}
|
||||
, include_WAE_entities_ {false}
|
||||
, highlight_73_ {false}
|
||||
, LotW_days_since_upload_ {0}
|
||||
, last_port_type_ {TransceiverFactory::Capabilities::none}
|
||||
, rig_is_dummy_ {false}
|
||||
@ -1397,7 +1432,12 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->highlight_by_mode_check_box->setChecked (highlight_by_mode_);
|
||||
ui_->only_fields_check_box->setChecked (highlight_only_fields_);
|
||||
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_->cbHighlightDXcall->setChecked(highlight_DXcall_);
|
||||
ui_->cbClearDXcall->setChecked(clear_DXcall_);
|
||||
ui_->cbHighlightDXgrid->setChecked(highlight_DXgrid_);
|
||||
ui_->cbClearDXgrid->setChecked(clear_DXgrid_);
|
||||
|
||||
set_rig_invariants ();
|
||||
}
|
||||
@ -1492,6 +1532,7 @@ void Configuration::impl::read_settings ()
|
||||
highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool ();
|
||||
highlight_only_fields_ = settings_->value("OnlyFieldsSought", 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_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 ();
|
||||
pwrBandTxMemory_ = settings_->value("pwrBandTxMemory",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 ()
|
||||
@ -1626,6 +1671,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("HighlightByMode", highlight_by_mode_);
|
||||
settings_->setValue ("OnlyFieldsSought", highlight_only_fields_);
|
||||
settings_->setValue ("IncludeWAEEntities", include_WAE_entities_);
|
||||
settings_->setValue ("Highlight73", highlight_73_);
|
||||
settings_->setValue ("LotWDaysSinceLastUpload", LotW_days_since_upload_);
|
||||
settings_->setValue ("toRTTY", log_as_RTTY_);
|
||||
settings_->setValue ("dBtoComments", report_in_comments_);
|
||||
@ -1685,6 +1731,10 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
|
||||
settings_->setValue ("Region", QVariant::fromValue (region_));
|
||||
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 ();
|
||||
}
|
||||
|
||||
@ -2163,6 +2213,7 @@ void Configuration::impl::accept ()
|
||||
highlight_by_mode_ = ui_->highlight_by_mode_check_box->isChecked ();
|
||||
highlight_only_fields_ = ui_->only_fields_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_users_.set_age_constraint (LotW_days_since_upload_);
|
||||
|
||||
@ -2172,6 +2223,10 @@ void Configuration::impl::accept ()
|
||||
dynamic_grid_.clear ();
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -181,6 +181,14 @@ public:
|
||||
bool highlight_by_mode () const;
|
||||
bool highlight_only_fields () 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};
|
||||
SpecialOperatingActivity special_op_id () const;
|
||||
|
131
Configuration.ui
131
Configuration.ui
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>554</width>
|
||||
<height>560</height>
|
||||
<height>599</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -181,29 +181,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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 &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><html><head/><body><p>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.</p><p>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.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start new period decodes at top</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="ppfx_check_box">
|
||||
<property name="text">
|
||||
@ -265,13 +242,10 @@
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="cbHighlightDXcall">
|
||||
<property name="text">
|
||||
<string>&Blank line between decoding periods</string>
|
||||
<string>Highlight DX Call in message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -285,6 +259,60 @@
|
||||
</property>
|
||||
</widget>
|
||||
</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 &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><html><head/><body><p>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.</p><p>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.</p></body></html></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>&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>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2302,6 +2330,23 @@ Right click for insert and delete options.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="DecodeHighlightingListView" name="highlighting_list_view">
|
||||
<property name="sizePolicy">
|
||||
@ -2349,20 +2394,10 @@ Right click for insert and delete options.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="include_WAE_check_box">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="highlight_73_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>
|
||||
<string>Highlight also messages with 73 or RR73</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -3233,13 +3268,13 @@ Right click for insert and delete options.</string>
|
||||
</connection>
|
||||
</connections>
|
||||
<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="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="special_op_activity_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="CAT_data_bits_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
@ -54,7 +54,7 @@ namespace Radio
|
||||
value *= std::pow (10., scale);
|
||||
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.;
|
||||
*ok = false;
|
||||
@ -91,8 +91,8 @@ namespace Radio
|
||||
value *= std::pow (10., scale);
|
||||
if (ok)
|
||||
{
|
||||
if (value < -std::numeric_limits<Frequency>::max ()
|
||||
|| value > std::numeric_limits<Frequency>::max ())
|
||||
if (value < static_cast<double>(std::numeric_limits<Frequency>::min ())
|
||||
|| value > static_cast<double>(std::numeric_limits<Frequency>::max ()))
|
||||
{
|
||||
value = 0.;
|
||||
*ok = false;
|
||||
|
4
cty.dat
4
cty.dat
@ -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:
|
||||
TL;
|
||||
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:
|
||||
TR;
|
||||
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],
|
||||
YH8[54];
|
||||
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:
|
||||
YJ;
|
||||
Syria: 20: 39: AS: 35.38: -38.20: -2.0: YK:
|
||||
|
@ -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
|
||||
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.
|
||||
|
||||
- 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
|
||||
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
|
||||
you receive the Tx3 message (R plus contest exchange) again, hit F4
|
||||
to re-send your RR73.
|
||||
you receive the Tx3 message (R plus contest exchange) again, and if
|
||||
you have activated the *Alternate F1-F6 bindings*, hit *F4* to
|
||||
re-send your RR73.
|
||||
|
||||
[[COMP-CALL]]
|
||||
=== Nonstandard Callsigns
|
||||
|
@ -830,7 +830,9 @@ subroutine split77(msg,nwords,nw,w)
|
||||
iz=j !Message length
|
||||
nwords=k !Number of words in msg
|
||||
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:)=' '
|
||||
if(nwords.lt.3) go to 900
|
||||
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
|
||||
nwords=nwords-1
|
||||
endif
|
||||
|
||||
|
||||
900 return
|
||||
end subroutine split77
|
||||
|
||||
|
@ -34,7 +34,9 @@ subroutine chkcall(w,bc,cok)
|
||||
|
||||
! 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(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
|
||||
i1=0
|
||||
|
161
lib/ft8/chkdec.f90
Normal file
161
lib/ft8/chkdec.f90
Normal 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
378
lib/ft8/ft8_a7.f90
Normal 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
261
lib/ft8/ft8c.f90
Normal 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
109
lib/ft8/ft8q3.f90
Normal 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
|
@ -9,11 +9,12 @@ subroutine gen_ft8wave(itone,nsym,nsps,bt,fsample,f0,cwave,wave,icmplx,nwave)
|
||||
real pulse(23040)
|
||||
real dphi(0:(nsym+2)*nsps-1)
|
||||
integer itone(nsym)
|
||||
data ibt0/0/
|
||||
save pulse,twopi,dt,hmod,ibt0,ctab
|
||||
data fchk0/0.0/
|
||||
save pulse,twopi,dt,hmod,fchk0,ctab
|
||||
|
||||
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)
|
||||
dt=1.0/fsample
|
||||
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)
|
||||
pulse(i)=gfsk_pulse(bt,tt)
|
||||
enddo
|
||||
ibt0=nint(10*bt)
|
||||
do i=0,NTAB-1
|
||||
phi=i*twopi/NTAB
|
||||
ctab(i)=cmplx(cos(phi),sin(phi))
|
||||
enddo
|
||||
fchk0=fchk
|
||||
endif
|
||||
|
||||
! Compute the smoothed frequency waveform.
|
||||
|
@ -58,6 +58,8 @@ subroutine subtractft8(dd0,itone,f0,dt,lrefinedt)
|
||||
sq0=sqf(0) !Do the subtraction with idt=0
|
||||
endif
|
||||
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
|
||||
|
||||
contains
|
||||
|
41
lib/ft8/test_ft8q3.f90
Normal file
41
lib/ft8/test_ft8q3.f90
Normal 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
|
@ -38,6 +38,7 @@ contains
|
||||
use iso_c_binding, only: c_bool, c_int
|
||||
use timer_module, only: timer
|
||||
use shmem, only: shmem_lock, shmem_unlock
|
||||
use ft8_a7
|
||||
|
||||
include 'ft8/ft8_params.f90'
|
||||
|
||||
@ -53,7 +54,8 @@ contains
|
||||
logical newdat,lsubtract,ldupe,lrefinedt
|
||||
logical*1 ldiskdat
|
||||
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 apsym2(58),aph10(10)
|
||||
character datetime*13,msg37*37
|
||||
@ -64,13 +66,33 @@ contains
|
||||
integer itone_save(NN,MAX_EARLY)
|
||||
real f1_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
|
||||
write(datetime,1001) nutc !### TEMPORARY ###
|
||||
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
|
||||
ndec_early=0
|
||||
return
|
||||
@ -178,7 +200,7 @@ contains
|
||||
hiscall12,f1,xdt,xbase,apsym2,aph10,nharderrors,dmin, &
|
||||
nbadcrc,iappass,msg37,xsnr,itone)
|
||||
call timer('ft8b ',1)
|
||||
nsnr=nint(xsnr)
|
||||
nsnr=nint(xsnr)
|
||||
xdt=xdt-0.5
|
||||
hd=nharderrors+dmin
|
||||
if(nbadcrc.eq.0) then
|
||||
@ -198,6 +220,11 @@ contains
|
||||
qual=1.0-(nharderrors+dmin)/60.0 ! scale qual to [0.0,1.0]
|
||||
if(emedelay.ne.0) xdt=xdt+2.0
|
||||
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
|
||||
call timestamp(tsec,tseq,ctime)
|
||||
@ -209,7 +236,43 @@ contains
|
||||
800 ndec_early=0
|
||||
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
|
||||
|
||||
subroutine timestamp(tsec,tseq,ctime)
|
||||
|
@ -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)
|
||||
! Temporarily, does not implement EME shorthands
|
||||
|
||||
use packjt
|
||||
character*1 msg00(23),msgsent0(23)
|
||||
character*22 msg0
|
||||
character*22 message !Message to be generated
|
||||
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/
|
||||
save
|
||||
|
||||
do i=1,22
|
||||
msg0(i:i)=msg00(i)
|
||||
enddo
|
||||
|
||||
if(msg0(1:1).eq.'@') then
|
||||
read(msg0(2:5),*,end=1,err=1) nfreq
|
||||
go to 2
|
||||
@ -48,7 +53,7 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype)
|
||||
call unpackmsg(dgen,msgsent) !Unpack to get message sent
|
||||
msgsent(20:22)=cok
|
||||
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 interleave63(sent,1) !Apply interleaving
|
||||
@ -79,5 +84,10 @@ subroutine gen65(msg0,ichk,msgsent,itone,itype)
|
||||
endif
|
||||
endif
|
||||
|
||||
999 return
|
||||
900 do i=1,22
|
||||
msgsent0(i)=msgsent(i:i)
|
||||
enddo
|
||||
msgsent0(23)=char(0)
|
||||
|
||||
return
|
||||
end subroutine gen65
|
||||
|
@ -62,6 +62,7 @@ contains
|
||||
character(len=12) :: mycall, hiscall !Used for AP decoding
|
||||
character(len=6) :: hisgrid
|
||||
character*37 decoded !Decoded message
|
||||
character*37 decodes(100)
|
||||
character*77 c77
|
||||
character*78 c78
|
||||
character*6 cutc
|
||||
@ -80,6 +81,8 @@ contains
|
||||
|
||||
! Start by setting some parameters and allocating storage for large arrays
|
||||
call sec0(0,tdecode)
|
||||
ndecodes=0
|
||||
decodes=' '
|
||||
nfa=nfa0
|
||||
nfb=nfb0
|
||||
nqd=nqd0
|
||||
@ -166,8 +169,8 @@ contains
|
||||
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
|
||||
emedelay,xdt,f0,snr1,width,dat4,snr2,idec,stageno)
|
||||
call timer('q65_dec0',1)
|
||||
! write(*,3001) '=a',sum(abs(float(iwave))),nfqso,ntol,ndepth,xdt,f0,idec
|
||||
!3001 format(a2,f15.0,3i5,f7.2,f7.1,i5)
|
||||
! write(*,3001) '=a',nfqso,ntol,ndepth,xdt,f0,idec
|
||||
!3001 format(a2,3i5,f7.2,f7.1,i5)
|
||||
|
||||
if(idec.ge.0) then
|
||||
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, &
|
||||
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
|
||||
call timer('q65loops',1)
|
||||
! write(*,3001) '=b',nfqso,ntol,ndepth,xdt,f0,idec
|
||||
if(idec.ge.0) then
|
||||
dtdec=xdt1
|
||||
f0dec=f1
|
||||
@ -268,33 +272,41 @@ contains
|
||||
! Unpack decoded message for display to user
|
||||
write(c77,1000) dat4(1:12),dat4(13)/2
|
||||
1000 format(12b6.6,b5.5)
|
||||
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get msgsent
|
||||
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
|
||||
nsnr=nint(snr2)
|
||||
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
|
||||
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
|
||||
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get decoded
|
||||
idupe=0
|
||||
do i=1,ndecodes
|
||||
if(decodes(i).eq.decoded) idupe=1
|
||||
enddo
|
||||
if(idupe.eq.0) then
|
||||
ndecodes=min(ndecodes+1,100)
|
||||
decodes(ndecodes)=decoded
|
||||
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
|
||||
nsnr=nint(snr2)
|
||||
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
|
||||
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.
|
||||
write(cmode,'(i3)') ntrperiod
|
||||
cmode(4:4)=char(ichar('A')+nsubmode)
|
||||
c6=hiscall(1:6)
|
||||
if(c6.eq.' ') c6='<b> '
|
||||
c4=hisgrid(1:4)
|
||||
if(c4.eq.' ') c4='<b> '
|
||||
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
|
||||
'1x,a6,1x,a6,1x,a4,1x,a)'
|
||||
if(ntrperiod.le.30) fmt(5:5)='6'
|
||||
if(idec.eq.3) nrc=0
|
||||
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, &
|
||||
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
|
||||
tdecode,mycall(1:6),c6,c4,trim(decoded)
|
||||
close(22)
|
||||
write(cmode,'(i3)') ntrperiod
|
||||
cmode(4:4)=char(ichar('A')+nsubmode)
|
||||
c6=hiscall(1:6)
|
||||
if(c6.eq.' ') c6='<b> '
|
||||
c4=hisgrid(1:4)
|
||||
if(c4.eq.' ') c4='<b> '
|
||||
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)'
|
||||
if(ntrperiod.le.30) fmt(5:5)='6'
|
||||
if(idec.eq.3) nrc=0
|
||||
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
|
||||
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
|
||||
tdecode,mycall(1:6),c6,c4,trim(decoded)
|
||||
close(22)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
navg0=1000*navg(0) + navg(1)
|
||||
@ -333,6 +345,7 @@ contains
|
||||
call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, &
|
||||
xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
|
||||
call timer('q65loops',1)
|
||||
! write(*,3001) '=e',nfqso,ntol,ndepth,xdt,f0,idec
|
||||
if(idec.ge.0) then
|
||||
dtdec=xdt1
|
||||
f0dec=f1
|
||||
@ -344,33 +357,41 @@ contains
|
||||
if(idec.ge.0) then
|
||||
! Unpack decoded message for display to user
|
||||
write(c77,1000) dat4(1:12),dat4(13)/2
|
||||
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get msgsent
|
||||
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
|
||||
nsnr=nint(snr2)
|
||||
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
|
||||
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
|
||||
call unpack77(c77,1,decoded,unpk77_success) !Unpack to get decoded
|
||||
idupe=0
|
||||
do i=1,ndecodes
|
||||
if(decodes(i).eq.decoded) idupe=1
|
||||
enddo
|
||||
if(idupe.eq.0) then
|
||||
ndecodes=min(ndecodes+1,100)
|
||||
decodes(ndecodes)=decoded
|
||||
call q65_snr(dat4,dtdec,f0dec,mode_q65,nused,snr2)
|
||||
nsnr=nint(snr2)
|
||||
call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, &
|
||||
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.
|
||||
write(cmode,'(i3)') ntrperiod
|
||||
cmode(4:4)=char(ichar('A')+nsubmode)
|
||||
c6=hiscall(1:6)
|
||||
if(c6.eq.' ') c6='<b> '
|
||||
c4=hisgrid(1:4)
|
||||
if(c4.eq.' ') c4='<b> '
|
||||
fmt='(i6.4,1x,a4,4i2,6i3,i4,f6.2,f7.1,f6.1,f7.1,f6.2,'// &
|
||||
'1x,a6,1x,a6,1x,a4,1x,a)'
|
||||
if(ntrperiod.le.30) fmt(5:5)='6'
|
||||
if(idec.eq.3) nrc=0
|
||||
write(22,fmt) nutc,cmode,nQSOprogress,idec,idfbest,idtbest,ibw, &
|
||||
ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
|
||||
tdecode,mycall(1:6),c6,c4,trim(decoded)
|
||||
close(22)
|
||||
write(cmode,'(i3)') ntrperiod
|
||||
cmode(4:4)=char(ichar('A')+nsubmode)
|
||||
c6=hiscall(1:6)
|
||||
if(c6.eq.' ') c6='<b> '
|
||||
c4=hisgrid(1:4)
|
||||
if(c4.eq.' ') c4='<b> '
|
||||
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)'
|
||||
if(ntrperiod.le.30) fmt(5:5)='6'
|
||||
if(idec.eq.3) nrc=0
|
||||
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
|
||||
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
|
||||
tdecode,mycall(1:6),c6,c4,trim(decoded)
|
||||
close(22)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
enddo ! icand
|
||||
|
@ -171,8 +171,6 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
|
||||
call timer('list_dec',0)
|
||||
call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
|
||||
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 idec=3 we have a q3 decode. Continue to compute sync curve for plotting.
|
||||
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, &
|
||||
better,ccf1)
|
||||
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.04 .or. mode_q65.ge.8) then
|
||||
! if(better.ge.1.10 .or. mode_q65.ge.8) then ORIGINAL
|
||||
call timer('list_dec',0)
|
||||
call q65_dec_q3(s1w,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
|
||||
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(ncw.gt.0 .and. iavg.le.1)
|
||||
! 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
|
||||
if(ccf2(i).lt.3.3) exit !Candidate limit
|
||||
f=i*df
|
||||
if(f.ge.(nfqso-ftol) .and. f.le.(nfqso+ftol)) cycle !Looked here already
|
||||
i3=max(1, i-mode_q65)
|
||||
i4=min(iz,i+mode_q65)
|
||||
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)
|
||||
w_equiv=sig_area/(smax-1.0)
|
||||
snr2=db(max(1.0,sig_area)) - db(2500.0/df)
|
||||
if(nused.eq.2) snr2=snr2 - 2.0
|
||||
if(nused.eq.3) snr2=snr2 - 2.9
|
||||
if(nused.ge.4) snr2=snr2 - 3.5
|
||||
if(nused.eq.2) snr2=snr2 - 1.5
|
||||
if(nused.eq.3) snr2=snr2 - 2.4
|
||||
if(nused.ge.4) snr2=snr2 - 3.0
|
||||
|
||||
return
|
||||
end subroutine q65_snr
|
||||
|
@ -39,8 +39,8 @@ namespace
|
||||
FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent)
|
||||
: QLineEdit (parent)
|
||||
{
|
||||
setValidator (new MHzValidator {-std::numeric_limits<FrequencyDelta>::max () / 10.e6,
|
||||
std::numeric_limits<FrequencyDelta>::max () / 10.e6, this});
|
||||
setValidator (new MHzValidator {static_cast<double>(std::numeric_limits<FrequencyDelta>::min ()) / 10.e6,
|
||||
static_cast<double>(std::numeric_limits<FrequencyDelta>::max ()) / 10.e6, this});
|
||||
}
|
||||
|
||||
auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta
|
||||
|
@ -39,7 +39,7 @@ namespace
|
||||
FrequencyLineEdit::FrequencyLineEdit (QWidget * 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
|
||||
|
@ -404,6 +404,7 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
QColor bg;
|
||||
QColor fg;
|
||||
bool CQcall = false;
|
||||
auto is_73 = decodedText.messageWords().filter (QRegularExpression {"^(73|RR73)$"}).size();
|
||||
if (decodedText.string ().contains (" CQ ")
|
||||
|| decodedText.string ().contains (" CQDX ")
|
||||
|| decodedText.string ().contains (" QRZ "))
|
||||
@ -413,19 +414,6 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
else
|
||||
{
|
||||
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();
|
||||
QString dxCall;
|
||||
@ -446,14 +434,14 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
message = message.left (ap_pos).trimmed ();
|
||||
}
|
||||
m_CQPriority="";
|
||||
if (CQcall)
|
||||
if (CQcall || (is_73 && (m_config->highlight_73 ())))
|
||||
{
|
||||
if (displayDXCCEntity)
|
||||
{
|
||||
// if enabled add the DXCC entity and B4 status to the end of the
|
||||
// preformated text line t1
|
||||
auto currentMode = mode;
|
||||
message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg
|
||||
message = appendWorkedB4 (message, dxCall, dxGrid, &bg, &fg
|
||||
, logBook, currentBand, currentMode, extra);
|
||||
}
|
||||
else
|
||||
@ -472,6 +460,20 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,8 @@
|
||||
#include "ui_mainwindow.h"
|
||||
#include "moc_mainwindow.cpp"
|
||||
|
||||
#define FCL fortran_charlen_t
|
||||
|
||||
extern "C" {
|
||||
//----------------------------------------------------- C and Fortran routines
|
||||
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,
|
||||
fortran_charlen_t, fortran_charlen_t);
|
||||
|
||||
void gen65_(char* msg, int* ichk, char* msgsent, int itone[],
|
||||
int* itext, fortran_charlen_t, fortran_charlen_t);
|
||||
void gen65(char* msg, int* ichk, char msgsent[], int itone[], int* itext);
|
||||
|
||||
void genq65_(char* msg, int* ichk, char* msgsent, int itone[],
|
||||
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);
|
||||
|
||||
int ptt_(int nport, int ntx, int* iptt, int* nopen);
|
||||
|
||||
void wspr_downsample_(short int d2[], int* k);
|
||||
|
||||
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,
|
||||
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,
|
||||
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 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 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
|
||||
@ -604,6 +597,12 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
ui->actionSave_decoded->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);
|
||||
ui->actionQuickDecode->setActionGroup(DepthGroup);
|
||||
ui->actionMediumDecode->setActionGroup(DepthGroup);
|
||||
@ -954,7 +953,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
|
||||
ui->txFirstCheckBox->setChecked(m_txFirst);
|
||||
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();
|
||||
ui->cbShMsgs->setChecked(m_bShMsgs);
|
||||
ui->cbSWL->setChecked(m_bSWL);
|
||||
@ -1188,6 +1187,10 @@ void MainWindow::writeSettings()
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1230,6 +1233,10 @@ void MainWindow::readSettings()
|
||||
ui->actionAstronomical_data->setChecked (displayAstro);
|
||||
|
||||
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();
|
||||
ui->actionNone->setChecked(m_settings->value("SaveNone",true).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
|
||||
// size and audio thread priority
|
||||
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 ();
|
||||
|
||||
checkMSK144ContestType();
|
||||
@ -1440,7 +1447,7 @@ void MainWindow::dataSink(qint64 frames)
|
||||
m_bUseRef=m_wideGraph->useRef();
|
||||
if(!m_diskData) {
|
||||
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;
|
||||
|
||||
@ -1480,7 +1487,7 @@ void MainWindow::dataSink(qint64 frames)
|
||||
int RxFreq=ui->RxFreqSpinBox->value ();
|
||||
int nkhz=(m_freqNominal+RxFreq)/1000;
|
||||
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);
|
||||
DecodedText decodedtext {t};
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
@ -1720,9 +1727,10 @@ void MainWindow::fastSink(qint64 frames)
|
||||
float rmsNoGain = 0;
|
||||
int ftol = ui->sbFtol->value ();
|
||||
hspec_(dec_data.d2,&k,&nutc0,&nTRpDepth,&RxFreq,&ftol,&bmsk144,
|
||||
&m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0],
|
||||
&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);
|
||||
&m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0],
|
||||
&dec_data.params.hiscall[0],&bshmsg,&bswl,
|
||||
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];
|
||||
QString t;
|
||||
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 ());
|
||||
ui->tx1->setEnabled (elide_tx1_not_allowed () || ui->tx1->isEnabled ());
|
||||
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) {
|
||||
statusUpdate ();
|
||||
@ -2537,7 +2545,7 @@ void MainWindow::on_actionSolve_FreqCal_triggered()
|
||||
auto data_dir {QDir::toNativeSeparators(m_config.writeable_data_dir().absolutePath()).toLocal8Bit ()};
|
||||
int iz,irc;
|
||||
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;
|
||||
if(irc==-1) t2="Cannot open " + data_dir + "/fmt.all";
|
||||
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 "
|
||||
"programs, and protocol specifications for the modes FSK441, FST4, FT8, "
|
||||
"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, "
|
||||
"IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; "
|
||||
"Philip Karn, KA9Q; and other members of the WSJT Development Group.\"");
|
||||
@ -3211,9 +3219,9 @@ void MainWindow::decode() //decode()
|
||||
narg[13]=-1;
|
||||
narg[14]=m_config.aggressive();
|
||||
memcpy(d2b,dec_data.d2,2*360000);
|
||||
watcher3.setFuture (QtConcurrent::run (std::bind (fast_decode_,&d2b[0],
|
||||
&narg[0],&m_TRperiod,&m_msg[0][0],
|
||||
dec_data.params.mycall,dec_data.params.hiscall,8000,12,12)));
|
||||
watcher3.setFuture (QtConcurrent::run (std::bind (fast_decode_, &d2b[0],
|
||||
&narg[0],&m_TRperiod, &m_msg[0][0], dec_data.params.mycall,
|
||||
dec_data.params.hiscall, (FCL)8000, (FCL)12, (FCL)12)));
|
||||
} else {
|
||||
mem_jt9->lock ();
|
||||
memcpy(to, from, qMin(mem_jt9->size(), size));
|
||||
@ -3457,6 +3465,15 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
ui->cbCQonly->isVisible() && ui->cbCQonly->isChecked(),
|
||||
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) {
|
||||
QString messagePriority=ui->decodedTextBrowser->CQPriority();
|
||||
if(messagePriority!="") {
|
||||
@ -3709,7 +3726,8 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
|
||||
|
||||
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 deCall;
|
||||
@ -4019,18 +4037,18 @@ void MainWindow::guiUpdate()
|
||||
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_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),
|
||||
&m_currentMessageType, 22, 22);
|
||||
if(m_mode=="JT65") gen65_(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),
|
||||
&m_currentMessageType);
|
||||
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"
|
||||
or m_mode=="FST4" or m_mode=="FST4W" || "Q65" == m_mode) {
|
||||
if(m_mode=="MSK144") {
|
||||
genmsk_128_90_(message, &ichk, msgsent, const_cast<int *> (itone),
|
||||
&m_currentMessageType, 37, 37);
|
||||
&m_currentMessageType, (FCL)37, (FCL)37);
|
||||
if(m_restart) {
|
||||
int nsym=144;
|
||||
if(itone[40]==-40) nsym=40;
|
||||
@ -4046,7 +4064,7 @@ void MainWindow::guiUpdate()
|
||||
int n3=0;
|
||||
char ft8msgbits[77];
|
||||
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 nsps=4*1920;
|
||||
float fsample=48000.0;
|
||||
@ -4073,7 +4091,7 @@ void MainWindow::guiUpdate()
|
||||
int ichk=0;
|
||||
char ft4msgbits[77];
|
||||
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 nsps=4*576;
|
||||
float fsample=48000.0;
|
||||
@ -4095,7 +4113,7 @@ void MainWindow::guiUpdate()
|
||||
ba2msg(ba,message);
|
||||
}
|
||||
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;
|
||||
if(m_config.x2ToneSpacing()) hmod=2;
|
||||
if(m_config.x4ToneSpacing()) hmod=4;
|
||||
@ -4122,7 +4140,7 @@ void MainWindow::guiUpdate()
|
||||
if(m_mode=="Q65") {
|
||||
int i3=-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;
|
||||
if(m_TRperiod==30) nsps=3600;
|
||||
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 const& my_grid = m_config.my_grid ().left (4);
|
||||
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 ()
|
||||
&& m_mode == "JT65";
|
||||
|
||||
@ -5761,7 +5779,7 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
|
||||
QByteArray s=t.toUpper().toLocal8Bit();
|
||||
ba2msg(s,message);
|
||||
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;
|
||||
bool text=false;
|
||||
bool shortMsg=false;
|
||||
@ -5859,7 +5877,7 @@ void MainWindow::on_dxCallEntry_textChanged (QString const& call)
|
||||
void MainWindow::on_dxCallEntry_editingFinished()
|
||||
{
|
||||
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;
|
||||
azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1().constData()),
|
||||
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;
|
||||
int nd=nDkm;
|
||||
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_xRcvd.clear ();
|
||||
if (m_config.clear_DXcall ()) ui->dxCallEntry->clear ();
|
||||
if (m_config.clear_DXgrid ()) ui->dxGridEntry->clear ();
|
||||
}
|
||||
|
||||
qint64 MainWindow::nWidgets(QString t)
|
||||
@ -6221,7 +6241,6 @@ void MainWindow::on_actionFT8_triggered()
|
||||
m_bFast9=false;
|
||||
m_bFastMode=false;
|
||||
WSPR_config(false);
|
||||
switch_mode (Modes::FT8);
|
||||
m_nsps=6912;
|
||||
m_FFTSize = m_nsps / 2;
|
||||
Q_EMIT FFTSize (m_FFTSize);
|
||||
@ -6272,6 +6291,8 @@ void MainWindow::on_actionFT8_triggered()
|
||||
on_fox_log_action_triggered();
|
||||
}
|
||||
if(SpecOp::HOUND == m_config.special_op_id()) {
|
||||
ui->houndButton->setChecked(true);
|
||||
ui->houndButton->setStyleSheet("background-color: #ff0000;");
|
||||
ui->txFirstCheckBox->setChecked(false);
|
||||
ui->txFirstCheckBox->setEnabled(false);
|
||||
ui->cbAutoSeq->setEnabled(false);
|
||||
@ -6289,6 +6310,8 @@ void MainWindow::on_actionFT8_triggered()
|
||||
ui->txb4->setEnabled(false);
|
||||
ui->txb5->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 ()) {
|
||||
@ -7034,6 +7057,7 @@ void MainWindow::on_rptSpinBox_valueChanged(int n)
|
||||
|
||||
void MainWindow::on_tuneButton_clicked (bool checked)
|
||||
{
|
||||
tuneATU_Timer.start (120000); // tune watchdog (120s)
|
||||
static bool lastChecked = false;
|
||||
if (lastChecked == checked) return;
|
||||
lastChecked = checked;
|
||||
@ -7814,7 +7838,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
|
||||
showNormal ();
|
||||
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
|
||||
m_bDoubleClicked = true;
|
||||
}
|
||||
@ -8010,7 +8034,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
|
||||
azdist_(const_cast <char *> ((m_config.my_grid () + " ").left (6).toLatin1 ().constData ()),
|
||||
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;
|
||||
if(m_config.miles()) {
|
||||
t1 = t1.asprintf("%7d",nDmiles);
|
||||
@ -9221,6 +9245,7 @@ void MainWindow::foxTest()
|
||||
|
||||
void MainWindow::write_all(QString txRx, QString message)
|
||||
{
|
||||
if (!(ui->actionDisable_writing_of_ALL_TXT->isChecked())) {
|
||||
QString line;
|
||||
QString t;
|
||||
QString msg;
|
||||
@ -9261,6 +9286,8 @@ void MainWindow::write_all(QString txRx, QString message)
|
||||
}
|
||||
|
||||
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";
|
||||
QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)};
|
||||
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
|
||||
MessageBox::warning_message(this, tr ("Log File Error"), message2); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::chkFT4()
|
||||
@ -9443,3 +9471,55 @@ QString MainWindow::WSPR_message()
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
@ -141,6 +141,12 @@ private:
|
||||
|
||||
private slots:
|
||||
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_tx2_editingFinished();
|
||||
void on_tx3_editingFinished();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -77,7 +77,7 @@ SignalMeter::SignalMeter (QWidget * parent)
|
||||
outer_layout->setSpacing (0);
|
||||
|
||||
auto inner_layout = new QHBoxLayout;
|
||||
inner_layout->setContentsMargins (9, 0, 9, 0);
|
||||
inner_layout->setContentsMargins (1, 0, 1, 0);
|
||||
inner_layout->setSpacing (0);
|
||||
|
||||
m_meter = new MeterWidget;
|
||||
|
Loading…
Reference in New Issue
Block a user