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

View File

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

View File

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

View File

@ -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 &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">
<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>&amp;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 &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>
</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>

View File

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

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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