mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-09-04 22:27:50 -04:00
Merge branch 'develop' into working-freqs
This commit is contained in:
commit
f59e9cba04
@ -71,7 +71,7 @@ message (STATUS "******************************************************")
|
|||||||
|
|
||||||
include (set_build_type)
|
include (set_build_type)
|
||||||
# RC 0 or omitted is a development build, GA is a General Availability release build
|
# RC 0 or omitted is a development build, GA is a General Availability release build
|
||||||
set_build_type (RC 4)
|
set_build_type (RC 5)
|
||||||
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
|
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1436,7 +1436,9 @@ void Configuration::impl::initialize_models ()
|
|||||||
ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true);
|
ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true);
|
||||||
ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval);
|
ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval);
|
||||||
ui_->opCallEntry->setText (opCall_);
|
ui_->opCallEntry->setText (opCall_);
|
||||||
|
ui_->udp_server_line_edit->setEnabled(false);
|
||||||
ui_->udp_server_line_edit->setText (udp_server_name_);
|
ui_->udp_server_line_edit->setText (udp_server_name_);
|
||||||
|
ui_->udp_server_line_edit->setEnabled(true);
|
||||||
on_udp_server_line_edit_editingFinished ();
|
on_udp_server_line_edit_editingFinished ();
|
||||||
ui_->udp_server_port_spin_box->setValue (udp_server_port_);
|
ui_->udp_server_port_spin_box->setValue (udp_server_port_);
|
||||||
load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_);
|
load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_);
|
||||||
@ -2538,6 +2540,28 @@ void Configuration::impl::on_udp_server_line_edit_textChanged (QString const&)
|
|||||||
|
|
||||||
void Configuration::impl::on_udp_server_line_edit_editingFinished ()
|
void Configuration::impl::on_udp_server_line_edit_editingFinished ()
|
||||||
{
|
{
|
||||||
|
if (this->isVisible())
|
||||||
|
{
|
||||||
|
int q1,q2,q3,q4;
|
||||||
|
char tmpbuf[2];
|
||||||
|
int n = sscanf(ui_->udp_server_line_edit->text ().trimmed ().toLatin1(), "%d.%d.%d.%d.%1s", &q1, &q2, &q3, &q4, tmpbuf);
|
||||||
|
const char *iperr;
|
||||||
|
switch(n)
|
||||||
|
{
|
||||||
|
case 0: iperr = "Error before first number";break;
|
||||||
|
case 1: iperr = "Error between first and second number";break;
|
||||||
|
case 2: iperr = "Error between second and third number";break;
|
||||||
|
case 3: iperr = "Error between third and fourth number";break;
|
||||||
|
case 4: iperr = ""; break;
|
||||||
|
case 5: iperr = "Invalid characters after IP address"; break;
|
||||||
|
default: iperr = "Unknown error parsing network address";
|
||||||
|
}
|
||||||
|
if (n != 4)
|
||||||
|
{
|
||||||
|
MessageBox::warning_message (this, tr ("Error in network address"), tr (iperr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (udp_server_name_edited_)
|
if (udp_server_name_edited_)
|
||||||
{
|
{
|
||||||
auto const& server = ui_->udp_server_line_edit->text ().trimmed ();
|
auto const& server = ui_->udp_server_line_edit->text ().trimmed ();
|
||||||
@ -2558,6 +2582,7 @@ void Configuration::impl::on_udp_server_line_edit_editingFinished ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Configuration::impl::host_info_results (QHostInfo host_info)
|
void Configuration::impl::host_info_results (QHostInfo host_info)
|
||||||
{
|
{
|
||||||
|
@ -137,6 +137,7 @@ void MessageClient::impl::host_info_results (QHostInfo host_info)
|
|||||||
if (QHostInfo::NoError != host_info.error ())
|
if (QHostInfo::NoError != host_info.error ())
|
||||||
{
|
{
|
||||||
Q_EMIT self_->error ("UDP server DNS lookup failed: " + host_info.errorString ());
|
Q_EMIT self_->error ("UDP server DNS lookup failed: " + host_info.errorString ());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -437,16 +437,15 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = commander_->readAll ();
|
QString result = commander_->readAll ();
|
||||||
// qDebug () << "result: " << result;
|
|
||||||
// for (int i = 0; i < result.size (); ++i)
|
|
||||||
// {
|
|
||||||
// qDebug () << i << ":" << hex << int (result[i]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
if (result != NULL)
|
||||||
|
{
|
||||||
CAT_TRACE (cmd << " -> " << QString {result});
|
CAT_TRACE (cmd << " -> " << QString {result});
|
||||||
return result; // converting raw UTF-8 bytes to QString
|
return result; // converting raw UTF-8 bytes to QString
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
bool DXLabSuiteCommanderTransceiver::write_to_port (QString const& s)
|
bool DXLabSuiteCommanderTransceiver::write_to_port (QString const& s)
|
||||||
{
|
{
|
||||||
|
@ -117,6 +117,10 @@ void PollingTransceiver::do_post_ptt (bool p)
|
|||||||
retries_ = polls_to_stabilize;
|
retries_ = polls_to_stabilize;
|
||||||
//retries_ = 0; // fast feedback on PTT
|
//retries_ = 0; // fast feedback on PTT
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_state_.ptt(p); // ensure this is initialized
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PollingTransceiver::do_pre_update ()
|
bool PollingTransceiver::do_pre_update ()
|
||||||
|
@ -72,7 +72,7 @@ set (UG_IMGS
|
|||||||
images/config-menu.png
|
images/config-menu.png
|
||||||
images/decode-menu.png
|
images/decode-menu.png
|
||||||
images/download_samples.png
|
images/download_samples.png
|
||||||
images/echo_144.png
|
images/Echo_1296.png
|
||||||
images/EME_Deep_0.png
|
images/EME_Deep_0.png
|
||||||
images/EME_Deep_1.png
|
images/EME_Deep_1.png
|
||||||
images/EME_Deep_2.png
|
images/EME_Deep_2.png
|
||||||
|
BIN
doc/user_guide/en/images/Echo_1296.png
Normal file
BIN
doc/user_guide/en/images/Echo_1296.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 177 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
@ -70,7 +70,8 @@ provides a mapping facility, archival storage, and many other
|
|||||||
features.
|
features.
|
||||||
|
|
||||||
*Echo* mode allows you to detect and measure your own station's echoes
|
*Echo* mode allows you to detect and measure your own station's echoes
|
||||||
from the moon, even if they are far below the audible threshold.
|
from the moon and to make other measurements useful for optimizing
|
||||||
|
your EME station's performance.
|
||||||
|
|
||||||
_WSJT-X_ provides spectral displays for receiver passbands as wide as
|
_WSJT-X_ provides spectral displays for receiver passbands as wide as
|
||||||
5 kHz, flexible rig control for nearly all modern radios used by
|
5 kHz, flexible rig control for nearly all modern radios used by
|
||||||
|
@ -15,10 +15,11 @@ that station.
|
|||||||
of situations with available _a priori_ (AP) information.
|
of situations with available _a priori_ (AP) information.
|
||||||
|
|
||||||
- *Echo* mode now offers a *Clear Avg* button and produces reliable
|
- *Echo* mode now offers a *Clear Avg* button and produces reliable
|
||||||
measurements of SNR even when Doppler spread is large. The *Measure*
|
measurements of SNR even when Doppler spread is large. Its *Monitor*
|
||||||
function can be used to measure SNR for a received unmodulated carrier
|
function can be used to measure SNR for a received unmodulated
|
||||||
-- for example, a key-down test signal emitted by another station and
|
carrier such as a key-down test signal emitted by another station and
|
||||||
reflected from the Moon.
|
reflected from the Moon, and to measure Sun, Moon, and ground noise as
|
||||||
|
aids for optimizing an EME station's performance.
|
||||||
|
|
||||||
- New buttons on the main window allow quick changes between modes
|
- New buttons on the main window allow quick changes between modes
|
||||||
FT4, FT8, MSK144, Q65, and JT65. Another new button allows toggling
|
FT4, FT8, MSK144, Q65, and JT65. Another new button allows toggling
|
||||||
|
@ -280,37 +280,43 @@ being readable by anyone listening in.
|
|||||||
|
|
||||||
=== Echo Mode
|
=== Echo Mode
|
||||||
|
|
||||||
*Echo* mode allows you to make sensitive measurements of your own
|
*Echo* mode provides tools for two types of measurements: echoes of
|
||||||
lunar echoes even when they are too weak to be heard. Select *Echo*
|
your transmitted signal from the Moon, and broadband noise power
|
||||||
from the *Mode* menu, aim your antenna at the moon, pick a clear
|
received from the Sun, Moon, and possibly other sources including
|
||||||
frequency, and toggle click *Tx Enable*. _WSJT-X_ will then cycle
|
nearby ground. In each case the system noise temperature (noise power
|
||||||
through the following loop every 6 seconds:
|
referred to the antenna terminals, expressed in Kelvin degrees) serves
|
||||||
|
as the reference noise level. Such measurements are widely used for
|
||||||
|
optimizing a station's capabilities for Earth-Moon-Earth (EME)
|
||||||
|
communication.
|
||||||
|
|
||||||
1. Transmit a 1500 Hz fixed tone for 2.3 s
|
For lunar echoes, _WSJT_ generates short fixed-frequency transmissions
|
||||||
2. Wait about 0.2 s for start of the return echo
|
that alternate with reception intervals at the appropriate
|
||||||
3. Record the received signal for 2.3 s
|
Doppler-shifted frequency. With *Split Operation* set to *Rig* or
|
||||||
4. Analyze, average, and display the results
|
*Fake It* on the *Settings | Radio* tab, check *Doppler tracking* and
|
||||||
5. Repeat from step 1
|
*Own Echo* on the Astronomical Data window. Point your antenna at the
|
||||||
|
Moon and click *Enable Tx* on the main window to start a sequence of
|
||||||
|
echo measurements. Each cycle takes 6 seconds. If strong enough,
|
||||||
|
echoes will be visible in the waterfall. Their average spectrum will
|
||||||
|
be displayed in the Echo Graph window, and numerical parameters of the
|
||||||
|
measurements appear in the main window:
|
||||||
|
|
||||||
To make a sequence of echo tests:
|
image::Echo_1296.png[align="center",alt="Echo 144 MHz"]
|
||||||
|
|
||||||
- Select *Echo* from the *Mode* menu.
|
At the end of each echo cycle a line of data in the main text window
|
||||||
|
displays the following information:
|
||||||
|
|
||||||
- Check *Doppler tracking* and *Constant frequency on the Moon* on the
|
UTC Time in hhmmss format
|
||||||
Astronomical Data window.
|
Hour UTC in hours and decimal fraction
|
||||||
|
Level Relative received noise power (dB)
|
||||||
|
Doppler EME Doppler shift at center of lunar disk
|
||||||
|
Width EME Doppler spread over full lunar disk
|
||||||
|
N Number of accumulated echo or monitor cycles
|
||||||
|
Q Estimated quality of averaged data on a 0 – 10 scale
|
||||||
|
DF Offset of spectral peak from 1500 Hz
|
||||||
|
SNR Average signal-to-noise ratio (dB/2500 Hz)
|
||||||
|
dBerr Estimated uncertainty of SNR
|
||||||
|
|
||||||
- Be sure that your rig control has been set up for _Split Operation_,
|
... more to come ...
|
||||||
using either *Rig* or *Fake It* on the *Settings | Radio* tab.
|
|
||||||
|
|
||||||
- Click *Enable Tx* on the main window to start a sequence of 6-second
|
|
||||||
cycles.
|
|
||||||
|
|
||||||
- _WSJT-X_ calculates and compensates for Doppler shift automatically.
|
|
||||||
As shown in the screen shot below, when proper Doppler corrections
|
|
||||||
have been applied your return echo should always appear at the center
|
|
||||||
of the plot area on the Echo Graph window.
|
|
||||||
|
|
||||||
image::echo_144.png[align="center",alt="Echo 144 MHz"]
|
|
||||||
|
|
||||||
=== Tips for EME
|
=== Tips for EME
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
subroutine avecho(id2,ndop,nfrit,nauto,navg,nqual,f1,xlevel,snrdb, &
|
||||||
dfreq,width,bDiskData)
|
db_err,dfreq,width,bDiskData)
|
||||||
|
|
||||||
integer TXLENGTH
|
integer TXLENGTH
|
||||||
parameter (TXLENGTH=27648) !27*1024
|
parameter (TXLENGTH=27648) !27*1024
|
||||||
@ -8,6 +8,8 @@ subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
|||||||
integer*2 id2(34560) !Buffer for Rx data
|
integer*2 id2(34560) !Buffer for Rx data
|
||||||
real sa(NZ) !Avg spectrum relative to initial Doppler echo freq
|
real sa(NZ) !Avg spectrum relative to initial Doppler echo freq
|
||||||
real sb(NZ) !Avg spectrum with Dither and changing Doppler removed
|
real sb(NZ) !Avg spectrum with Dither and changing Doppler removed
|
||||||
|
real, dimension (:,:), allocatable :: sax
|
||||||
|
real, dimension (:,:), allocatable :: sbx
|
||||||
integer nsum !Number of integrations
|
integer nsum !Number of integrations
|
||||||
real dop0 !Doppler shift for initial integration (Hz)
|
real dop0 !Doppler shift for initial integration (Hz)
|
||||||
real dop !Doppler shift for current integration (Hz)
|
real dop !Doppler shift for current integration (Hz)
|
||||||
@ -20,7 +22,17 @@ subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
|||||||
equivalence (x,c),(ipk,ipkv)
|
equivalence (x,c),(ipk,ipkv)
|
||||||
common/echocom/nclearave,nsum,blue(NZ),red(NZ)
|
common/echocom/nclearave,nsum,blue(NZ),red(NZ)
|
||||||
common/echocom2/fspread_self,fspread_dx
|
common/echocom2/fspread_self,fspread_dx
|
||||||
save dop0,sa,sb
|
data navg0/-1/
|
||||||
|
save dop0,navg0,sax,sbx
|
||||||
|
|
||||||
|
if(navg.ne.navg0) then
|
||||||
|
if(allocated(sax)) deallocate(sax)
|
||||||
|
if(allocated(sbx)) deallocate(sbx)
|
||||||
|
allocate(sax(1:navg,1:NZ))
|
||||||
|
allocate(sbx(1:navg,1:NZ))
|
||||||
|
nsum=0
|
||||||
|
navg0=navg
|
||||||
|
endif
|
||||||
|
|
||||||
fspread=fspread_dx !### Use the predicted Doppler spread ###
|
fspread=fspread_dx !### Use the predicted Doppler spread ###
|
||||||
if(bDiskData) fspread=width
|
if(bDiskData) fspread=width
|
||||||
@ -44,8 +56,8 @@ subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
|||||||
if(nclearave.ne.0) nsum=0
|
if(nclearave.ne.0) nsum=0
|
||||||
if(nsum.eq.0) then
|
if(nsum.eq.0) then
|
||||||
dop0=dop !Remember the initial Doppler
|
dop0=dop !Remember the initial Doppler
|
||||||
sa=0. !Clear the average arrays
|
sax=0. !Clear the average arrays
|
||||||
sb=0.
|
sbx=0.
|
||||||
endif
|
endif
|
||||||
|
|
||||||
x(TXLENGTH+1:)=0.
|
x(TXLENGTH+1:)=0.
|
||||||
@ -67,10 +79,14 @@ subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
nsum=nsum+1
|
nsum=nsum+1
|
||||||
|
j=mod(nsum-1,navg)+1
|
||||||
do i=1,NZ
|
do i=1,NZ
|
||||||
sa(i)=sa(i) + s(ia+i-2048) !Center at initial doppler freq
|
sax(j,i)=s(ia+i-2048) !Center at initial doppler freq
|
||||||
sb(i)=sb(i) + s(ib+i-2048) !Center at expected echo freq
|
sbx(j,i)=s(ib+i-2048) !Center at expected echo freq
|
||||||
|
sa(i)=sum(sax(1:navg,i))
|
||||||
|
sb(i)=sum(sbx(1:navg,i))
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
call echo_snr(sa,sb,fspread,blue,red,snrdb,db_err,dfreq,snr_detect)
|
call echo_snr(sa,sb,fspread,blue,red,snrdb,db_err,dfreq,snr_detect)
|
||||||
nqual=snr_detect-2
|
nqual=snr_detect-2
|
||||||
if(nqual.lt.0) nqual=0
|
if(nqual.lt.0) nqual=0
|
||||||
@ -87,12 +103,17 @@ subroutine avecho(id2,ndop,nfrit,nauto,nqual,f1,xlevel,snrdb,db_err, &
|
|||||||
call smo121(blue,NZ)
|
call smo121(blue,NZ)
|
||||||
enddo
|
enddo
|
||||||
|
|
||||||
ia=200.0/df
|
ia=50.0/df
|
||||||
ib=400.0/df
|
ib=250.0/df
|
||||||
call pctile(red(ia:ib),ib-ia+1,50,bred)
|
call pctile(red(ia:ib),ib-ia+1,50,bred1)
|
||||||
red=red-bred
|
call pctile(blue(ia:ib),ib-ia+1,50,bblue1)
|
||||||
call pctile(blue(ia:ib),ib-ia+1,50,bblue)
|
ia=1250.0/df
|
||||||
blue=blue-bblue
|
ib=1450.0/df
|
||||||
|
call pctile(red(ia:ib),ib-ia+1,50,bred2)
|
||||||
|
call pctile(blue(ia:ib),ib-ia+1,50,bblue2)
|
||||||
|
|
||||||
|
red=red-0.5*(bred1+bred2)
|
||||||
|
blue=blue-0.5*(bblue1+bblue2)
|
||||||
|
|
||||||
900 call sleep_msec(10) !Avoid the "blue Decode button" syndrome
|
900 call sleep_msec(10) !Avoid the "blue Decode button" syndrome
|
||||||
return
|
return
|
||||||
|
@ -8,7 +8,7 @@ program echosim
|
|||||||
character arg*12,fname*17
|
character arg*12,fname*17
|
||||||
complex c0(0:NMAX-1)
|
complex c0(0:NMAX-1)
|
||||||
complex c(0:NMAX-1)
|
complex c(0:NMAX-1)
|
||||||
! complex cwave(0:NWAVE-1)
|
real*4 level_1,level_2
|
||||||
real*8 f0,dt,twopi,phi,dphi
|
real*8 f0,dt,twopi,phi,dphi
|
||||||
real wave(NZ)
|
real wave(NZ)
|
||||||
integer*2 iwave(NZ) !Generated full-length waveform
|
integer*2 iwave(NZ) !Generated full-length waveform
|
||||||
@ -20,9 +20,11 @@ program echosim
|
|||||||
|
|
||||||
! Get command-line argument(s)
|
! Get command-line argument(s)
|
||||||
nargs=iargc()
|
nargs=iargc()
|
||||||
if(nargs.ne.5) then
|
if(nargs.ne.3 .and. nargs.ne.5) then
|
||||||
print*,'Usage: echosim f0 fdop fspread nfiles snr'
|
print*,'Usage 1: echosim f0 fdop fspread nfiles snr'
|
||||||
print*,'Examples: echosim 1500 0.0 4.0 10 -22'
|
print*,'Example: echosim 1500 0.0 4.0 10 -22'
|
||||||
|
print*,'Usage 2: echosim level_1 level_2 nfiles'
|
||||||
|
print*,'Example: echosim 30.0 40.0 100'
|
||||||
go to 999
|
go to 999
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -32,12 +34,21 @@ program echosim
|
|||||||
read(arg,*) fdop !Doppler shift (Hz)
|
read(arg,*) fdop !Doppler shift (Hz)
|
||||||
call getarg(3,arg)
|
call getarg(3,arg)
|
||||||
read(arg,*) fspread !Frequency spread (Hz) (JHT Lorentzian model)
|
read(arg,*) fspread !Frequency spread (Hz) (JHT Lorentzian model)
|
||||||
|
|
||||||
|
if(nargs.eq.3) then
|
||||||
|
level_1=f0
|
||||||
|
level_2=fdop
|
||||||
|
nfiles=fspread
|
||||||
|
snrdb=0.
|
||||||
|
go to 10
|
||||||
|
endif
|
||||||
|
|
||||||
call getarg(4,arg)
|
call getarg(4,arg)
|
||||||
read(arg,*) nfiles !Number of files
|
read(arg,*) nfiles !Number of files
|
||||||
call getarg(5,arg)
|
call getarg(5,arg)
|
||||||
read(arg,*) snrdb !SNR_2500
|
read(arg,*) snrdb !SNR_2500
|
||||||
|
|
||||||
twopi=8.d0*atan(1.d0)
|
10 twopi=8.d0*atan(1.d0)
|
||||||
fs=12000.0 !Sample rate (Hz)
|
fs=12000.0 !Sample rate (Hz)
|
||||||
dt=1.d0/fs !Sample interval (s)
|
dt=1.d0/fs !Sample interval (s)
|
||||||
bandwidth_ratio=2500.0/(fs/2.0)
|
bandwidth_ratio=2500.0/(fs/2.0)
|
||||||
@ -49,6 +60,9 @@ program echosim
|
|||||||
1000 format(' N f0 fDop fSpread SNR File name'/51('-'))
|
1000 format(' N f0 fDop fSpread SNR File name'/51('-'))
|
||||||
|
|
||||||
do ifile=1,nfiles
|
do ifile=1,nfiles
|
||||||
|
wave=0.
|
||||||
|
|
||||||
|
if(nargs.eq.5) then
|
||||||
phi=0.d0
|
phi=0.d0
|
||||||
do i=0,NWAVE-1
|
do i=0,NWAVE-1
|
||||||
phi=phi + dphi
|
phi=phi + dphi
|
||||||
@ -61,6 +75,8 @@ program echosim
|
|||||||
c=sig*c0
|
c=sig*c0
|
||||||
wave(1:NWAVE)=imag(c(1:NWAVE))
|
wave(1:NWAVE)=imag(c(1:NWAVE))
|
||||||
peak=maxval(abs(wave))
|
peak=maxval(abs(wave))
|
||||||
|
endif
|
||||||
|
|
||||||
if(snrdb.lt.90) then
|
if(snrdb.lt.90) then
|
||||||
do i=1,NWAVE !Add gaussian noise at specified SNR
|
do i=1,NWAVE !Add gaussian noise at specified SNR
|
||||||
xnoise=gran()
|
xnoise=gran()
|
||||||
@ -73,6 +89,10 @@ program echosim
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
gain=100.0
|
gain=100.0
|
||||||
|
if(nargs.eq.3) then
|
||||||
|
gain=10.0**(0.05*level_1)
|
||||||
|
if(mod((ifile-1)/10,2).eq.1) gain=10.0**(0.05*level_2)
|
||||||
|
endif
|
||||||
if(snrdb.lt.90.0) then
|
if(snrdb.lt.90.0) then
|
||||||
wave=gain*wave
|
wave=gain*wave
|
||||||
else
|
else
|
||||||
|
@ -586,13 +586,26 @@ contains
|
|||||||
xsig=xsig+s4(itone(i),i)
|
xsig=xsig+s4(itone(i),i)
|
||||||
enddo
|
enddo
|
||||||
base=candidates(icand,5)
|
base=candidates(icand,5)
|
||||||
arg=600.0*(xsig/base)-1.0
|
select case(ntrperiod)
|
||||||
|
case(15)
|
||||||
|
snr_calfac=800.0
|
||||||
|
case(30)
|
||||||
|
snr_calfac=600.0
|
||||||
|
case(60)
|
||||||
|
snr_calfac=430.0
|
||||||
|
case(120)
|
||||||
|
snr_calfac=390.0
|
||||||
|
case(300)
|
||||||
|
snr_calfac=340.0
|
||||||
|
case(900)
|
||||||
|
snr_calfac=320.0
|
||||||
|
case(1800)
|
||||||
|
snr_calfac=320.0
|
||||||
|
case default
|
||||||
|
end select
|
||||||
|
arg=snr_calfac*xsig/base - 1.0
|
||||||
if(arg.gt.0.0) then
|
if(arg.gt.0.0) then
|
||||||
xsnr=10*log10(arg)-35.5-12.5*log10(nsps/8200.0)
|
xsnr=10*log10(arg)+10*log10(1.46/2500)+10*log10(8200.0/nsps)
|
||||||
if(ntrperiod.eq. 15) xsnr=xsnr+2
|
|
||||||
if(ntrperiod.eq. 30) xsnr=xsnr+1
|
|
||||||
if(ntrperiod.eq. 900) xsnr=xsnr+1
|
|
||||||
if(ntrperiod.eq.1800) xsnr=xsnr+2
|
|
||||||
else
|
else
|
||||||
xsnr=-99.9
|
xsnr=-99.9
|
||||||
endif
|
endif
|
||||||
|
@ -287,6 +287,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
|
|||||||
! 5 : WW_DIGI
|
! 5 : WW_DIGI
|
||||||
! 6 : FOX
|
! 6 : FOX
|
||||||
! 7 : HOUND
|
! 7 : HOUND
|
||||||
|
! 8 : ARRL_DIGI
|
||||||
!
|
!
|
||||||
! Conditions that cause us to bail out of AP decoding
|
! Conditions that cause us to bail out of AP decoding
|
||||||
if(ncontest.le.5 .and. iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
if(ncontest.le.5 .and. iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
||||||
@ -306,6 +307,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
|
|||||||
if(ncontest.eq.4) llrz(1:29)=apmag*mcqru(1:29)
|
if(ncontest.eq.4) llrz(1:29)=apmag*mcqru(1:29)
|
||||||
if(ncontest.eq.5) llrz(1:29)=apmag*mcqww(1:29)
|
if(ncontest.eq.5) llrz(1:29)=apmag*mcqww(1:29)
|
||||||
if(ncontest.eq.7) llrz(1:29)=apmag*mcq(1:29)
|
if(ncontest.eq.7) llrz(1:29)=apmag*mcq(1:29)
|
||||||
|
if(ncontest.eq.8) llrz(1:29)=apmag*mcqtest(1:29)
|
||||||
apmask(75:77)=1
|
apmask(75:77)=1
|
||||||
llrz(75:76)=apmag*(-1)
|
llrz(75:76)=apmag*(-1)
|
||||||
llrz(77)=apmag*(+1)
|
llrz(77)=apmag*(+1)
|
||||||
@ -313,7 +315,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
|
|||||||
|
|
||||||
if(iaptype.eq.2) then ! MyCall,???,???
|
if(iaptype.eq.2) then ! MyCall,???,???
|
||||||
apmask=0
|
apmask=0
|
||||||
if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.5) then
|
if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.5.or.ncontest.eq.8) then
|
||||||
apmask(1:29)=1
|
apmask(1:29)=1
|
||||||
llrz(1:29)=apmag*apsym(1:29)
|
llrz(1:29)=apmag*apsym(1:29)
|
||||||
apmask(75:77)=1
|
apmask(75:77)=1
|
||||||
@ -353,7 +355,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
|
|||||||
|
|
||||||
if(iaptype.eq.3) then ! MyCall,DxCall,???
|
if(iaptype.eq.3) then ! MyCall,DxCall,???
|
||||||
apmask=0
|
apmask=0
|
||||||
if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.2.or.ncontest.eq.5.or.ncontest.eq.7) then
|
if(ncontest.eq.0.or.ncontest.eq.1.or.ncontest.eq.2.or.ncontest.eq.5.or.ncontest.eq.7.or.ncontest.eq.8) then
|
||||||
apmask(1:58)=1
|
apmask(1:58)=1
|
||||||
llrz(1:58)=apmag*apsym
|
llrz(1:58)=apmag*apsym
|
||||||
apmask(75:77)=1
|
apmask(75:77)=1
|
||||||
@ -379,7 +381,7 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
|
|||||||
if(iaptype.eq.5.and.ncontest.eq.7) cycle !Hound
|
if(iaptype.eq.5.and.ncontest.eq.7) cycle !Hound
|
||||||
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
||||||
apmask=0
|
apmask=0
|
||||||
if(ncontest.le.5 .or. (ncontest.eq.7.and.iaptype.eq.6)) then
|
if(ncontest.le.5 .or. (ncontest.eq.7.and.iaptype.eq.6) .or. ncontest.eq.8) then
|
||||||
apmask(1:77)=1 ! mycall, hiscall, RRR|73|RR73
|
apmask(1:77)=1 ! mycall, hiscall, RRR|73|RR73
|
||||||
llrz(1:58)=apmag*apsym
|
llrz(1:58)=apmag*apsym
|
||||||
if(iaptype.eq.4) llrz(59:77)=apmag*mrrr
|
if(iaptype.eq.4) llrz(59:77)=apmag*mrrr
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,nzhsym,candidate, &
|
||||||
ncand,sbase)
|
ncand,sbase)
|
||||||
|
|
||||||
include 'ft8_params.f90'
|
include 'ft8_params.f90'
|
||||||
parameter (MAXPRECAND=500)
|
parameter (MAXPRECAND=1000)
|
||||||
! Search over +/- 2.5s relative to 0.5s TX start time.
|
! Maximum sync correlation lag +/- 2.5s relative to 0.5s TX start time.
|
||||||
|
! 2.5s / 0.16s/symbol * 4 samples/symbol = 62.5 lag steps in 2.5s
|
||||||
parameter (JZ=62)
|
parameter (JZ=62)
|
||||||
complex cx(0:NH1)
|
complex cx(0:NH1)
|
||||||
real s(NH1,NHSYM)
|
real s(NH1,NHSYM)
|
||||||
@ -12,11 +13,14 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
|||||||
real x(NFFT1)
|
real x(NFFT1)
|
||||||
real sync2d(NH1,-JZ:JZ)
|
real sync2d(NH1,-JZ:JZ)
|
||||||
real red(NH1)
|
real red(NH1)
|
||||||
|
real red2(NH1)
|
||||||
real candidate0(3,MAXPRECAND)
|
real candidate0(3,MAXPRECAND)
|
||||||
real candidate(3,maxcand)
|
real candidate(3,maxcand)
|
||||||
real dd(NMAX)
|
real dd(NMAX)
|
||||||
integer jpeak(NH1)
|
integer jpeak(NH1)
|
||||||
|
integer jpeak2(NH1)
|
||||||
integer indx(NH1)
|
integer indx(NH1)
|
||||||
|
integer indx2(NH1)
|
||||||
integer ii(1)
|
integer ii(1)
|
||||||
integer icos7(0:6)
|
integer icos7(0:6)
|
||||||
data icos7/3,1,4,0,6,5,2/ !Costas 7x7 tone pattern
|
data icos7/3,1,4,0,6,5,2/ !Costas 7x7 tone pattern
|
||||||
@ -82,11 +86,16 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
|||||||
enddo
|
enddo
|
||||||
|
|
||||||
red=0.
|
red=0.
|
||||||
|
red2=0.
|
||||||
|
mlag=10
|
||||||
|
mlag2=JZ
|
||||||
do i=ia,ib
|
do i=ia,ib
|
||||||
ii=maxloc(sync2d(i,-JZ:JZ)) - 1 - JZ
|
ii=maxloc(sync2d(i,-mlag:mlag)) - 1 - mlag
|
||||||
j0=ii(1)
|
jpeak(i)=ii(1)
|
||||||
jpeak(i)=j0
|
red(i)=sync2d(i,jpeak(i))
|
||||||
red(i)=sync2d(i,j0)
|
ii=maxloc(sync2d(i,-mlag2:mlag2)) - 1 - mlag2
|
||||||
|
jpeak2(i)=ii(1)
|
||||||
|
red2(i)=sync2d(i,jpeak2(i))
|
||||||
enddo
|
enddo
|
||||||
iz=ib-ia+1
|
iz=ib-ia+1
|
||||||
call indexx(red(ia:ib),iz,indx)
|
call indexx(red(ia:ib),iz,indx)
|
||||||
@ -100,14 +109,29 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
|||||||
if(ibase.gt.nh1) ibase=nh1
|
if(ibase.gt.nh1) ibase=nh1
|
||||||
base=red(ibase)
|
base=red(ibase)
|
||||||
red=red/base
|
red=red/base
|
||||||
|
call indexx(red2(ia:ib),iz,indx2)
|
||||||
|
ibase2=indx2(npctile) - 1 + ia
|
||||||
|
if(ibase2.lt.1) ibase2=1
|
||||||
|
if(ibase2.gt.nh1) ibase2=nh1
|
||||||
|
base2=red2(ibase2)
|
||||||
|
red2=red2/base2
|
||||||
do i=1,min(MAXPRECAND,iz)
|
do i=1,min(MAXPRECAND,iz)
|
||||||
n=ia + indx(iz+1-i) - 1
|
n=ia + indx(iz+1-i) - 1
|
||||||
if(red(n).lt.syncmin.or.isnan(red(n)).or.k.eq.MAXPRECAND) exit
|
if(k.ge.MAXPRECAND) exit
|
||||||
|
if( (red(n).ge.syncmin) .and. (.not.isnan(red(n))) ) then
|
||||||
k=k+1
|
k=k+1
|
||||||
candidate0(1,k)=n*df
|
candidate0(1,k)=n*df
|
||||||
candidate0(2,k)=(jpeak(n)-0.5)*tstep
|
candidate0(2,k)=(jpeak(n)-0.5)*tstep
|
||||||
candidate0(3,k)=red(n)
|
candidate0(3,k)=red(n)
|
||||||
|
endif
|
||||||
|
if(abs(jpeak2(n)-jpeak(n)).eq.0) cycle
|
||||||
|
if(k.ge.MAXPRECAND) exit
|
||||||
|
if( (red2(n).ge.syncmin) .and. (.not.isnan(red2(n))) ) then
|
||||||
|
k=k+1
|
||||||
|
candidate0(1,k)=n*df
|
||||||
|
candidate0(2,k)=(jpeak2(n)-0.5)*tstep
|
||||||
|
candidate0(3,k)=red2(n)
|
||||||
|
endif
|
||||||
enddo
|
enddo
|
||||||
ncand=k
|
ncand=k
|
||||||
|
|
||||||
@ -116,7 +140,8 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
|||||||
if(i.ge.2) then
|
if(i.ge.2) then
|
||||||
do j=1,i-1
|
do j=1,i-1
|
||||||
fdiff=abs(candidate0(1,i))-abs(candidate0(1,j))
|
fdiff=abs(candidate0(1,i))-abs(candidate0(1,j))
|
||||||
if(abs(fdiff).lt.4.0) then
|
tdiff=abs(candidate0(2,i)-candidate0(2,j))
|
||||||
|
if(abs(fdiff).lt.4.0.and.tdiff.lt.0.04) then
|
||||||
if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0.
|
if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0.
|
||||||
if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0.
|
if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0.
|
||||||
endif
|
endif
|
||||||
@ -148,6 +173,5 @@ subroutine sync8(dd,nfa,nfb,syncmin,nfqso,maxcand,s,candidate, &
|
|||||||
endif
|
endif
|
||||||
enddo
|
enddo
|
||||||
ncand=k-1
|
ncand=k-1
|
||||||
|
|
||||||
return
|
return
|
||||||
end subroutine sync8
|
end subroutine sync8
|
||||||
|
@ -44,7 +44,7 @@ contains
|
|||||||
|
|
||||||
class(ft8_decoder), intent(inout) :: this
|
class(ft8_decoder), intent(inout) :: this
|
||||||
procedure(ft8_decode_callback) :: callback
|
procedure(ft8_decode_callback) :: callback
|
||||||
parameter (MAXCAND=300,MAX_EARLY=100)
|
parameter (MAXCAND=600,MAX_EARLY=100)
|
||||||
real*8 tsec,tseq
|
real*8 tsec,tseq
|
||||||
real s(NH1,NHSYM)
|
real s(NH1,NHSYM)
|
||||||
real sbase(NH1)
|
real sbase(NH1)
|
||||||
@ -80,7 +80,9 @@ contains
|
|||||||
dt0=0.
|
dt0=0.
|
||||||
f0=0.
|
f0=0.
|
||||||
endif
|
endif
|
||||||
if(nutc.ne.nutc0) then
|
!Added 41==nzhsym to force a reset if the same wav file is processed twice or more in a row,
|
||||||
|
!in which case nutc.eq.nutc0 and ndec(jseq,1) doesn't get reset
|
||||||
|
if(nzhsym==41 .or. (nutc.ne.nutc0)) then
|
||||||
! New UTC. Move previously saved 'a7' data from k=1 to k=0
|
! New UTC. Move previously saved 'a7' data from k=1 to k=0
|
||||||
iz=ndec(jseq,1)
|
iz=ndec(jseq,1)
|
||||||
dt0(1:iz,jseq,0) = dt0(1:iz,jseq,1)
|
dt0(1:iz,jseq,0) = dt0(1:iz,jseq,1)
|
||||||
@ -107,6 +109,7 @@ contains
|
|||||||
dd=iwave
|
dd=iwave
|
||||||
dd1=dd
|
dd1=dd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if(nzhsym.eq.41) then
|
if(nzhsym.eq.41) then
|
||||||
ndecodes=0
|
ndecodes=0
|
||||||
allmessages=' '
|
allmessages=' '
|
||||||
@ -114,10 +117,12 @@ contains
|
|||||||
else
|
else
|
||||||
ndecodes=ndec_early
|
ndecodes=ndec_early
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if(nzhsym.eq.47 .and. ndec_early.eq.0) then
|
if(nzhsym.eq.47 .and. ndec_early.eq.0) then
|
||||||
dd1=dd
|
dd1=dd
|
||||||
go to 800
|
go to 800
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if(nzhsym.eq.47 .and. ndec_early.ge.1) then
|
if(nzhsym.eq.47 .and. ndec_early.ge.1) then
|
||||||
lsubtracted=.false.
|
lsubtracted=.false.
|
||||||
lrefinedt=.true.
|
lrefinedt=.true.
|
||||||
@ -140,6 +145,7 @@ contains
|
|||||||
dd1=dd
|
dd1=dd
|
||||||
go to 900
|
go to 900
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if(nzhsym.eq.50 .and. ndec_early.ge.1 .and. .not.nagain) then
|
if(nzhsym.eq.50 .and. ndec_early.ge.1 .and. .not.nagain) then
|
||||||
n=47*3456
|
n=47*3456
|
||||||
dd(1:n)=dd1(1:n)
|
dd(1:n)=dd1(1:n)
|
||||||
@ -151,6 +157,7 @@ contains
|
|||||||
enddo
|
enddo
|
||||||
call timer('sub_ft8c',1)
|
call timer('sub_ft8c',1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifa=nfa
|
ifa=nfa
|
||||||
ifb=nfb
|
ifb=nfb
|
||||||
if(nzhsym.eq.50 .and. nagain) then
|
if(nzhsym.eq.50 .and. nagain) then
|
||||||
@ -164,11 +171,12 @@ contains
|
|||||||
! ndepth=2: subtraction, 3 passes, bp+osd (no subtract refinement)
|
! ndepth=2: subtraction, 3 passes, bp+osd (no subtract refinement)
|
||||||
! ndepth=3: subtraction, 3 passes, bp+osd
|
! ndepth=3: subtraction, 3 passes, bp+osd
|
||||||
npass=3
|
npass=3
|
||||||
if(ndepth.eq.1) npass=1
|
if(ndepth.eq.1) npass=2
|
||||||
do ipass=1,npass
|
do ipass=1,npass
|
||||||
newdat=.true.
|
newdat=.true.
|
||||||
syncmin=1.3
|
syncmin=1.3
|
||||||
if(ndepth.le.2) syncmin=1.6
|
if(ndepth.le.2) syncmin=1.6
|
||||||
|
if(nzhsym.eq.41) syncmin=2.0
|
||||||
if(ipass.eq.1) then
|
if(ipass.eq.1) then
|
||||||
lsubtract=.true.
|
lsubtract=.true.
|
||||||
ndeep=ndepth
|
ndeep=ndepth
|
||||||
@ -185,7 +193,7 @@ contains
|
|||||||
endif
|
endif
|
||||||
call timer('sync8 ',0)
|
call timer('sync8 ',0)
|
||||||
maxc=MAXCAND
|
maxc=MAXCAND
|
||||||
call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,s,candidate, &
|
call sync8(dd,ifa,ifb,syncmin,nfqso,maxc,nzhsym,candidate, &
|
||||||
ncand,sbase)
|
ncand,sbase)
|
||||||
call timer('sync8 ',1)
|
call timer('sync8 ',1)
|
||||||
do icand=1,ncand
|
do icand=1,ncand
|
||||||
@ -221,10 +229,6 @@ contains
|
|||||||
if(emedelay.ne.0) xdt=xdt+2.0
|
if(emedelay.ne.0) xdt=xdt+2.0
|
||||||
call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual)
|
call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual)
|
||||||
call ft8_a7_save(nutc,xdt,f1,msg37) !Enter decode in table
|
call ft8_a7_save(nutc,xdt,f1,msg37) !Enter decode in table
|
||||||
! ii=ndec(jseq,1)
|
|
||||||
! write(41,3041) jseq,ii,nint(f0(ii,jseq,0)),msg0(ii,jseq,0)(1:22),&
|
|
||||||
! nint(f0(ii,jseq,1)),msg0(ii,jseq,1)(1:22)
|
|
||||||
!3041 format(3i5,2x,a22,i5,2x,a22)
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
call timestamp(tsec,tseq,ctime)
|
call timestamp(tsec,tseq,ctime)
|
||||||
@ -237,7 +241,7 @@ contains
|
|||||||
if(nzhsym.lt.50) ndec_early=ndecodes
|
if(nzhsym.lt.50) ndec_early=ndecodes
|
||||||
|
|
||||||
900 continue
|
900 continue
|
||||||
if(nzhsym.eq.50 .and. ndec(jseq,0).ge.1) then
|
if(lft8apon .and. ncontest.ne.6 .and. ncontest.ne.7 .and. nzhsym.eq.50 .and. ndec(jseq,0).ge.1) then
|
||||||
newdat=.true.
|
newdat=.true.
|
||||||
do i=1,ndec(jseq,0)
|
do i=1,ndec(jseq,0)
|
||||||
if(f0(i,jseq,0).eq.-99.0) exit
|
if(f0(i,jseq,0).eq.-99.0) exit
|
||||||
|
@ -55,6 +55,7 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if(k.lt.k0) then !Start a new data block
|
if(k.lt.k0) then !Start a new data block
|
||||||
|
k0=0
|
||||||
ja=0
|
ja=0
|
||||||
ssum=0.
|
ssum=0.
|
||||||
ihsym=0
|
ihsym=0
|
||||||
@ -64,11 +65,8 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
|
|||||||
sq=0.
|
sq=0.
|
||||||
pxmax=0.;
|
pxmax=0.;
|
||||||
|
|
||||||
! dwell_time=0.0001
|
|
||||||
! if(k.gt.k0 .and. npct.gt.0) call blanker(shared_data%id2(k0+1:k), &
|
|
||||||
! k-k0,dwell_time,npct)
|
|
||||||
|
|
||||||
do i=k0+1,k
|
do i=k0+1,k
|
||||||
|
if(k0.eq.0 .and. i.le.10) cycle
|
||||||
x1=shared_data%id2(i)
|
x1=shared_data%id2(i)
|
||||||
if (abs(x1).gt.pxmax) pxmax = abs(x1);
|
if (abs(x1).gt.pxmax) pxmax = abs(x1);
|
||||||
sq=sq + x1*x1
|
sq=sq + x1*x1
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
program testfast9
|
program testfast9
|
||||||
|
|
||||||
parameter (NMAX=359424)
|
parameter (NMAX=30*12000)
|
||||||
integer*2 id2(NMAX)
|
integer*2 id2(NMAX)
|
||||||
integer narg(0:11)
|
integer narg(0:11)
|
||||||
character*80 line(100)
|
character*80 line(100)
|
||||||
@ -9,7 +9,7 @@ program testfast9
|
|||||||
nargs=iargc()
|
nargs=iargc()
|
||||||
if(nargs.ne.2) then
|
if(nargs.ne.2) then
|
||||||
print*,'Usage: testfast9 submode infile'
|
print*,'Usage: testfast9 submode infile'
|
||||||
print*,'Example: testfast9 E /data/VE1SKY/K1JT/JT9E/150806_123300.wav'
|
print*,'Example: testfast9 E 150806_123300.wav'
|
||||||
go to 999
|
go to 999
|
||||||
endif
|
endif
|
||||||
call getarg(1,submode)
|
call getarg(1,submode)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "SettingsGroup.hpp"
|
#include "SettingsGroup.hpp"
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void astrosub_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
|
void astrosub_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
|
||||||
@ -44,7 +45,7 @@ Astro::~Astro()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
||||||
int fQSO, int nsetftx, int ntxFreq, QString azelDir)
|
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg)
|
||||||
{
|
{
|
||||||
static int ntxFreq0=-99;
|
static int ntxFreq0=-99;
|
||||||
char cc[300];
|
char cc[300];
|
||||||
@ -86,6 +87,65 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
|||||||
ntsky,xnr,dgrd);
|
ntsky,xnr,dgrd);
|
||||||
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
|
ui->astroTextBrowser->setText(" "+ date + "\nUTC: " + utc + "\n" + cc);
|
||||||
|
|
||||||
|
double azOffset=0.0;
|
||||||
|
double elOffset=0.0;
|
||||||
|
double rad=57.2957795131;
|
||||||
|
int iCycle=2;
|
||||||
|
// Are we doing pointing tests?
|
||||||
|
bool bPointing=ui->cbPointingTests->isChecked();
|
||||||
|
ui->gbPointing->setVisible(bPointing);
|
||||||
|
if(bPointing) {
|
||||||
|
int nDwell=int(ui->sbDwell->value());
|
||||||
|
if(ui->cbAutoCycle->isChecked()) {
|
||||||
|
iCycle=(t.currentSecsSinceEpoch()%(6*nDwell))/nDwell + 1;
|
||||||
|
if(iCycle==1) {
|
||||||
|
azOffset = -ui->sbOffset->value()/cos(elsun/rad);
|
||||||
|
ui->rb1->setChecked(true);
|
||||||
|
}
|
||||||
|
if(iCycle==2 or iCycle==5) {
|
||||||
|
ui->rb2->setChecked(true);
|
||||||
|
}
|
||||||
|
if(iCycle==3) {
|
||||||
|
azOffset = +ui->sbOffset->value()/cos(elsun/rad);
|
||||||
|
ui->rb3->setChecked(true);
|
||||||
|
}
|
||||||
|
if(iCycle==4) {
|
||||||
|
elOffset = -ui->sbOffset->value();
|
||||||
|
ui->rb4->setChecked(true);
|
||||||
|
}
|
||||||
|
if(iCycle==6) {
|
||||||
|
elOffset = +ui->sbOffset->value();
|
||||||
|
ui->rb6->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ui->cbOnOff->isChecked()) {
|
||||||
|
iCycle=(t.currentSecsSinceEpoch()%(2*nDwell))/nDwell + 1;
|
||||||
|
if(iCycle==1) {
|
||||||
|
azOffset = -ui->sbOffset->value()/cos(elsun/rad);
|
||||||
|
ui->rb1->setChecked(true);
|
||||||
|
}
|
||||||
|
if(iCycle==2) {
|
||||||
|
ui->rb2->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ui->cbAutoCycle->isChecked() or ui->cbOnOff->isChecked()) {
|
||||||
|
QFile f("pointing.out");
|
||||||
|
if(f.open(QIODevice::WriteOnly | QIODevice::Append)) {
|
||||||
|
QTextStream out(&f);
|
||||||
|
out << t.toString("yyyy-MMM-dd hh:mm:ss");
|
||||||
|
sprintf(cc,"%7.1f %7.1f %d %7.1f %7.1f %10.1f %7.2f\n",
|
||||||
|
azsun,elsun,iCycle,azOffset,elOffset,xavg,10.0*log10(xavg));
|
||||||
|
out << cc;
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui->rb2->setChecked(true);
|
||||||
|
ui->cbAutoCycle->setChecked(false);
|
||||||
|
ui->cbOnOff->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write pointing data to azel.dat
|
||||||
QString fname=azelDir+"/azel.dat";
|
QString fname=azelDir+"/azel.dat";
|
||||||
QFile f(fname);
|
QFile f(fname);
|
||||||
if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if(!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
@ -107,7 +167,7 @@ void Astro::astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
|||||||
"%3d,%1d,fQSO\n"
|
"%3d,%1d,fQSO\n"
|
||||||
"%3d,%1d,fQSO2\n",
|
"%3d,%1d,fQSO2\n",
|
||||||
nhr,nmin,isec,azmoon,elmoon,
|
nhr,nmin,isec,azmoon,elmoon,
|
||||||
nhr,nmin,isec,azsun,elsun,
|
nhr,nmin,isec,azsun+azOffset,elsun+elOffset,
|
||||||
nhr,nmin,isec,0.0,0.0,
|
nhr,nmin,isec,0.0,0.0,
|
||||||
nfreq,ndop,ndop00,
|
nfreq,ndop,ndop00,
|
||||||
fQSO,nsetftx,
|
fQSO,nsetftx,
|
||||||
@ -120,3 +180,14 @@ void Astro::setFontSize(int n)
|
|||||||
{
|
{
|
||||||
ui->astroTextBrowser->setFontPointSize(n);
|
ui->astroTextBrowser->setFontPointSize(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Astro::on_cbAutoCycle_clicked(bool checked)
|
||||||
|
{
|
||||||
|
if(checked) ui->cbOnOff->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Astro::on_cbOnOff_clicked(bool checked)
|
||||||
|
{
|
||||||
|
if(checked) ui->cbAutoCycle->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -15,10 +15,14 @@ class Astro : public QWidget
|
|||||||
public:
|
public:
|
||||||
explicit Astro (QString const& settings_filename, QWidget *parent = 0);
|
explicit Astro (QString const& settings_filename, QWidget *parent = 0);
|
||||||
void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
void astroUpdate(QDateTime t, QString mygrid, QString hisgrid,
|
||||||
int fQSO, int nsetftx, int ntxFreq, QString azelDir);
|
int fQSO, int nsetftx, int ntxFreq, QString azelDir, double xavg);
|
||||||
void setFontSize(int n);
|
void setFontSize(int n);
|
||||||
~Astro ();
|
~Astro ();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_cbOnOff_clicked(bool checked);
|
||||||
|
void on_cbAutoCycle_clicked(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::Astro *ui;
|
Ui::Astro *ui;
|
||||||
QString m_settings_filename;
|
QString m_settings_filename;
|
||||||
|
220
map65/astro.ui
220
map65/astro.ui
@ -6,22 +6,194 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>262</width>
|
<width>441</width>
|
||||||
<height>483</height>
|
<height>483</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QTextBrowser" name="astroTextBrowser">
|
<widget class="QGroupBox" name="gbPointing">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>269</x>
|
||||||
|
<y>19</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>431</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<widget class="QRadioButton" name="rb1">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>100</y>
|
||||||
|
<width>30</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QRadioButton" name="rb2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>100</y>
|
||||||
|
<width>40</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>2, 5</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QRadioButton" name="rb3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>110</x>
|
||||||
|
<y>100</y>
|
||||||
|
<width>30</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>3</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QRadioButton" name="rb4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>150</y>
|
||||||
|
<width>30</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QRadioButton" name="rb6">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>30</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>6</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QDoubleSpinBox" name="sbOffset">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>Offset </string>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> deg</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>0.500000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>20.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<double>0.500000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>2.500000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="cbAutoCycle">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>330</y>
|
||||||
|
<width>91</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Auto Cycle</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QCheckBox" name="cbOnOff">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>380</y>
|
||||||
|
<width>70</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>On Off</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSpinBox" name="sbDwell">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>280</y>
|
||||||
|
<width>130</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="suffix">
|
||||||
|
<string> s</string>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>Dwell </string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>300</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>256</width>
|
<width>258</width>
|
||||||
<height>451</height>
|
<height>471</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTextBrowser" name="astroTextBrowser">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<family>Courier New</family>
|
<family>Courier New</family>
|
||||||
@ -31,6 +203,46 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbPointingTests">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pointing Tests</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@ -14,6 +14,7 @@ subroutine decode0(dd,ss,savg,nstandalone)
|
|||||||
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
|
mcall3,nkeep,ntol,nxant,nrxlog,nfsample,nxpol,nmode, &
|
||||||
nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
|
nfast,nsave,max_drift,nhsym,mycall,mygrid,hiscall,hisgrid,datetime
|
||||||
common/early/nhsym1,nhsym2,ldecoded(32768)
|
common/early/nhsym1,nhsym2,ldecoded(32768)
|
||||||
|
common/decodes/ndecodes
|
||||||
data neme0/-99/,mcall3b/1/
|
data neme0/-99/,mcall3b/1/
|
||||||
save
|
save
|
||||||
|
|
||||||
@ -62,8 +63,8 @@ subroutine decode0(dd,ss,savg,nstandalone)
|
|||||||
call sec0(1,tdec)
|
call sec0(1,tdec)
|
||||||
if(nhsym.eq.nhsym1) write(*,1010) nsum,nsave,nstandalone,nhsym,tdec
|
if(nhsym.eq.nhsym1) write(*,1010) nsum,nsave,nstandalone,nhsym,tdec
|
||||||
1010 format('<EarlyFinished>',3i4,i6,f6.2)
|
1010 format('<EarlyFinished>',3i4,i6,f6.2)
|
||||||
if(nhsym.eq.nhsym2) write(*,1012) nsum,nsave,nstandalone,nhsym,tdec
|
if(nhsym.eq.nhsym2) write(*,1012) nsum,nsave,nstandalone,nhsym,tdec,ndecodes
|
||||||
1012 format('<DecodeFinished>',3i4,i6,f6.2)
|
1012 format('<DecodeFinished>',3i4,i6,f6.2,i5)
|
||||||
flush(6)
|
flush(6)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -34,12 +34,15 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
|
|||||||
common/c3com/ mcall3a
|
common/c3com/ mcall3a
|
||||||
common/testcom/ifreq
|
common/testcom/ifreq
|
||||||
common/early/nhsym1,nhsym2,ldecoded(32768)
|
common/early/nhsym1,nhsym2,ldecoded(32768)
|
||||||
|
common/decodes/ndecodes
|
||||||
|
|
||||||
data blank/' '/,cm/'#'/
|
data blank/' '/,cm/'#'/
|
||||||
data shmsg0/'ATT','RO ','RRR','73 '/
|
data shmsg0/'ATT','RO ','RRR','73 '/
|
||||||
data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/
|
data nfile/0/,nutc0/-999/,nid/0/,ip000/1/,ip001/1/,mousefqso0/-999/
|
||||||
save
|
save
|
||||||
|
|
||||||
|
ndecodes=0
|
||||||
|
|
||||||
! Clean start for Q65 at early decode
|
! Clean start for Q65 at early decode
|
||||||
if(nhsym.eq.nhsym1 .or. nagain.ne.0) ldecoded=.false.
|
if(nhsym.eq.nhsym1 .or. nagain.ne.0) ldecoded=.false.
|
||||||
if(ndiskdat.eq.1) ldecoded=.false.
|
if(ndiskdat.eq.1) ldecoded=.false.
|
||||||
@ -50,7 +53,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
|
|||||||
mode65=mod(nmode,10)
|
mode65=mod(nmode,10)
|
||||||
if(mode65.eq.3) mode65=4
|
if(mode65.eq.3) mode65=4
|
||||||
mode_q65=nmode/10
|
mode_q65=nmode/10
|
||||||
nts_jt65=2**(mode65-1) !JT65 tone separation factor
|
nts_jt65=mode65 !JT65 tone separation factor
|
||||||
nts_q65=2**(mode_q65-1) !Q65 tone separation factor
|
nts_q65=2**(mode_q65-1) !Q65 tone separation factor
|
||||||
xpol=(nxpol.ne.0)
|
xpol=(nxpol.ne.0)
|
||||||
|
|
||||||
@ -158,7 +161,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
|
|||||||
ssmax=1.e30
|
ssmax=1.e30
|
||||||
call ccf65(ss(1,1,i),nhsym,ssmax,sync1,ipol,jpz,dt, &
|
call ccf65(ss(1,1,i),nhsym,ssmax,sync1,ipol,jpz,dt, &
|
||||||
flipk,syncshort,snr2,ipol2,dt2)
|
flipk,syncshort,snr2,ipol2,dt2)
|
||||||
if(dt.lt.-2.6 .or. dt.gt.2.5) sync1=-99.0 !###
|
!### if(dt.lt.-2.6 .or. dt.gt.2.5) sync1=-99.0 !###
|
||||||
call timer('ccf65 ',1)
|
call timer('ccf65 ',1)
|
||||||
if(mode65.eq.0) syncshort=-99.0 !If "No JT65", don't waste time
|
if(mode65.eq.0) syncshort=-99.0 !If "No JT65", don't waste time
|
||||||
|
|
||||||
@ -410,8 +413,8 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
|
|||||||
if(cand(icand)%iflip.ne.0) cycle !Do only Q65 candidates here
|
if(cand(icand)%iflip.ne.0) cycle !Do only Q65 candidates here
|
||||||
if(candec(icand)) cycle !Skip if already decoded
|
if(candec(icand)) cycle !Skip if already decoded
|
||||||
freq=cand(icand)%f+nkhz_center-48.0-1.27046
|
freq=cand(icand)%f+nkhz_center-48.0-1.27046
|
||||||
! If here at nqd=1, do only candidates at mousefqso +/- ntol
|
!###! If here at nqd=1, do only candidates at mousefqso +/- ntol
|
||||||
if(nqd.eq.1 .and. abs(freq-mousefqso).gt.0.001*ntol) cycle
|
!### if(nqd.eq.1 .and. abs(freq-mousefqso).gt.0.001*ntol) cycle
|
||||||
ikhz=nint(freq)
|
ikhz=nint(freq)
|
||||||
f0=cand(icand)%f
|
f0=cand(icand)%f
|
||||||
call timer('q65b ',0)
|
call timer('q65b ',0)
|
||||||
@ -499,6 +502,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
|
|||||||
write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, &
|
write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, &
|
||||||
nsync2,nutc,decoded,cp,cmode
|
nsync2,nutc,decoded,cp,cmode
|
||||||
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2)
|
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2)
|
||||||
|
ndecodes=ndecodes+1
|
||||||
write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, &
|
write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, &
|
||||||
cmode(1:1),cmode(2:2)
|
cmode(1:1),cmode(2:2)
|
||||||
1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1)
|
1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1)
|
||||||
|
@ -35,6 +35,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
|
|||||||
character*1 cp,cmode*2
|
character*1 cp,cmode*2
|
||||||
common/cacb/ca,cb
|
common/cacb/ca,cb
|
||||||
common/early/nhsym1,nhsym2,ldecoded(32768)
|
common/early/nhsym1,nhsym2,ldecoded(32768)
|
||||||
|
common/decodes/ndecodes
|
||||||
data nutc00/-1/,msg00/' '/
|
data nutc00/-1/,msg00/' '/
|
||||||
save
|
save
|
||||||
|
|
||||||
@ -179,6 +180,7 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
|
|||||||
! to map65_rx.log
|
! to map65_rx.log
|
||||||
if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then
|
if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then
|
||||||
! Write to file map65_rx.log:
|
! Write to file map65_rx.log:
|
||||||
|
ndecodes=ndecodes+1
|
||||||
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0
|
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0
|
||||||
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3)
|
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3)
|
||||||
nutc00=nutc
|
nutc00=nutc
|
||||||
|
@ -19,7 +19,7 @@ int main(int argc, char *argv[])
|
|||||||
QApplication a {argc, argv};
|
QApplication a {argc, argv};
|
||||||
// Override programs executable basename as application name.
|
// Override programs executable basename as application name.
|
||||||
a.setApplicationName ("MAP65");
|
a.setApplicationName ("MAP65");
|
||||||
a.setApplicationVersion ("3.0.0");
|
a.setApplicationVersion ("3.0.1");
|
||||||
// switch off as we share an Info.plist file with WSJT-X
|
// switch off as we share an Info.plist file with WSJT-X
|
||||||
a.setAttribute (Qt::AA_DontUseNativeMenuBar);
|
a.setAttribute (Qt::AA_DontUseNativeMenuBar);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
|
@ -520,6 +520,8 @@ void MainWindow::dataSink(int k)
|
|||||||
static int nkhz;
|
static int nkhz;
|
||||||
static int nfsample=96000;
|
static int nfsample=96000;
|
||||||
static int nxpol=0;
|
static int nxpol=0;
|
||||||
|
static int nsec0=0;
|
||||||
|
static int nsum=0;
|
||||||
static float fgreen;
|
static float fgreen;
|
||||||
static int ndiskdat;
|
static int ndiskdat;
|
||||||
static int nb;
|
static int nb;
|
||||||
@ -529,6 +531,7 @@ void MainWindow::dataSink(int k)
|
|||||||
static float rejectx;
|
static float rejectx;
|
||||||
static float rejecty;
|
static float rejecty;
|
||||||
static float slimit;
|
static float slimit;
|
||||||
|
static double xsum=0.0;
|
||||||
|
|
||||||
if(m_diskData) {
|
if(m_diskData) {
|
||||||
ndiskdat=1;
|
ndiskdat=1;
|
||||||
@ -551,8 +554,22 @@ void MainWindow::dataSink(int k)
|
|||||||
&nfsample, &fgreen, &m_adjustIQ, &m_applyIQcal,
|
&nfsample, &fgreen, &m_adjustIQ, &m_applyIQcal,
|
||||||
&m_gainx, &m_gainy, &m_phasex, &m_phasey, &rejectx, &rejecty,
|
&m_gainx, &m_gainy, &m_phasex, &m_phasey, &rejectx, &rejecty,
|
||||||
&px, &py, s, &nkhz, &ihsym, &nzap, &slimit, lstrong);
|
&px, &py, s, &nkhz, &ihsym, &nzap, &slimit, lstrong);
|
||||||
|
|
||||||
|
int nsec=QDateTime::currentSecsSinceEpoch();
|
||||||
|
if(nsec==nsec0) {
|
||||||
|
xsum+=pow(10.0,0.1*px);
|
||||||
|
nsum+=1;
|
||||||
|
} else {
|
||||||
|
m_xavg=0.0;
|
||||||
|
if(nsum>0) m_xavg=xsum/nsum;
|
||||||
|
xsum=pow(10.0,0.1*px);
|
||||||
|
nsum=1;
|
||||||
|
}
|
||||||
|
nsec0=nsec;
|
||||||
|
|
||||||
QString t;
|
QString t;
|
||||||
m_pctZap=nzap/178.3;
|
m_pctZap=nzap/178.3;
|
||||||
|
ui->yMeterFrame->setVisible(m_xpol);
|
||||||
if(m_xpol) {
|
if(m_xpol) {
|
||||||
lab4->setText (
|
lab4->setText (
|
||||||
QString {" Rx noise: %1 %2 %3 %% "}
|
QString {" Rx noise: %1 %2 %3 %% "}
|
||||||
@ -1119,6 +1136,9 @@ void MainWindow::diskDat() //diskDat()
|
|||||||
//These may be redundant??
|
//These may be redundant??
|
||||||
m_diskData=true;
|
m_diskData=true;
|
||||||
datcom_.newdat=1;
|
datcom_.newdat=1;
|
||||||
|
if(m_wide_graph_window->m_bForceCenterFreq) {
|
||||||
|
datcom_.fcenter=m_wide_graph_window->m_dForceCenterFreq;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_fs96000) hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol
|
if(m_fs96000) hsym=2048.0*96000.0/11025.0; //Samples per JT65 half-symbol
|
||||||
if(!m_fs96000) hsym=2048.0*95238.1/11025.0;
|
if(!m_fs96000) hsym=2048.0*95238.1/11025.0;
|
||||||
@ -1396,6 +1416,8 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
QFile lockFile(m_appDir + "/.lock");
|
QFile lockFile(m_appDir + "/.lock");
|
||||||
lockFile.open(QIODevice::ReadWrite);
|
lockFile.open(QIODevice::ReadWrite);
|
||||||
if(t.indexOf("<DecodeFinished>") >= 0) {
|
if(t.indexOf("<DecodeFinished>") >= 0) {
|
||||||
|
int ndecodes=t.mid(40,5).toInt();
|
||||||
|
lab5->setText(QString::number(ndecodes));
|
||||||
m_map65RxLog=0;
|
m_map65RxLog=0;
|
||||||
m_startAnother=m_loopall;
|
m_startAnother=m_loopall;
|
||||||
}
|
}
|
||||||
@ -1404,6 +1426,8 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_log();
|
||||||
|
|
||||||
if(t.indexOf("!") >= 0) {
|
if(t.indexOf("!") >= 0) {
|
||||||
int n=t.length();
|
int n=t.length();
|
||||||
int m=2;
|
int m=2;
|
||||||
@ -1688,7 +1712,7 @@ void MainWindow::guiUpdate()
|
|||||||
QDateTime t = QDateTime::currentDateTimeUtc();
|
QDateTime t = QDateTime::currentDateTimeUtc();
|
||||||
int fQSO=m_wide_graph_window->QSOfreq();
|
int fQSO=m_wide_graph_window->QSOfreq();
|
||||||
m_astro_window->astroUpdate(t, m_myGrid, m_hisGrid, fQSO, m_setftx,
|
m_astro_window->astroUpdate(t, m_myGrid, m_hisGrid, fQSO, m_setftx,
|
||||||
m_txFreq, m_azelDir);
|
m_txFreq, m_azelDir, m_xavg);
|
||||||
m_setftx=0;
|
m_setftx=0;
|
||||||
QString utc = t.date().toString(" yyyy MMM dd \n") + t.time().toString();
|
QString utc = t.date().toString(" yyyy MMM dd \n") + t.time().toString();
|
||||||
ui->labUTC->setText(utc);
|
ui->labUTC->setText(utc);
|
||||||
@ -2344,3 +2368,24 @@ bool MainWindow::isGrid4(QString g)
|
|||||||
if(g.mid(3,1)<'0' or g.mid(3,1)>'9') return false;
|
if(g.mid(3,1)<'0' or g.mid(3,1)>'9') return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::read_log()
|
||||||
|
{
|
||||||
|
// Update "m_worked" by reading wsjtx.log
|
||||||
|
m_worked.clear(); //Start from scratch
|
||||||
|
QFile f("wsjtx.log");
|
||||||
|
f.open(QIODevice::ReadOnly);
|
||||||
|
if(f.isOpen()) {
|
||||||
|
QTextStream in(&f);
|
||||||
|
QString line,callsign;
|
||||||
|
for(int i=0; i<99999; i++) {
|
||||||
|
line=in.readLine();
|
||||||
|
if(line.length()<=0) break;
|
||||||
|
callsign=line.mid(40,6);
|
||||||
|
int n=callsign.indexOf(",");
|
||||||
|
if(n>0) callsign=callsign.left(n);
|
||||||
|
m_worked[callsign]=true;
|
||||||
|
}
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -194,12 +194,12 @@ private:
|
|||||||
qint32 m_RxState;
|
qint32 m_RxState;
|
||||||
qint32 m_dB;
|
qint32 m_dB;
|
||||||
|
|
||||||
|
|
||||||
double m_fAdd;
|
double m_fAdd;
|
||||||
// double m_IQamp;
|
// double m_IQamp;
|
||||||
// double m_IQphase;
|
// double m_IQphase;
|
||||||
double m_cal570;
|
double m_cal570;
|
||||||
double m_TxOffset;
|
double m_TxOffset;
|
||||||
|
double m_xavg;
|
||||||
|
|
||||||
bool m_monitoring;
|
bool m_monitoring;
|
||||||
bool m_transmitting;
|
bool m_transmitting;
|
||||||
@ -294,6 +294,7 @@ private:
|
|||||||
void stub();
|
void stub();
|
||||||
bool isGrid4(QString g);
|
bool isGrid4(QString g);
|
||||||
bool subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
bool subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
||||||
|
void read_log();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void getfile(QString fname, bool xpol, int idInt);
|
extern void getfile(QString fname, bool xpol, int idInt);
|
||||||
|
@ -90,6 +90,7 @@
|
|||||||
#include "ExportCabrillo.h"
|
#include "ExportCabrillo.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "moc_mainwindow.cpp"
|
#include "moc_mainwindow.cpp"
|
||||||
|
#include "Logger.hpp"
|
||||||
|
|
||||||
#define FCL fortran_charlen_t
|
#define FCL fortran_charlen_t
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ extern "C" {
|
|||||||
|
|
||||||
void save_echo_params_(int* ndoptotal, int* ndop, int* nfrit, float* f1, float* fspread, short id2[], int* idir);
|
void save_echo_params_(int* ndoptotal, int* ndop, int* nfrit, float* f1, float* fspread, short id2[], int* idir);
|
||||||
|
|
||||||
void avecho_( short id2[], int* dop, int* nfrit, int* nauto, int* nqual, float* f1,
|
void avecho_( short id2[], int* dop, int* nfrit, int* nauto, int* navg, int* nqual, float* f1,
|
||||||
float* level, float* sigdb, float* snr, float* dfreq,
|
float* level, float* sigdb, float* snr, float* dfreq,
|
||||||
float* width, bool* bDiskData);
|
float* width, bool* bDiskData);
|
||||||
|
|
||||||
@ -208,6 +209,8 @@ QVector<QColor> g_ColorTbl;
|
|||||||
using SpecOp = Configuration::SpecialOperatingActivity;
|
using SpecOp = Configuration::SpecialOperatingActivity;
|
||||||
|
|
||||||
bool m_displayBand = false;
|
bool m_displayBand = false;
|
||||||
|
bool no_a7_decodes = false;
|
||||||
|
bool keep_frequency = false;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -753,24 +756,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ensure a balanced layout of the mode buttons
|
|
||||||
qreal pointSize = m_config.text_font().pointSizeF();
|
|
||||||
if (pointSize < 11) {
|
|
||||||
ui->houndButton->setMaximumWidth(40);
|
|
||||||
ui->ft8Button->setMaximumWidth(40);
|
|
||||||
ui->ft4Button->setMaximumWidth(40);
|
|
||||||
ui->msk144Button->setMaximumWidth(40);
|
|
||||||
ui->q65Button->setMaximumWidth(40);
|
|
||||||
ui->jt65Button->setMaximumWidth(40);
|
|
||||||
} else {
|
|
||||||
ui->houndButton->setMinimumWidth(50);
|
|
||||||
ui->ft8Button->setMinimumWidth(50);
|
|
||||||
ui->ft4Button->setMinimumWidth(50);
|
|
||||||
ui->msk144Button->setMinimumWidth(50);
|
|
||||||
ui->q65Button->setMinimumWidth(50);
|
|
||||||
ui->jt65Button->setMinimumWidth(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hook up save WAV file exit handling
|
// hook up save WAV file exit handling
|
||||||
connect (&m_saveWAVWatcher, &QFutureWatcher<QString>::finished, [this] {
|
connect (&m_saveWAVWatcher, &QFutureWatcher<QString>::finished, [this] {
|
||||||
// extract the promise from the future
|
// extract the promise from the future
|
||||||
@ -1224,6 +1209,7 @@ void MainWindow::writeSettings()
|
|||||||
m_settings->setValue("Blanker",ui->sbNB->value());
|
m_settings->setValue("Blanker",ui->sbNB->value());
|
||||||
m_settings->setValue("Score",m_score);
|
m_settings->setValue("Score",m_score);
|
||||||
m_settings->setValue("labDXpedText",ui->labDXped->text());
|
m_settings->setValue("labDXpedText",ui->labDXped->text());
|
||||||
|
m_settings->setValue("EchoAvg",ui->sbEchoAvg->value());
|
||||||
|
|
||||||
{
|
{
|
||||||
QList<QVariant> coeffs; // suitable for QSettings
|
QList<QVariant> coeffs; // suitable for QSettings
|
||||||
@ -1357,6 +1343,7 @@ void MainWindow::readSettings()
|
|||||||
ui->actionAuto_Clear_Avg->setChecked (m_settings->value ("AutoClearAvg", false).toBool());
|
ui->actionAuto_Clear_Avg->setChecked (m_settings->value ("AutoClearAvg", false).toBool());
|
||||||
ui->decodes_splitter->restoreState(m_settings->value("SplitterState").toByteArray());
|
ui->decodes_splitter->restoreState(m_settings->value("SplitterState").toByteArray());
|
||||||
ui->sbNB->setValue(m_settings->value("Blanker",0).toInt());
|
ui->sbNB->setValue(m_settings->value("Blanker",0).toInt());
|
||||||
|
ui->sbEchoAvg->setValue(m_settings->value("EchoAvg",10).toInt());
|
||||||
{
|
{
|
||||||
auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients"
|
auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients"
|
||||||
, QList<QVariant> {0., 0., 0., 0., 0.}).toList ();
|
, QList<QVariant> {0., 0., 0., 0., 0.}).toList ();
|
||||||
@ -1374,6 +1361,7 @@ void MainWindow::readSettings()
|
|||||||
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::TimeCriticalPriority).toInt () % 8);
|
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::TimeCriticalPriority).toInt () % 8);
|
||||||
m_settings->endGroup ();
|
m_settings->endGroup ();
|
||||||
|
|
||||||
|
m_specOp=m_config.special_op_id();
|
||||||
checkMSK144ContestType();
|
checkMSK144ContestType();
|
||||||
if(displayMsgAvg) on_actionMessage_averaging_triggered();
|
if(displayMsgAvg) on_actionMessage_averaging_triggered();
|
||||||
if (displayFoxLog) on_fox_log_action_triggered ();
|
if (displayFoxLog) on_fox_log_action_triggered ();
|
||||||
@ -1410,10 +1398,35 @@ void MainWindow::set_application_font (QFont const& font)
|
|||||||
QFile sf {sheet};
|
QFile sf {sheet};
|
||||||
if (sf.open (QFile::ReadOnly | QFile::Text))
|
if (sf.open (QFile::ReadOnly | QFile::Text))
|
||||||
{
|
{
|
||||||
ss = sf.readAll () + ss;
|
QString tmp = sf.readAll();
|
||||||
|
if (tmp != NULL) ss = sf.readAll () + tmp;
|
||||||
|
else qDebug() << "tmp==NULL at sf.readAll";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qApp->setStyleSheet (ss + "* {" + font_as_stylesheet (font) + '}');
|
qApp->setStyleSheet (ss + "* {" + font_as_stylesheet (font) + '}');
|
||||||
|
// ensure a balanced layout of the mode buttons
|
||||||
|
qreal pointSize = m_config.text_font().pointSizeF();
|
||||||
|
if (pointSize < 11) {
|
||||||
|
ui->houndButton->setMaximumWidth(40);
|
||||||
|
ui->ft8Button->setMaximumWidth(40);
|
||||||
|
ui->ft4Button->setMaximumWidth(40);
|
||||||
|
ui->msk144Button->setMaximumWidth(40);
|
||||||
|
ui->q65Button->setMaximumWidth(40);
|
||||||
|
ui->jt65Button->setMaximumWidth(40);
|
||||||
|
ui->houndButton->setMinimumWidth(0);
|
||||||
|
ui->ft8Button->setMinimumWidth(0);
|
||||||
|
ui->ft4Button->setMinimumWidth(0);
|
||||||
|
ui->msk144Button->setMinimumWidth(0);
|
||||||
|
ui->q65Button->setMinimumWidth(0);
|
||||||
|
ui->jt65Button->setMinimumWidth(0);
|
||||||
|
} else {
|
||||||
|
ui->houndButton->setMinimumWidth(50);
|
||||||
|
ui->ft8Button->setMinimumWidth(50);
|
||||||
|
ui->ft4Button->setMinimumWidth(50);
|
||||||
|
ui->msk144Button->setMinimumWidth(50);
|
||||||
|
ui->q65Button->setMinimumWidth(50);
|
||||||
|
ui->jt65Button->setMinimumWidth(50);
|
||||||
|
}
|
||||||
for (auto& widget : qApp->topLevelWidgets ())
|
for (auto& widget : qApp->topLevelWidgets ())
|
||||||
{
|
{
|
||||||
widget->updateGeometry ();
|
widget->updateGeometry ();
|
||||||
@ -1541,7 +1554,7 @@ void MainWindow::dataSink(qint64 frames)
|
|||||||
if(m_ihsym <=0) return;
|
if(m_ihsym <=0) return;
|
||||||
if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer
|
if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer
|
||||||
if(m_monitoring || m_diskData) {
|
if(m_monitoring || m_diskData) {
|
||||||
m_wideGraph->dataSink2(s,m_df3,m_ihsym,m_diskData);
|
m_wideGraph->dataSink2(s,m_df3,m_ihsym,m_diskData,m_px);
|
||||||
}
|
}
|
||||||
if(m_mode=="MSK144") return;
|
if(m_mode=="MSK144") return;
|
||||||
|
|
||||||
@ -1616,11 +1629,12 @@ void MainWindow::dataSink(qint64 frames)
|
|||||||
echocom_.nclearave=m_nclearave;
|
echocom_.nclearave=m_nclearave;
|
||||||
int nDop=m_fAudioShift;
|
int nDop=m_fAudioShift;
|
||||||
int nDopTotal=m_fDop;
|
int nDopTotal=m_fDop;
|
||||||
|
int navg=ui->sbEchoAvg->value();
|
||||||
if(m_diskData) {
|
if(m_diskData) {
|
||||||
int idir=-1;
|
int idir=-1;
|
||||||
save_echo_params_(&nDopTotal,&nDop,&nfrit,&f1,&width,dec_data.d2,&idir);
|
save_echo_params_(&nDopTotal,&nDop,&nfrit,&f1,&width,dec_data.d2,&idir);
|
||||||
}
|
}
|
||||||
avecho_(dec_data.d2,&nDop,&nfrit,&nauto,&nqual,&f1,&xlevel,&sigdb,
|
avecho_(dec_data.d2,&nDop,&nfrit,&nauto,&navg,&nqual,&f1,&xlevel,&sigdb,
|
||||||
&dBerr,&dfreq,&width,&m_diskData);
|
&dBerr,&dfreq,&width,&m_diskData);
|
||||||
//Don't restart Monitor after an Echo transmission
|
//Don't restart Monitor after an Echo transmission
|
||||||
if(m_bEchoTxed and !m_auto) {
|
if(m_bEchoTxed and !m_auto) {
|
||||||
@ -1629,7 +1643,7 @@ void MainWindow::dataSink(qint64 frames)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(m_monitoring or m_auto or m_diskData) {
|
if(m_monitoring or m_auto or m_diskData) {
|
||||||
QString t0;
|
QString t0,t1;
|
||||||
if(m_diskData) {
|
if(m_diskData) {
|
||||||
t0=t0.asprintf("%06d ",m_UTCdisk);
|
t0=t0.asprintf("%06d ",m_UTCdisk);
|
||||||
} else {
|
} else {
|
||||||
@ -1640,17 +1654,20 @@ void MainWindow::dataSink(qint64 frames)
|
|||||||
if(m_auto) isec=isec - isec%6;
|
if(m_auto) isec=isec - isec%6;
|
||||||
if(!m_auto) isec=isec - isec%3;
|
if(!m_auto) isec=isec - isec%3;
|
||||||
t0=t0.asprintf("%02d%02d%02d ",ihr,imin,isec);
|
t0=t0.asprintf("%02d%02d%02d ",ihr,imin,isec);
|
||||||
|
t1=now.toString("yyMMdd_");
|
||||||
}
|
}
|
||||||
int n=t0.toInt();
|
int n=t0.toInt();
|
||||||
int nsec=((n/10000)*3600) + (((n/100)%100)*60) + (n%100);
|
int nsec=((n/10000)*3600) + (((n/100)%100)*60) + (n%100);
|
||||||
if(!m_echoRunning) m_echoSec0=nsec;
|
if(!m_echoRunning or echocom_.nsum<2) m_echoSec0=nsec;
|
||||||
n=(nsec-m_echoSec0 + 864000)%86400;
|
float hour=n/10000 + ((n/100)%100)/60.0 + (n%100)/3600.0;
|
||||||
m_echoRunning=true;
|
m_echoRunning=true;
|
||||||
QString t;
|
QString t;
|
||||||
t = t.asprintf("%6d %5.2f %7d %7.1f %7d %7d %7d %7.1f %7.1f",n,xlevel,
|
t = t.asprintf("%9.6f %5.2f %7d %7.1f %7d %7d %7d %7.1f %7.1f",hour,xlevel,
|
||||||
nDopTotal,width,echocom_.nsum,nqual,qRound(dfreq),sigdb,dBerr);
|
nDopTotal,width,echocom_.nsum,nqual,qRound(dfreq),sigdb,dBerr);
|
||||||
t = t0 + t;
|
t = t0 + t;
|
||||||
if (ui) ui->decodedTextBrowser->appendText(t);
|
if (ui) ui->decodedTextBrowser->appendText(t);
|
||||||
|
t=t1+t;
|
||||||
|
write_all("Rx",t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_echoGraph->isVisible()) m_echoGraph->plotSpec();
|
if(m_echoGraph->isVisible()) m_echoGraph->plotSpec();
|
||||||
@ -3176,6 +3193,7 @@ void MainWindow::on_ClrAvgButton_clicked()
|
|||||||
if(m_mode=="Echo") {
|
if(m_mode=="Echo") {
|
||||||
echocom_.nsum=0;
|
echocom_.nsum=0;
|
||||||
m_echoGraph->clearAvg();
|
m_echoGraph->clearAvg();
|
||||||
|
m_wideGraph->restartTotalPower();
|
||||||
} else {
|
} else {
|
||||||
if(m_msgAvgWidget != NULL) {
|
if(m_msgAvgWidget != NULL) {
|
||||||
if(m_msgAvgWidget->isVisible()) m_msgAvgWidget->displayAvg("");
|
if(m_msgAvgWidget->isVisible()) m_msgAvgWidget->displayAvg("");
|
||||||
@ -3682,6 +3700,10 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't allow a7 decodes during the first period because they can be leftovers from the previous band
|
||||||
|
if (!(no_a7_decodes && line_read.contains("a7"))) {
|
||||||
|
|
||||||
if (m_mode!="FT8" and m_mode!="FT4" and !m_mode.startsWith ("FST4") and m_mode!="Q65") {
|
if (m_mode!="FT8" and m_mode!="FT4" and !m_mode.startsWith ("FST4") and m_mode!="Q65") {
|
||||||
//Pad 22-char msg to at least 37 chars
|
//Pad 22-char msg to at least 37 chars
|
||||||
line_read = line_read.left(44) + " " + line_read.mid(44);
|
line_read = line_read.left(44) + " " + line_read.mid(44);
|
||||||
@ -3748,6 +3770,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
}
|
}
|
||||||
m_tBlankLine = line_read.left(ntime);
|
m_tBlankLine = line_read.left(ntime);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ("FST4W" == m_mode)
|
if ("FST4W" == m_mode)
|
||||||
{
|
{
|
||||||
uploadWSPRSpots (true, line_read);
|
uploadWSPRSpots (true, line_read);
|
||||||
@ -3797,7 +3820,8 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
|
|
||||||
if (m_config.highlight_DXcall () && (m_hisCall!="") && ((decodedtext.string().contains(QRegularExpression {"(\\w+) " + m_hisCall}))
|
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 +">"}))
|
||||||
|| (decodedtext.string().contains(QRegularExpression {"<(\\w+)> " + m_hisCall})))) {
|
|| (decodedtext.string().contains(QRegularExpression {"<(\\w+)> " + m_hisCall}))
|
||||||
|
|| (decodedtext.string().contains(QRegularExpression {"<...> " + m_hisCall})))) {
|
||||||
ui->decodedTextBrowser->highlight_callsign(m_hisCall, QColor(255,0,0), QColor(255,255,255), true); // highlight dxCallEntry
|
ui->decodedTextBrowser->highlight_callsign(m_hisCall, QColor(255,0,0), QColor(255,255,255), true); // highlight dxCallEntry
|
||||||
QTimer::singleShot (500, [=] { // repeated highlighting to override JTAlert
|
QTimer::singleShot (500, [=] { // repeated highlighting to override JTAlert
|
||||||
ui->decodedTextBrowser->highlight_callsign(m_hisCall, QColor(255,0,0), QColor(255,255,255), true);
|
ui->decodedTextBrowser->highlight_callsign(m_hisCall, QColor(255,0,0), QColor(255,255,255), true);
|
||||||
@ -4019,7 +4043,8 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
QTextStream s(&f);
|
QTextStream s(&f);
|
||||||
QString t=s.readAll();
|
QString t=s.readAll();
|
||||||
m_msgAvgWidget->displayAvg(t);
|
if (t != NULL) m_msgAvgWidget->displayAvg(t);
|
||||||
|
else qDebug() << "tmp==NULL at s.readAll";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4119,7 +4144,7 @@ void MainWindow::pskPost (DecodedText const& decodedtext)
|
|||||||
}
|
}
|
||||||
int snr = decodedtext.snr();
|
int snr = decodedtext.snr();
|
||||||
Frequency frequency = m_freqNominalPeriod + audioFrequency; // prevent spotting wrong band
|
Frequency frequency = m_freqNominalPeriod + audioFrequency; // prevent spotting wrong band
|
||||||
if(grid.contains (grid_regexp)) {
|
if(grid.contains (grid_regexp) || decodedtext.string().contains(" CQ ")) {
|
||||||
// qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr;
|
// qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr;
|
||||||
if (!m_psk_Reporter.addRemoteStation (deCall, grid, frequency, msgmode, snr))
|
if (!m_psk_Reporter.addRemoteStation (deCall, grid, frequency, msgmode, snr))
|
||||||
{
|
{
|
||||||
@ -6148,7 +6173,9 @@ void MainWindow::on_addButton_clicked() //Add button
|
|||||||
// preserve symlinks
|
// preserve symlinks
|
||||||
f1.open (QFile::WriteOnly | QFile::Text); // truncates
|
f1.open (QFile::WriteOnly | QFile::Text); // truncates
|
||||||
f2.seek (0);
|
f2.seek (0);
|
||||||
f1.write (f2.readAll ()); // copy contents
|
QByteArray tmp = f2.readAll();
|
||||||
|
if (tmp != (const char*)NULL) f1.write (tmp); // copy contents
|
||||||
|
else qDebug() << "tmp==NULL at f1.write";
|
||||||
f2.remove ();
|
f2.remove ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6526,6 +6553,7 @@ void MainWindow::displayWidgets(qint64 n)
|
|||||||
(m_config.RTTY_Exchange()=="DX" or m_config.RTTY_Exchange()=="#") );
|
(m_config.RTTY_Exchange()=="DX" or m_config.RTTY_Exchange()=="#") );
|
||||||
}
|
}
|
||||||
if(m_mode=="MSK144") b=SpecOp::EU_VHF==m_specOp;
|
if(m_mode=="MSK144") b=SpecOp::EU_VHF==m_specOp;
|
||||||
|
ui->sbEchoAvg->setVisible(m_mode=="Echo");
|
||||||
ui->sbSerialNumber->setVisible(b);
|
ui->sbSerialNumber->setVisible(b);
|
||||||
m_lastCallsign.clear (); // ensures Tx5 is updated for new modes
|
m_lastCallsign.clear (); // ensures Tx5 is updated for new modes
|
||||||
b=m_mode.startsWith("FST4");
|
b=m_mode.startsWith("FST4");
|
||||||
@ -6634,6 +6662,7 @@ void MainWindow::on_actionFT4_triggered()
|
|||||||
m_wideGraph->setMode(m_mode);
|
m_wideGraph->setMode(m_mode);
|
||||||
m_send_RR73=true;
|
m_send_RR73=true;
|
||||||
VHF_features_enabled(bVHF);
|
VHF_features_enabled(bVHF);
|
||||||
|
ui->cbAutoSeq->setChecked(true);
|
||||||
m_fastGraph->hide();
|
m_fastGraph->hide();
|
||||||
m_wideGraph->show();
|
m_wideGraph->show();
|
||||||
ui->rh_decodes_headings_label->setText(" UTC dB DT Freq " + tr ("Message"));
|
ui->rh_decodes_headings_label->setText(" UTC dB DT Freq " + tr ("Message"));
|
||||||
@ -6740,7 +6769,7 @@ void MainWindow::on_actionFT8_triggered()
|
|||||||
ui->txb5->setEnabled(false);
|
ui->txb5->setEnabled(false);
|
||||||
ui->txb6->setEnabled(false);
|
ui->txb6->setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
switch_mode (Modes::FT8);
|
if (!(keep_frequency)) switch_mode (Modes::FT8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_specOp != SpecOp::HOUND) {
|
if(m_specOp != SpecOp::HOUND) {
|
||||||
@ -6951,6 +6980,7 @@ void MainWindow::on_actionQ65_triggered()
|
|||||||
m_mode="Q65";
|
m_mode="Q65";
|
||||||
ui->actionQ65->setChecked(true);
|
ui->actionQ65->setChecked(true);
|
||||||
switch_mode(Modes::Q65);
|
switch_mode(Modes::Q65);
|
||||||
|
ui->cbAutoSeq->setChecked(true);
|
||||||
fast_config(false);
|
fast_config(false);
|
||||||
WSPR_config(false);
|
WSPR_config(false);
|
||||||
setup_status_bar(true);
|
setup_status_bar(true);
|
||||||
@ -7032,6 +7062,7 @@ void MainWindow::on_actionMSK144_triggered()
|
|||||||
m_toneSpacing=0.0;
|
m_toneSpacing=0.0;
|
||||||
WSPR_config(false);
|
WSPR_config(false);
|
||||||
VHF_features_enabled(true);
|
VHF_features_enabled(true);
|
||||||
|
ui->cbAutoSeq->setChecked(true);
|
||||||
m_bFastMode=true;
|
m_bFastMode=true;
|
||||||
m_bFast9=false;
|
m_bFast9=false;
|
||||||
ui->sbTR->values ({5, 10, 15, 30});
|
ui->sbTR->values ({5, 10, 15, 30});
|
||||||
@ -7108,7 +7139,13 @@ void MainWindow::on_actionWSPR_triggered()
|
|||||||
|
|
||||||
void MainWindow::on_actionEcho_triggered()
|
void MainWindow::on_actionEcho_triggered()
|
||||||
{
|
{
|
||||||
|
int nd=int(m_ndepth&3);
|
||||||
on_actionJT4_triggered();
|
on_actionJT4_triggered();
|
||||||
|
// Don't allow decoding depth to be changed just because Echo mode was entered:
|
||||||
|
if(nd==1) ui->actionQuickDecode->setChecked (true);
|
||||||
|
if(nd==2) ui->actionMediumDecode->setChecked (true);
|
||||||
|
if(nd==3) ui->actionDeepestDecode->setChecked (true);
|
||||||
|
|
||||||
m_mode="Echo";
|
m_mode="Echo";
|
||||||
ui->actionEcho->setChecked(true);
|
ui->actionEcho->setChecked(true);
|
||||||
m_TRperiod=3.0;
|
m_TRperiod=3.0;
|
||||||
@ -7131,11 +7168,11 @@ void MainWindow::on_actionEcho_triggered()
|
|||||||
m_bFastMode=false;
|
m_bFastMode=false;
|
||||||
m_bFast9=false;
|
m_bFast9=false;
|
||||||
WSPR_config(true);
|
WSPR_config(true);
|
||||||
ui->lh_decodes_headings_label->setText(" UTC Tsec Level Doppler Width N Q DF SNR dBerr");
|
ui->lh_decodes_headings_label->setText(" UTC Hour Level Doppler Width N Q DF SNR dBerr");
|
||||||
// 01234567890123456789012345678901234567
|
// 01234567890123456789012345678901234567
|
||||||
displayWidgets(nWidgets("00000000000000000010001000000000000000"));
|
displayWidgets(nWidgets("00000000000000000010001000000000000000"));
|
||||||
fast_config(false);
|
fast_config(false);
|
||||||
if(m_astroWidget) m_astroWidget->selectOwnEcho();
|
ui->sbEchoAvg->values ({1, 2, 5, 10, 20, 50, 100});
|
||||||
statusChanged();
|
statusChanged();
|
||||||
monitor(false);
|
monitor(false);
|
||||||
}
|
}
|
||||||
@ -7455,6 +7492,10 @@ void MainWindow::on_bandComboBox_activated (int index)
|
|||||||
|
|
||||||
void MainWindow::band_changed (Frequency f)
|
void MainWindow::band_changed (Frequency f)
|
||||||
{
|
{
|
||||||
|
// Don't allow a7 decodes during the first period because they can be leftovers from the previous band
|
||||||
|
no_a7_decodes = true;
|
||||||
|
QTimer::singleShot ((int(1500.0*m_TRperiod)), [=] {no_a7_decodes = false;});
|
||||||
|
|
||||||
// Set the attenuation value if options are checked
|
// Set the attenuation value if options are checked
|
||||||
if (m_config.pwrBandTxMemory() && !m_tune) {
|
if (m_config.pwrBandTxMemory() && !m_tune) {
|
||||||
auto const&curBand = ui->bandComboBox->currentText();
|
auto const&curBand = ui->bandComboBox->currentText();
|
||||||
@ -7991,7 +8032,7 @@ void MainWindow::on_outAttenuation_valueChanged (int a)
|
|||||||
tt_str = tr ("Transmit digital gain ");
|
tt_str = tr ("Transmit digital gain ");
|
||||||
}
|
}
|
||||||
tt_str += (a ? QString::number (-dBAttn, 'f', 1) : "0") + "dB";
|
tt_str += (a ? QString::number (-dBAttn, 'f', 1) : "0") + "dB";
|
||||||
if (!m_block_pwr_tooltip) {
|
if (ui->outAttenuation->hasFocus() && !m_block_pwr_tooltip) {
|
||||||
QToolTip::showText (QCursor::pos (), tt_str, ui->outAttenuation);
|
QToolTip::showText (QCursor::pos (), tt_str, ui->outAttenuation);
|
||||||
}
|
}
|
||||||
QString curBand = ui->bandComboBox->currentText();
|
QString curBand = ui->bandComboBox->currentText();
|
||||||
@ -9734,7 +9775,9 @@ void MainWindow::write_all(QString txRx, QString message)
|
|||||||
QString t;
|
QString t;
|
||||||
QString msg;
|
QString msg;
|
||||||
QString mode_string;
|
QString mode_string;
|
||||||
|
QString file_name="ALL.TXT";
|
||||||
|
|
||||||
|
if(m_mode!="Echo") {
|
||||||
if (message.size () > 5 && message[4]==' ') {
|
if (message.size () > 5 && message[4]==' ') {
|
||||||
msg=message.mid(4,-1);
|
msg=message.mid(4,-1);
|
||||||
} else {
|
} else {
|
||||||
@ -9758,7 +9801,11 @@ void MainWindow::write_all(QString txRx, QString message)
|
|||||||
auto time = QDateTime::currentDateTimeUtc ();
|
auto time = QDateTime::currentDateTimeUtc ();
|
||||||
if( txRx=="Rx" && !m_bFastMode ) time=m_dateTimeSeqStart;
|
if( txRx=="Rx" && !m_bFastMode ) time=m_dateTimeSeqStart;
|
||||||
|
|
||||||
|
if (txRx=="Rx") {
|
||||||
t = t.asprintf("%10.3f ",m_freqNominalPeriod/1.e6); // prevent writing of wrong frequencies
|
t = t.asprintf("%10.3f ",m_freqNominalPeriod/1.e6); // prevent writing of wrong frequencies
|
||||||
|
} else {
|
||||||
|
t = t.asprintf("%10.3f ",m_freqNominal/1.e6);
|
||||||
|
}
|
||||||
if (m_diskData) {
|
if (m_diskData) {
|
||||||
if (m_fileDateTime.size()==11) {
|
if (m_fileDateTime.size()==11) {
|
||||||
line=m_fileDateTime + " " + t + txRx + " " + mode_string + msg;
|
line=m_fileDateTime + " " + t + txRx + " " + mode_string + msg;
|
||||||
@ -9769,10 +9816,14 @@ void MainWindow::write_all(QString txRx, QString message)
|
|||||||
line=time.toString("yyMMdd_hhmmss") + t + txRx + " " + mode_string + msg;
|
line=time.toString("yyMMdd_hhmmss") + t + txRx + " " + mode_string + msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString file_name="ALL.TXT";
|
|
||||||
if (ui->actionSplit_ALL_TXT_yearly->isChecked()) file_name=(time.toString("yyyy") + "-" + "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 (ui->actionSplit_ALL_TXT_monthly->isChecked()) file_name=(time.toString("yyyy-MM") + "-" + "ALL.TXT");
|
||||||
if (m_mode=="WSPR") file_name="ALL_WSPR.TXT";
|
if (m_mode=="WSPR") file_name="ALL_WSPR.TXT";
|
||||||
|
} else {
|
||||||
|
file_name="all_echo.txt";
|
||||||
|
line=message;
|
||||||
|
}
|
||||||
|
|
||||||
QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)};
|
QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)};
|
||||||
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
|
||||||
QTextStream out(&f);
|
QTextStream out(&f);
|
||||||
@ -9966,6 +10017,8 @@ void MainWindow::on_houndButton_clicked (bool checked)
|
|||||||
} else {
|
} else {
|
||||||
ui->houndButton->setStyleSheet("");
|
ui->houndButton->setStyleSheet("");
|
||||||
m_config.setSpecial_None();
|
m_config.setSpecial_None();
|
||||||
|
keep_frequency = true;
|
||||||
|
QTimer::singleShot (250, [=] {keep_frequency = false;});
|
||||||
}
|
}
|
||||||
m_specOp=m_config.special_op_id();
|
m_specOp=m_config.special_op_id();
|
||||||
on_actionFT8_triggered();
|
on_actionFT8_triggered();
|
||||||
@ -10025,26 +10078,3 @@ void MainWindow::on_jt65Button_clicked()
|
|||||||
}
|
}
|
||||||
on_actionJT65_triggered();
|
on_actionJT65_triggered();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionCopy_to_WSJTX_txt_triggered()
|
|
||||||
{
|
|
||||||
static QFile f {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("WSJT-X.txt")};
|
|
||||||
if(!f.open(QIODevice::Text | QIODevice::WriteOnly)) {
|
|
||||||
MessageBox::warning_message (this, tr ("WSJT-X.txt file error"),
|
|
||||||
tr ("Cannot open \"%1\" for writing").arg (f.fileName ()),
|
|
||||||
tr ("Error: %1").arg (f.errorString ()));
|
|
||||||
} else {
|
|
||||||
QString t=ui->decodedTextBrowser->toPlainText();
|
|
||||||
|
|
||||||
QTextStream out(&f);
|
|
||||||
out << t <<
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
|
||||||
endl
|
|
||||||
#else
|
|
||||||
Qt::endl
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
f.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -173,7 +173,6 @@ private slots:
|
|||||||
void on_actionOpen_next_in_directory_triggered();
|
void on_actionOpen_next_in_directory_triggered();
|
||||||
void on_actionDecode_remaining_files_in_directory_triggered();
|
void on_actionDecode_remaining_files_in_directory_triggered();
|
||||||
void on_actionDelete_all_wav_files_in_SaveDir_triggered();
|
void on_actionDelete_all_wav_files_in_SaveDir_triggered();
|
||||||
void on_actionCopy_to_WSJTX_txt_triggered();
|
|
||||||
void on_actionOpen_log_directory_triggered ();
|
void on_actionOpen_log_directory_triggered ();
|
||||||
void on_actionNone_triggered();
|
void on_actionNone_triggered();
|
||||||
void on_actionSave_all_triggered();
|
void on_actionSave_all_triggered();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -100,7 +100,6 @@ void CPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
|
|||||||
if(m_bReference) m_h2=m_h-30;
|
if(m_bReference) m_h2=m_h-30;
|
||||||
if(m_h2<1) m_h2=1;
|
if(m_h2<1) m_h2=1;
|
||||||
m_h1=m_h-m_h2;
|
m_h1=m_h-m_h2;
|
||||||
// m_line=0;
|
|
||||||
m_2DPixmap = QPixmap(m_Size.width(), m_h2);
|
m_2DPixmap = QPixmap(m_Size.width(), m_h2);
|
||||||
m_2DPixmap.fill(Qt::black);
|
m_2DPixmap.fill(Qt::black);
|
||||||
m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1);
|
m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1);
|
||||||
@ -112,6 +111,8 @@ void CPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
|
|||||||
m_ScalePixmap.fill(Qt::white);
|
m_ScalePixmap.fill(Qt::white);
|
||||||
m_Percent2DScreen0 = m_Percent2DScreen;
|
m_Percent2DScreen0 = m_Percent2DScreen;
|
||||||
m_bResized = true;
|
m_bResized = true;
|
||||||
|
m_vpixperdiv = float(m_h2)/float(VERT_DIVS);
|
||||||
|
m_x=0;
|
||||||
}
|
}
|
||||||
DrawOverlay();
|
DrawOverlay();
|
||||||
}
|
}
|
||||||
@ -167,6 +168,8 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
|
|||||||
static QPoint LineBuf[MAX_SCREENSIZE];
|
static QPoint LineBuf[MAX_SCREENSIZE];
|
||||||
static QPoint LineBuf2[MAX_SCREENSIZE];
|
static QPoint LineBuf2[MAX_SCREENSIZE];
|
||||||
static QPoint LineBuf3[MAX_SCREENSIZE];
|
static QPoint LineBuf3[MAX_SCREENSIZE];
|
||||||
|
static QPoint LineBuf4[MAX_SCREENSIZE];
|
||||||
|
|
||||||
j=0;
|
j=0;
|
||||||
j0=int(m_startFreq/m_fftBinWidth + 0.5);
|
j0=int(m_startFreq/m_fftBinWidth + 0.5);
|
||||||
int iz=XfromFreq(5000.0);
|
int iz=XfromFreq(5000.0);
|
||||||
@ -231,7 +234,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i==iz-1 and !m_bQ65_Sync) {
|
if(i==iz-1 and !m_bQ65_Sync and !m_bTotalPower) {
|
||||||
painter2D.drawPolyline(LineBuf,j);
|
painter2D.drawPolyline(LineBuf,j);
|
||||||
}
|
}
|
||||||
LineBuf[j].setX(i);
|
LineBuf[j].setX(i);
|
||||||
@ -320,6 +323,22 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed)
|
|||||||
painter2D.drawText(m_w-100,m_h2/2,t);
|
painter2D.drawText(m_w-100,m_h2/2,t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_bTotalPower and m_pdB>1.0) {
|
||||||
|
painter2D.setPen(Qt::green);
|
||||||
|
if(m_x==m_w-1) {
|
||||||
|
for (int i=0; i<m_w-1; i++) {
|
||||||
|
LineBuf4[i].setY(LineBuf4[i+1].y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int yy=m_h2 - 0.1*m_vpixperdiv*(m_pdB-20.0);
|
||||||
|
LineBuf4[m_x].setX(m_x);
|
||||||
|
LineBuf4[m_x].setY(yy);
|
||||||
|
if(LineBuf4[m_w-1].y()==0) LineBuf4[m_w-1].setY(yy);
|
||||||
|
painter2D.drawPolyline(LineBuf4,m_x);
|
||||||
|
if(m_x < m_w-1) m_x++;
|
||||||
|
}
|
||||||
|
|
||||||
update(); //trigger a new paintEvent
|
update(); //trigger a new paintEvent
|
||||||
m_bScaleOK=true;
|
m_bScaleOK=true;
|
||||||
}
|
}
|
||||||
@ -333,6 +352,7 @@ void CPlotter::drawRed(int ia, int ib, float swide[])
|
|||||||
|
|
||||||
void CPlotter::replot()
|
void CPlotter::replot()
|
||||||
{
|
{
|
||||||
|
resizeEvent(NULL);
|
||||||
float swide[m_w];
|
float swide[m_w];
|
||||||
m_bReplot=true;
|
m_bReplot=true;
|
||||||
for(int irow=0; irow<m_h1; irow++) {
|
for(int irow=0; irow<m_h1; irow++) {
|
||||||
@ -369,7 +389,6 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
|||||||
painter.setBrush(Qt::SolidPattern);
|
painter.setBrush(Qt::SolidPattern);
|
||||||
|
|
||||||
m_fSpan = w*df;
|
m_fSpan = w*df;
|
||||||
// int n=m_fSpan/10;
|
|
||||||
m_freqPerDiv=10;
|
m_freqPerDiv=10;
|
||||||
if(m_fSpan>100) m_freqPerDiv=20;
|
if(m_fSpan>100) m_freqPerDiv=20;
|
||||||
if(m_fSpan>250) m_freqPerDiv=50;
|
if(m_fSpan>250) m_freqPerDiv=50;
|
||||||
@ -377,9 +396,9 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
|||||||
if(m_fSpan>1000) m_freqPerDiv=200;
|
if(m_fSpan>1000) m_freqPerDiv=200;
|
||||||
if(m_fSpan>2500) m_freqPerDiv=500;
|
if(m_fSpan>2500) m_freqPerDiv=500;
|
||||||
|
|
||||||
|
if(!m_bTotalPower) {
|
||||||
pixperdiv = m_freqPerDiv/df;
|
pixperdiv = m_freqPerDiv/df;
|
||||||
m_hdivs = w*df/m_freqPerDiv + 1.9999;
|
m_hdivs = w*df/m_freqPerDiv + 1.9999;
|
||||||
|
|
||||||
float xx0=float(m_startFreq)/float(m_freqPerDiv);
|
float xx0=float(m_startFreq)/float(m_freqPerDiv);
|
||||||
xx0=xx0-int(xx0);
|
xx0=xx0-int(xx0);
|
||||||
int x0=xx0*pixperdiv+0.5;
|
int x0=xx0*pixperdiv+0.5;
|
||||||
@ -390,13 +409,36 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
|||||||
painter.drawLine(x, 0, x , m_h2);
|
painter.drawLine(x, 0, x , m_h2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pixperdiv = (float)m_h2 / (float)VERT_DIVS;
|
|
||||||
painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
|
painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
|
||||||
|
if(m_bTotalPower) painter.setPen(QPen(Qt::white, 1,Qt::DashLine));
|
||||||
for( int i=1; i<VERT_DIVS; i++) { //draw horizontal grids
|
for( int i=1; i<VERT_DIVS; i++) { //draw horizontal grids
|
||||||
y = (int)( (float)i*pixperdiv );
|
y = int(i*m_vpixperdiv);
|
||||||
|
if(m_bTotalPower) {
|
||||||
|
painter.drawLine(15, y, w, y);
|
||||||
|
} else {
|
||||||
painter.drawLine(0, y, w, y);
|
painter.drawLine(0, y, w, y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_bTotalPower) {
|
||||||
|
painter.setPen(QPen(Qt::white));
|
||||||
|
for( int i=1; i<VERT_DIVS; i++) { //draw horizontal grids
|
||||||
|
y = int(i*m_vpixperdiv);
|
||||||
|
painter.drawText(0,y+5,QString::number(10*(VERT_DIVS-i) + 20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_bTotalPower and m_h2>100) {
|
||||||
|
painter.setPen(QPen(Qt::white, 1,Qt::DotLine));
|
||||||
|
for( int i=1; i<5*VERT_DIVS; i++) { //draw horizontal 2 dB grids
|
||||||
|
if(i%5 > 0) {
|
||||||
|
y = int(0.2*i*m_vpixperdiv);
|
||||||
|
painter.drawLine(0, y, w, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QRect rect0;
|
QRect rect0;
|
||||||
QPainter painter0(&m_ScalePixmap);
|
QPainter painter0(&m_ScalePixmap);
|
||||||
@ -730,7 +772,15 @@ int CPlotter::rxFreq() {return m_rxFreq;} //rxFreq
|
|||||||
void CPlotter::mouseMoveEvent (QMouseEvent * event)
|
void CPlotter::mouseMoveEvent (QMouseEvent * event)
|
||||||
{
|
{
|
||||||
int x=event->x();
|
int x=event->x();
|
||||||
|
int y=event->y();
|
||||||
|
float pdB=10.0*(m_h-y)/m_vpixperdiv + 20.0;
|
||||||
|
if(y<(m_h-m_h2)) {
|
||||||
QToolTip::showText(event->globalPos(),QString::number(int(FreqfromX(x))));
|
QToolTip::showText(event->globalPos(),QString::number(int(FreqfromX(x))));
|
||||||
|
} else {
|
||||||
|
QString t;
|
||||||
|
t=t.asprintf("%4.1f dB",pdB);
|
||||||
|
QToolTip::showText(event->globalPos(),t);
|
||||||
|
}
|
||||||
QWidget::mouseMoveEvent(event);
|
QWidget::mouseMoveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,3 +924,13 @@ void CPlotter::setDiskUTC(int nutc)
|
|||||||
{
|
{
|
||||||
m_nUTC=nutc;
|
m_nUTC=nutc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPlotter::drawTotalPower(float pdB)
|
||||||
|
{
|
||||||
|
m_pdB=pdB;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPlotter::restartTotalPower()
|
||||||
|
{
|
||||||
|
m_x=0;
|
||||||
|
}
|
||||||
|
@ -34,6 +34,7 @@ public:
|
|||||||
QSize sizeHint() const Q_DECL_OVERRIDE;
|
QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void draw(float swide[], bool bScroll, bool bRed); //Update the waterfall
|
void draw(float swide[], bool bScroll, bool bRed); //Update the waterfall
|
||||||
|
void drawTotalPower(float pdB);
|
||||||
void replot();
|
void replot();
|
||||||
void SetRunningState(bool running);
|
void SetRunningState(bool running);
|
||||||
void setPlotZero(int plotZero);
|
void setPlotZero(int plotZero);
|
||||||
@ -81,12 +82,15 @@ public:
|
|||||||
bool Reference() const {return m_bReference;}
|
bool Reference() const {return m_bReference;}
|
||||||
void setQ65_Sync(bool b) {m_bQ65_Sync = b;}
|
void setQ65_Sync(bool b) {m_bQ65_Sync = b;}
|
||||||
bool Q65_Sync() const {return m_bQ65_Sync;}
|
bool Q65_Sync() const {return m_bQ65_Sync;}
|
||||||
|
void setTotalPower(bool b) {m_bTotalPower = b;}
|
||||||
|
bool TotalPower() const {return m_bTotalPower;}
|
||||||
void drawRed(int ia, int ib, float swide[]);
|
void drawRed(int ia, int ib, float swide[]);
|
||||||
void setVHF(bool bVHF);
|
void setVHF(bool bVHF);
|
||||||
void setRedFile(QString fRed);
|
void setRedFile(QString fRed);
|
||||||
void setFST4_FreqRange(int fLow,int fHigh);
|
void setFST4_FreqRange(int fLow,int fHigh);
|
||||||
void setSingleDecode(bool b);
|
void setSingleDecode(bool b);
|
||||||
void setDiskUTC(int nutc);
|
void setDiskUTC(int nutc);
|
||||||
|
void restartTotalPower();
|
||||||
|
|
||||||
bool scaleOK () const {return m_bScaleOK;}
|
bool scaleOK () const {return m_bScaleOK;}
|
||||||
signals:
|
signals:
|
||||||
@ -116,12 +120,15 @@ private:
|
|||||||
bool m_bReference;
|
bool m_bReference;
|
||||||
bool m_bReference0;
|
bool m_bReference0;
|
||||||
bool m_bQ65_Sync;
|
bool m_bQ65_Sync;
|
||||||
|
bool m_bTotalPower;
|
||||||
bool m_bVHF;
|
bool m_bVHF;
|
||||||
bool m_bSingleDecode;
|
bool m_bSingleDecode;
|
||||||
bool m_bFirst=true;
|
bool m_bFirst=true;
|
||||||
bool m_bResized;
|
bool m_bResized;
|
||||||
|
|
||||||
float m_fSpan;
|
float m_fSpan;
|
||||||
|
float m_pdB=0.0;
|
||||||
|
float m_vpixperdiv;
|
||||||
|
|
||||||
qint32 m_plotZero;
|
qint32 m_plotZero;
|
||||||
qint32 m_plotGain;
|
qint32 m_plotGain;
|
||||||
@ -137,6 +144,7 @@ private:
|
|||||||
qint32 m_nfa;
|
qint32 m_nfa;
|
||||||
qint32 m_nfb;
|
qint32 m_nfb;
|
||||||
qint32 m_nUTC;
|
qint32 m_nUTC;
|
||||||
|
qint32 m_x=0;
|
||||||
|
|
||||||
QPixmap m_WaterfallPixmap;
|
QPixmap m_WaterfallPixmap;
|
||||||
QPixmap m_2DPixmap;
|
QPixmap m_2DPixmap;
|
||||||
|
@ -71,11 +71,13 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
|
|||||||
ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool());
|
ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool());
|
||||||
ui->widePlot->setReference(m_settings->value("Reference",false).toBool());
|
ui->widePlot->setReference(m_settings->value("Reference",false).toBool());
|
||||||
ui->widePlot->setQ65_Sync(m_settings->value("Q65_Sync",false).toBool());
|
ui->widePlot->setQ65_Sync(m_settings->value("Q65_Sync",false).toBool());
|
||||||
|
ui->widePlot->setTotalPower(m_settings->value("TotalPower",false).toBool());
|
||||||
if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0);
|
if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0);
|
||||||
if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1);
|
if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1);
|
||||||
if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2);
|
if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2);
|
||||||
if(ui->widePlot->Reference()) ui->spec2dComboBox->setCurrentIndex(3);
|
if(ui->widePlot->Reference()) ui->spec2dComboBox->setCurrentIndex(3);
|
||||||
if(ui->widePlot->Q65_Sync()) ui->spec2dComboBox->setCurrentIndex(4);
|
if(ui->widePlot->Q65_Sync()) ui->spec2dComboBox->setCurrentIndex(4);
|
||||||
|
if(ui->widePlot->TotalPower()) ui->spec2dComboBox->setCurrentIndex(5);
|
||||||
int nbpp=m_settings->value("BinsPerPixel",2).toInt();
|
int nbpp=m_settings->value("BinsPerPixel",2).toInt();
|
||||||
ui->widePlot->setBinsPerPixel(nbpp);
|
ui->widePlot->setBinsPerPixel(nbpp);
|
||||||
ui->sbPercent2dPlot->setValue(m_Percent2DScreen);
|
ui->sbPercent2dPlot->setValue(m_Percent2DScreen);
|
||||||
@ -133,6 +135,7 @@ void WideGraph::saveSettings() //saveS
|
|||||||
m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg());
|
m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg());
|
||||||
m_settings->setValue ("Reference", ui->widePlot->Reference());
|
m_settings->setValue ("Reference", ui->widePlot->Reference());
|
||||||
m_settings->setValue ("Q65_Sync", ui->widePlot->Q65_Sync());
|
m_settings->setValue ("Q65_Sync", ui->widePlot->Q65_Sync());
|
||||||
|
m_settings->setValue ("TotalPower", ui->widePlot->TotalPower());
|
||||||
m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ());
|
m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ());
|
||||||
m_settings->setValue ("StartFreq", ui->widePlot->startFreq ());
|
m_settings->setValue ("StartFreq", ui->widePlot->startFreq ());
|
||||||
m_settings->setValue ("WaterfallPalette", m_waterfallPalette);
|
m_settings->setValue ("WaterfallPalette", m_waterfallPalette);
|
||||||
@ -148,11 +151,12 @@ void WideGraph::drawRed(int ia, int ib)
|
|||||||
ui->widePlot->drawRed(ia,ib,m_swide);
|
ui->widePlot->drawRed(ia,ib,m_swide);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) //dataSink2
|
void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata, float pdB) //dataSink2
|
||||||
{
|
{
|
||||||
static float splot[NSMAX];
|
static float splot[NSMAX];
|
||||||
int nbpp = ui->widePlot->binsPerPixel();
|
int nbpp = ui->widePlot->binsPerPixel();
|
||||||
|
|
||||||
|
if(ui->widePlot->TotalPower()) ui->widePlot->drawTotalPower(pdB);
|
||||||
//Average spectra over specified number, m_waterfallAvg
|
//Average spectra over specified number, m_waterfallAvg
|
||||||
if (m_n==0) {
|
if (m_n==0) {
|
||||||
for (int i=0; i<NSMAX; i++)
|
for (int i=0; i<NSMAX; i++)
|
||||||
@ -313,6 +317,7 @@ void WideGraph::on_spec2dComboBox_currentIndexChanged(int index)
|
|||||||
ui->widePlot->setLinearAvg(false);
|
ui->widePlot->setLinearAvg(false);
|
||||||
ui->widePlot->setReference(false);
|
ui->widePlot->setReference(false);
|
||||||
ui->widePlot->setQ65_Sync(false);
|
ui->widePlot->setQ65_Sync(false);
|
||||||
|
ui->widePlot->setTotalPower(false);
|
||||||
ui->smoSpinBox->setEnabled(false);
|
ui->smoSpinBox->setEnabled(false);
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
@ -332,6 +337,9 @@ void WideGraph::on_spec2dComboBox_currentIndexChanged(int index)
|
|||||||
case 4:
|
case 4:
|
||||||
ui->widePlot->setQ65_Sync(true);
|
ui->widePlot->setQ65_Sync(true);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
ui->widePlot->setTotalPower(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
replot();
|
replot();
|
||||||
}
|
}
|
||||||
@ -473,6 +481,7 @@ void WideGraph::on_zeroSlider_valueChanged(int value) //Zero
|
|||||||
void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2
|
void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2
|
||||||
{
|
{
|
||||||
ui->widePlot->setPlot2dGain(value);
|
ui->widePlot->setPlot2dGain(value);
|
||||||
|
if(ui->widePlot->TotalPower()) return;
|
||||||
if(ui->widePlot->scaleOK ()) {
|
if(ui->widePlot->scaleOK ()) {
|
||||||
ui->widePlot->draw(m_swide,false,false);
|
ui->widePlot->draw(m_swide,false,false);
|
||||||
if(m_mode=="Q65") ui->widePlot->draw(m_swide,false,true);
|
if(m_mode=="Q65") ui->widePlot->draw(m_swide,false,true);
|
||||||
@ -482,6 +491,7 @@ void WideGraph::on_gain2dSlider_valueChanged(int value) //Gain2
|
|||||||
void WideGraph::on_zero2dSlider_valueChanged(int value) //Zero2
|
void WideGraph::on_zero2dSlider_valueChanged(int value) //Zero2
|
||||||
{
|
{
|
||||||
ui->widePlot->setPlot2dZero(value);
|
ui->widePlot->setPlot2dZero(value);
|
||||||
|
if(ui->widePlot->TotalPower()) return;
|
||||||
if(ui->widePlot->scaleOK ()) {
|
if(ui->widePlot->scaleOK ()) {
|
||||||
ui->widePlot->draw(m_swide,false,false);
|
ui->widePlot->draw(m_swide,false,false);
|
||||||
if(m_mode=="Q65") ui->widePlot->draw(m_swide,false,true);
|
if(m_mode=="Q65") ui->widePlot->draw(m_swide,false,true);
|
||||||
@ -540,3 +550,8 @@ void WideGraph::setDiskUTC(int nutc)
|
|||||||
{
|
{
|
||||||
ui->widePlot->setDiskUTC(nutc);
|
ui->widePlot->setDiskUTC(nutc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WideGraph::restartTotalPower()
|
||||||
|
{
|
||||||
|
ui->widePlot->restartTotalPower();
|
||||||
|
}
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
explicit WideGraph(QSettings *, QWidget *parent = 0);
|
explicit WideGraph(QSettings *, QWidget *parent = 0);
|
||||||
~WideGraph ();
|
~WideGraph ();
|
||||||
|
|
||||||
void dataSink2(float s[], float df3, int ihsym, int ndiskdata);
|
void dataSink2(float s[], float df3, int ihsym, int ndiskdata, float pdB);
|
||||||
void setRxFreq(int n);
|
void setRxFreq(int n);
|
||||||
int rxFreq();
|
int rxFreq();
|
||||||
int nStartFreq();
|
int nStartFreq();
|
||||||
@ -51,6 +51,7 @@ public:
|
|||||||
void setFST4_FreqRange(int fLow,int fHigh);
|
void setFST4_FreqRange(int fLow,int fHigh);
|
||||||
void setSingleDecode(bool b);
|
void setSingleDecode(bool b);
|
||||||
void setDiskUTC(int nutc);
|
void setDiskUTC(int nutc);
|
||||||
|
void restartTotalPower();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void freezeDecode2(int n);
|
void freezeDecode2(int n);
|
||||||
|
@ -340,6 +340,11 @@
|
|||||||
<string>Q65_Sync</string>
|
<string>Q65_Sync</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Total power (dB)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="2">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user