Merge branch 'release-2.5.0'

This commit is contained in:
Bill Somerville 2021-06-28 05:15:39 +01:00
commit 2c07d5af3e
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
42 changed files with 1365 additions and 1201 deletions

View File

@ -71,7 +71,7 @@ message (STATUS "******************************************************")
include (set_build_type)
# RC 0 or omitted is a development build, GA is a General Availability release build
set_build_type (RC 1)
set_build_type (RC 2)
set (wsjtx_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${BUILD_TYPE_REVISION}")
#
@ -169,6 +169,7 @@ set (fort_qt_CXXSRCS
)
set (wsjt_qt_CXXSRCS
helper_functions.cpp
qt_helpers.cpp
widgets/MessageBox.cpp
MetaDataRegistry.cpp
@ -237,6 +238,7 @@ set (wsjt_qt_CXXSRCS
Network/NetworkAccessManager.cpp
widgets/LazyFillComboBox.cpp
widgets/CheckableItemComboBox.cpp
widgets/BandComboBox.cpp
)
set (wsjt_qtmm_CXXSRCS

View File

@ -3,6 +3,7 @@
#include <QApplication>
#include <boost/log/core.hpp>
#include "Logger.hpp"
class QObject;
@ -12,8 +13,8 @@ class QEvent;
// We can't use the GUI after QApplication::exit() is called so
// uncaught exceptions can get lost on Windows systems where there is
// no console terminal, so here we override QApplication::notify() and
// wrap the base class call with a try block to catch and display
// exceptions in a message box.
// wrap the base class call with a try block to catch and log any
// uncaught exceptions.
//
class ExceptionCatchingApplication
: public QApplication
@ -31,12 +32,16 @@ public:
}
catch (std::exception const& e)
{
LOG_FATAL (e.what ());
LOG_FATAL ("Unexpected exception caught in event loop: " << e.what ());
}
catch (...)
{
LOG_FATAL ("Unexpected fatal error");
LOG_FATAL ("Unexpected unknown exception caught in event loop");
}
// There's nowhere to go from here as Qt will not pass exceptions
// through the event loop, so we must abort.
boost::log::core::get ()->flush ();
qFatal ("Aborting");
return false;
}
};

40
NEWS
View File

@ -12,6 +12,46 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.5.0-rc2
Jun 28, 2021
-------------------------
Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0. Changes
in the package since WSJT-X 2.5.0-rc1 include the following
enhancements and defect repairs:
MAP65:
- Compute polarization angle for Xpol systems and display to nearest
degree
- Compute and display the recommended Tx polarization
- Protect against Fortran bounds errors in several places
- Insert leading 0 when needed in UTC hours and minutes on waterfall
- Wideband Q65 synchronization corrected to include single-polarization
mode
- Corrected a one-symbol (0.6 s) delay in Q65 Tx audio
- Basic instruction document for building an MS Windows portaudio DLL
for MAP65 users who are unable to use WDM/KS drivers for their
multi-channel sound cards.
WSJT-X (including the decoder for Q65 used by MAP65):
- Increase maximum DT to 5.5 s when EME decoding is enabled in Q65
- Fix generation of Tx5 message when "hiscall" has suffix /P or /R.
- Improve width management of GUI's band-selection combo box
- Restore plotting of Q65 sync curve after a q3 decode
- Disable selection of "View | Message Averaging F7" for modes
other than JT4 and JT65
- Switching to Q65 mode now defaults to "Decode | Fast"
- Repair a long standing regression with message generation for
72-bit modes when using a compound callsign.
- Repair a defect in diagnostic logging that could cause crashes on
some platforms.
- Repair a defect which failed to strip leading and trailing spaces
on input of callsigns during validation.
- Hamlib updates including repair of defects with PTT handling on a
separate serial port via rigctld, delayed PTT with Elecraft K3
series rigs, and support for the Icom IC-575 rig.
- Updated CTY.DAT database
Release: WSJT-X 2.5.0-rc1
Jun 3, 2021
-------------------------

View File

@ -12,6 +12,46 @@
Copyright 2001 - 2021 by Joe Taylor, K1JT.
Release: WSJT-X 2.5.0-rc2
Jun 28, 2021
-------------------------
Remember that the WSJT-X 2.5.0 package includes MAP65 3.0.0. Changes
in the package since WSJT-X 2.5.0-rc1 include the following
enhancements and defect repairs:
MAP65:
- Compute polarization angle for Xpol systems and display to nearest
degree
- Compute and display the recommended Tx polarization
- Protect against Fortran bounds errors in several places
- Insert leading 0 when needed in UTC hours and minutes on waterfall
- Wideband Q65 synchronization corrected to include single-polarization
mode
- Corrected a one-symbol (0.6 s) delay in Q65 Tx audio
- Basic instruction document for building an MS Windows portaudio DLL
for MAP65 users who are unable to use WDM/KS drivers for their
multi-channel sound cards.
WSJT-X (including the decoder for Q65 used by MAP65):
- Increase maximum DT to 5.5 s when EME decoding is enabled in Q65
- Fix generation of Tx5 message when "hiscall" has suffix /P or /R.
- Improve width management of GUI's band-selection combo box
- Restore plotting of Q65 sync curve after a q3 decode
- Disable selection of "View | Message Averaging F7" for modes
other than JT4 and JT65
- Switching to Q65 mode now defaults to "Decode | Fast"
- Repair a long standing regression with message generation for
72-bit modes when using a compound callsign.
- Repair a defect in diagnostic logging that could cause crashes on
some platforms.
- Repair a defect which failed to strip leading and trailing spaces
on input of callsigns during validation.
- Hamlib updates including repair of defects with PTT handling on a
separate serial port via rigctld, delayed PTT with Elecraft K3
series rigs, and support for the Icom IC-575 rig.
- Updated CTY.DAT database
Release: WSJT-X 2.5.0-rc1
Jun 3, 2021
-------------------------

View File

@ -93,7 +93,7 @@ namespace
<< boost::log::add_value ("Line", context.line)
<< boost::log::add_value ("File", file)
<< boost::log::add_value ("Function", function)
<< msg.toStdWString ();
<< msg.toStdString ();
}
else
{
@ -101,7 +101,7 @@ namespace
<< boost::log::add_value ("Line", context.line)
<< boost::log::add_value ("File", file)
<< boost::log::add_value ("Function", function)
<< context.category << ": " << msg.toStdWString ();
<< context.category << ": " << msg.toStdString ();
}
}
@ -132,7 +132,7 @@ namespace
#else
, keywords::file_name =
#endif
app_data.absoluteFilePath ("logs/wsjtx_syslog_%Y-%m.log").toStdString ()
app_data.absoluteFilePath ("logs/wsjtx_syslog_%Y-%m.log").toStdWString ()
, keywords::time_based_rotation = sinks::file::rotation_at_time_point (gregorian::greg_day (1), 0, 0, 0)
, keywords::open_mode = std::ios_base::out | std::ios_base::app
#if BOOST_VERSION / 100 >= 1063

1206
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -214,7 +214,7 @@ a suitable location like ~/build and change working directory to it:
Configure and build and install the library in a suitable place (I use
~/local as a root directory for installed packages.
~/src/portaudio/configure --prefix=$(HOME)/local/portaudio/mingw64 \
~/src/portaudio/configure --prefix=$HOME/local/portaudio/mingw64 \
--with-winapi=wmme,directx,wdmks --disable-static --enable-shared CFLAGS=-DNDEBUG
make && make install

View File

@ -0,0 +1,76 @@
Building the MS Windows portaudio DLL with ASIO Support
=======================================================
Some MAP65 users may not be able to use WDM/KS hosted audio devices
due to sharing issues with other applications, to circumvent this they
can build a version of the portaudio DLL with ASIO support. We cannot
provide a portaudio DLL with ASIO support as the Steinberg ASIO SDK
license prevents redistribution of drivers or hosting applications
without a commercial license agreement, nor is the Steinberg ASIO SDK
license compatible with the GPL v3 license that MAP65 is released
under. Users may build a portaudio DLL themselves, strictly for
personal use, under the terms of the Steinberg ASIO license.
Building portaudio on MS Windows is done most easily using the MinGW
(GNU) tool-chain which can be installed on MS Windows using the MSYS2
unix like environment which in turn includes a package manager
(pacman) that allows simple installation of necessary prerequisite
packages like the MinGW 64-bit tool-chain. To install MSYS2 download
the latest 64-bit installer from the MSYS2 project web site. This page
contains links to the installer download and detailed instructions to
install and bring up-to-date the base MSYS2 packages.
https://www.msys2.org/wiki/MSYS2-installation/
Take particular care to restart the MSYS2 shell window when directed
to.
Once MSYS2 is installed you will find a start menu entry labelled
"MSYS2 MinGW 64-bit", use that to start a fresh MSYS2 shell window for
the rest of these instructions.
The first step is to install some prerequisite packages which contain
the tools needed to prepare and build the portaudio DLL. Execute the
following command to do that:
pacman -S make diffutils unzip mingw-w64-x86_64-gcc sed tar curl
Then make directories to put downloaded sources in and for building:
mkdir -p ~/src ~/build/portaudio
Fetch and unpack the Steinberg ASIO SDK (note the ASIO SDK license
document included, particularly that it strictly disallows
redistribution of the DLL we will be building here), and portaudio
sources:
curl -Lo ~/src/asiosdk.zip https://www.steinberg.net/asiosdk
(cd ~/src ; unzip asiosdk.zip)
curl -O --output-dir ~/src \
http://files.portaudio.com/archives/pa_stable_v190700_20210406.tgz
tar -C ~/src -xf ~/src/pa_stable_v190700_20210406.tgz
Patch and build the portaudio library:
sed -i -e 's/-luuid//g' ~/src/portaudio/configure
cd ~/build/portaudio
~/src/portaudio/configure --with-winapi=wmme,directx,wdmks,asio \
--with-asiodir=$HOME/src/asiosdk_2.3.3_2019-06-14 \
--disable-static --enable-shared
make -j
You can check the library build is working by running a test program
that was also built:
bin/pa_devs
which should list every audio device on your system by every host API,
if all is well that should include the audio devices on your system
with ASIO drivers.
Copy the new portaudio DLL to your WSJT-X/MAP65 installation directory:
cp lib/.libs/libportaudio-2.dll /c/WSJT/wsjtx/bin/
Note that if you upgrade WSJT-X you will need to copy this DLL again
since it will be overwritten by one with no ASIO support.

View File

@ -141,7 +141,7 @@ C:\Tools\boost-build\MinGW32\bin\b2 -j8 toolset=gcc ^
--build-dir=%USERPROFILE%\build\boost ^
address-model=32 architecture=x86 variant=debug,release ^
link=shared threading=multi ^
--with-log --with-stacktrace --prefix=C:\Tools\boost install
--with-log --with-stacktrace --with-timer --prefix=C:\Tools\boost install
If all is well you should see the following line about a 1/3 of the
way through the initial configuration steps.
@ -188,7 +188,7 @@ cd ..\..
C:\Tools\boost-build\MinGW64\bin\b2 -j8 toolset=gcc-8~64 ^
address-model=64 architecture=x86 variant=debug,release ^
link=shared threading=multi ^
--with-log --with-stacktrace ^
--with-log --with-stacktrace --with-timer ^
--build-dir=%USERPROFILE%\build\boost ^
--prefix=C:\Tools\boost install
@ -206,9 +206,11 @@ After some time it should complete with something like:
warnings can usually be ignored. If successful; you can release some
space by cleaning the build tree:
C:\Tools\boost-build\MinGW32\bin\b2 toolset=gcc-8~64 ^
C:\Tools\boost-build\MinGW64\bin\b2 toolset=gcc-8~64 ^
address-model=64 --build-dir=%USERPROFILE%\build\boost ^
--build-type=complete clean
Run-time Environment
--------------------

View File

@ -1,9 +1,9 @@
#include "getfile.h"
#include <QDir>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#include <random>
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@ -22,155 +22,6 @@
#include <err.h>
#endif
#include "commons.h"
extern dec_data dec_data;
void getfile(QString fname, int ntrperiod)
{
// struct WAVHDR {
// char ariff[4];
// int lenfile;
// char awave[4];
// char afmt[4];
// int lenfmt;
// short nfmt2;
// short nchan2;
// int nsamrate;
// int nbytesec;
// short nbytesam2;
// short nbitsam2;
// char adata[4];
// int ndata;
// } hdr;
char name[512];
strncpy(name,fname.toLatin1(), sizeof (name) - 1);
name[sizeof (name) - 1] = '\0';
FILE* fp=fopen(name,"rb");
int i1=fname.lastIndexOf("/");
QString baseName=fname.mid(i1+1);
i1=fname.indexOf(".wav",0,Qt::CaseInsensitive);
dec_data.params.nutc=0;
if(i1>0) {
int i0=fname.indexOf("_",-11);
if(i1==i0+7) {
dec_data.params.nutc=fname.mid(i1-6,6).toInt();
} else {
dec_data.params.nutc=100*fname.mid(i1-4,4).toInt();
}
}
if(ntrperiod > 120 or ntrperiod <0) ntrperiod=120;
int npts=ntrperiod*12000;
memset(dec_data.d2,0,2*npts);
if(fp != NULL) {
struct
{
char id[4];
uint32_t size;
} desc;
char type[4];
struct
{
uint16_t nfmt2;
uint16_t nchan2;
uint32_t nsamrate;
uint32_t nbytesec;
uint16_t nbytesam2;
uint16_t nbitsam2;
} fmt;
// read header
if (fread(&desc, sizeof desc, 1, fp) < 1) return; // RIFF
if (fread(type, sizeof type, 1, fp) < 1) return; // WAVE
do
{
if (fread(&desc, sizeof desc, 1, fp) < 1) return; // WAVE component
if (!memcmp(desc.id,"fmt ",4)) {
fpos_t pos;
fgetpos(fp,&pos);
if (fread(&fmt,sizeof fmt,1,fp) < 1) return;
fsetpos(fp,&pos);
}
if (!memcmp(desc.id,"data",sizeof desc.id)) break;
} while (!fseek(fp,(desc.size + 1) / 2 * 2,SEEK_CUR));
// Read (and ignore) a 44-byte WAV header; then read data
// int n=fread(&hdr,1,44,fp);
int n=fread(dec_data.d2,2,npts,fp);
if(fmt.nsamrate==11025) wav12_(dec_data.d2,dec_data.d2,&n,(short*)&fmt.nbitsam2);
fclose(fp);
dec_data.params.newdat=1;
dec_data.params.kin=n;
}
}
void savewav(QString fname, int ntrperiod)
{
struct {
char ariff[4]; //ChunkID: "RIFF"
int nchunk; //ChunkSize: 36+SubChunk2Size
char awave[4]; //Format: "WAVE"
char afmt[4]; //Subchunk1ID: "fmt "
int lenfmt; //Subchunk1Size: 16
short int nfmt2; //AudioFormat: 1
short int nchan2; //NumChannels: 1
int nsamrate; //SampleRate: 12000
int nbytesec; //ByteRate: SampleRate*NumChannels*BitsPerSample/8
short int nbytesam2; //BlockAlign: NumChannels*BitsPerSample/8
short int nbitsam2; //BitsPerSample: 16
char adata[4]; //Subchunk2ID: "data"
int ndata; //Subchunk2Size: numSamples*NumChannels*BitsPerSample/8
} hdr;
int npts=ntrperiod*12000;
// qint16* buf=(qint16*)malloc(2*npts);
char name[512];
strncpy(name,fname.toLatin1(),sizeof (name) - 1);
name[sizeof (name) - 1] = '\0';
FILE* fp=fopen(name,"wb");
if(fp != NULL) {
// Write a WAV header
hdr.ariff[0]='R';
hdr.ariff[1]='I';
hdr.ariff[2]='F';
hdr.ariff[3]='F';
hdr.nchunk=36 + 2*npts;
hdr.awave[0]='W';
hdr.awave[1]='A';
hdr.awave[2]='V';
hdr.awave[3]='E';
hdr.afmt[0]='f';
hdr.afmt[1]='m';
hdr.afmt[2]='t';
hdr.afmt[3]=' ';
hdr.lenfmt=16;
hdr.nfmt2=1;
hdr.nchan2=1;
hdr.nsamrate=12000;
hdr.nbytesec=2*12000;
hdr.nbytesam2=2;
hdr.nbitsam2=16;
hdr.adata[0]='d';
hdr.adata[1]='a';
hdr.adata[2]='t';
hdr.adata[3]='a';
hdr.ndata=2*npts;
fwrite(&hdr,sizeof(hdr),1,fp);
// memcpy(dec_data.d2,buf,2*npts);
// fwrite(buf,2,npts,fp);
fwrite(dec_data.d2,2,npts,fp);
fclose(fp);
}
// free(buf);
}
//#define MAX_RANDOM 0x7fffffff
/* Generate gaussian random float with mean=0 and std_dev=1 */
float gran()
@ -202,72 +53,3 @@ float gran()
return v2*fac;
#endif
}
int ptt(int nport, int ntx, int* iptt, int* nopen)
{
#ifdef WIN32
static HANDLE hFile;
char s[10];
int i3=1,i4=1,i5=1,i6=1,i9=1,i00=1; //Defs to silence compiler warning
if(nport==0) {
*iptt=ntx;
return 0;
}
if(ntx && (!(*nopen))) {
sprintf(s,"\\\\.\\COM%d",nport);
hFile=CreateFile(TEXT(s),GENERIC_WRITE,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE) {
QString t;
t = t.asprintf("Cannot open COM port %d for PTT\n",nport);
return 1;
}
*nopen=1;
}
if(ntx && *nopen) {
i3=EscapeCommFunction(hFile,SETRTS);
i5=EscapeCommFunction(hFile,SETDTR);
*iptt=1;
}
else {
i4=EscapeCommFunction(hFile,CLRRTS);
i6=EscapeCommFunction(hFile,CLRDTR);
i9=EscapeCommFunction(hFile,CLRBREAK);
i00=CloseHandle(hFile);
*iptt=0;
*nopen=0;
}
if((i3+i4+i5+i6+i9+i00)==-999) return 1; //Silence compiler warning
return 0;
#else
int control=TIOCM_RTS | TIOCM_DTR;
// int control = TIOCM_RTS;
static int fd;
if(*nopen==0) {
fd=open("/dev/ttyUSB0",O_RDWR | O_NONBLOCK);
if(fd<0) {
return -1;
}
*nopen=1;
}
if(ntx) {
ioctl(fd, TIOCMBIS, &control);
*iptt=1;
*nopen=1;
} else {
ioctl(fd, TIOCMBIC, &control);
close(fd);
*iptt=0;
*nopen=0;
}
return 0;
#endif
if((nport+ntx+(*iptt)==-99999)) *nopen=0; //Silence compiler warning
return 0;
}

View File

@ -1,19 +1,8 @@
// -*- Mode: C++ -*-
#ifndef GETFILE_H
#define GETFILE_H
#include <QString>
#include <QFile>
#include <QDebug>
void getfile(QString fname, int ntrperiod);
float gran();
//int ptt(int* nport, int* ntx, int* iptt);
int ptt(int nport, int ntx, int* iptt, int* nopen);
extern "C" {
int ptt_(int nport, int ntx, int* iptt, int* nopen);
void wav12_(short d2[], short d1[], int* nbytes, short* nbitsam2);
}
#endif // GETFILE_H

33
helper_functions.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "helper_functions.h"
double tx_duration(QString mode, double trPeriod, int nsps, bool bFast9)
{
double txt=0.0;
if(mode=="FT4") txt=1.0 + 105*576/12000.0; // FT4
if(mode=="FT8") txt=1.0 + 79*1920/12000.0; // FT8
if(mode=="JT4") txt=1.0 + 207.0*2520/11025.0; // JT4
if(mode=="JT9") txt=1.0 + 85.0*nsps/12000.0; // JT9
if(mode=="JT65") txt=1.0 + 126*4096/11025.0; // JT65
if(mode=="Q65") { // Q65
if(trPeriod==15) txt=0.5 + 85*1800/12000.0;
if(trPeriod==30) txt=0.5 + 85*3600/12000.0;
if(trPeriod==60) txt=1.0 + 85*7200/12000.0;
if(trPeriod==120) txt=1.0 + 85*16000/12000.0;
if(trPeriod==300) txt=1.0 + 85*41472/12000.0;
}
if(mode=="WSPR") txt=2.0 + 162*8192/12000.0; // WSPR
if(mode=="FST4" or mode=="FST4W") { //FST4, FST4W
if(trPeriod==15) txt=1.0 + 160*720/12000.0;
if(trPeriod==30) txt=1.0 + 160*1680/12000.0;
if(trPeriod==60) txt=1.0 + 160*3888/12000.0;
if(trPeriod==120) txt=1.0 + 160*8200/12000.0;
if(trPeriod==300) txt=1.0 + 160*21504/12000.0;
if(trPeriod==900) txt=1.0 + 160*66560/12000.0;
if(trPeriod==1800) txt=1.0 + 160*134400/12000.0;
}
if(mode=="MSK144" or bFast9) {
txt=trPeriod-0.25; // JT9-fast, MSK144
}
if(mode=="Echo") txt=2.4;
return txt;
}

7
helper_functions.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef HELPER_FUNCTIONS_H
#define HELPER_FUNCTIONS_H
#include <QString>
double tx_duration(QString mode, double trPeriod, int nsps, bool bFast9);
#endif // HELPER_FUNCTIONS_H

View File

@ -148,13 +148,16 @@ contains
nused=1
iavg=0
call timer('q65_dec0',0)
! Call top-level routine in q65 module: establish sync and try for a q3 decode.
! Call top-level routine in q65 module: establish sync and try for a
! q3 or q0 decode.
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec)
call timer('q65_dec0',1)
! write(*,3001) '=a',sum(abs(float(iwave))),nfqso,ntol,ndepth,xdt,f0,idec
!3001 format(a2,f15.0,3i5,f7.2,f7.1,i5)
if(idec.ge.0) then
dtdec=xdt !We have a list-decode result at nfqso
dtdec=xdt !We have a q3 or q0 decode at nfqso
f0dec=f0
go to 100
endif
@ -207,6 +210,7 @@ contains
call q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
emedelay,xdt,f0,snr1,width,dat4,snr2,idec)
call timer('list_avg',1)
if(idec.ge.0) then
dtdec=xdt !We have a list-decode result from averaged data
f0dec=f0

View File

@ -124,7 +124,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
dtstep=nsps/(NSTEP*12000.0) !Step size in seconds
lag1=-1.0/dtstep
lag2=1.0/dtstep + 0.9999
if(nsps.ge.3600 .and. emedelay.gt.0) lag2=4.0/dtstep + 0.9999 !Include EME
if(nsps.ge.3600 .and. emedelay.gt.0) lag2=5.5/dtstep + 0.9999 !Include EME
j0=0.5/dtstep
if(nsps.ge.7200) j0=1.0/dtstep !Nominal start-signal index
@ -139,16 +139,17 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
endif
i0=nint(nfqso/df) !Target QSO frequency
if(i0-64.lt.1 .or. i0-65+LL.gt.iz) go to 900 !Frequency out of range
call pctile(s1(i0-64:i0-65+LL,1:jz),LL*jz,45,base)
ii1=max(1,i0-64)
ii2=i0-65+LL
call pctile(s1(ii1:ii2,1:jz),ii2-ii1+1*jz,45,base)
s1=s1/base
s1raw=s1
! Apply fast AGC to the symbol spectra
s1max=20.0 !Empirical choice
do j=1,jz !### Maybe wrong way? ###
smax=maxval(s1(i0-64:i0-65+LL,j))
if(smax.gt.s1max) s1(i0-64:i0-65+LL,j)=s1(i0-64:i0-65+LL,j)*s1max/smax
smax=maxval(s1(ii1:ii2,j))
if(smax.gt.s1max) s1(ii1:ii2,j)=s1(ii1:ii2,j)*s1max/smax
enddo
dat4=0
@ -162,9 +163,10 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call timer('list_dec',0)
call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded)
call timer('list_dec',1)
if(idec.eq.3) go to 900 !Good q3 decode, we're done
! If idec=3 we have a q3 decode. Continue to compute sync curve for plotting.
endif
! Get 2d CCF and ccf2 using sync symbols only
if(iavg.eq.0) then
call timer('ccf_22a ',0)
call q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
@ -172,7 +174,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call timer('ccf_22a ',1)
endif
! Get 2d CCF and ccf2 using sync symbols only
! Get 2d CCF and ccf2_avg using sync symbols only
if(iavg.ge.1) then
call timer('ccf_22b ',0)
call q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
@ -211,7 +213,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
call q65_write_red(iz,xdt,ccf2_avg,ccf2)
if(iavg.eq.0 .or. iavg.eq.2) then
if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then
call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded)
endif
@ -439,8 +441,8 @@ subroutine q65_ccf_22(s1,iz,jz,nfqso,ntol,ndepth,ntrperiod,iavg,ipk,jpk, &
ib=min(nfb,4900)/df
if(nqd.ne.1 .or. iavg.ne.0) max_drift=0
if(max_drift.ne.0) then
ia=nint((nfqso-ntol)/df)
ib=nint((nfqso+ntol)/df)
ia=max(nint(100/df),nint((nfqso-ntol)/df))
ib=min(nint(4900/df),nint((nfqso+ntol)/df))
endif
do i=ia,ib

View File

@ -73,7 +73,7 @@ program test_q65
! 1 2 3 4 5 6 7
! 1234567890123456789012345678901234567890123456789012345678901234567890123456'
cmd1='q65sim "K1ABC W9XYZ EN37 " A 1500 5.0 0.0 0.0 1 60 100 -10.0 > junk0'
cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 3 -b A -Q 3 -f 1500 *.wav > junk'
cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 3 -b A -Q 3 -f 1500 -X 32 *.wav > junk'
write(cmd1(10:33),'(a)') '"'//msg//'"'
cmd1(35:35)=csubmode

View File

@ -60,8 +60,8 @@ set (libm65_FSRCS
nchar.f90
noisegen.f90
packjt.f90
# pctile.f90
pfxdump.f90
polfit.f90
recvpkt.f90
rfile3a.f90
s3avg.f90
@ -80,6 +80,7 @@ set (libm65_FSRCS
trimlist.f90
twkfreq.f90
twkfreq_xy.f90
txpol.f90
wavhdr.f90
f77_wisdom.f

View File

@ -36,7 +36,7 @@ subroutine gen_q65_wave(msg,ntxfreq,mode65,msgsent,iwave,nwave)
j0=0
do i=1,iz
t=t+dt
j=t/tsym
j=t/tsym + 1.0
if(j.ne.j0) then
f=f0 + itone(j)*dfgen
dphi=twopi*dt*f

View File

@ -19,7 +19,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
real*8 fcenter
character*22 msg(MAXMSG)
character*3 shmsg0(4)
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,grid*6,cp*1,cm*1
character mycall*12,hiscall*12,mygrid*6,hisgrid*6,cp*1,cm*1
integer indx(MAXMSG),nsiz(MAXMSG)
logical done(MAXMSG)
logical xpol,bq65,q65b_called
@ -43,12 +43,13 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
mode65=mod(nmode,10)
if(mode65.eq.3) mode65=4
mode_q65=nmode/10
xpol=(nxpol.ne.0)
nts_jt65=2**(mode65-1) !JT65 tone separation factor
nts_q65=2**(mode_q65) !Q65 tone separation factor
if(nagain.eq.0) then
call timer('get_cand',0)
call get_candidates(ss,savg,mfa,mfb,nts_jt65,nts_q65,cand,ncand)
call get_candidates(ss,savg,xpol,mfa,mfb,nts_jt65,nts_q65,cand,ncand)
call timer('get_cand',1)
candec=.false.
endif
@ -66,7 +67,6 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
mcall3a=mcall3b
mousefqso0=mousefqso
xpol=(nxpol.ne.0)
if(.not.xpol) ndphi=0
nsum=0
@ -318,28 +318,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
if(npol.lt.0) npol=npol+180
endif
! If Tx station's grid is in decoded message, compute optimum TxPol
i1=index(decoded,' ')
i2=index(decoded(i1+1:),' ') + i1
grid=' '
if(i2.ge.8 .and. i2.le.18) grid=decoded(i2+1:i2+4)//'mm'
ntxpol=0
cp=' '
if(xpol) then
if(grid(1:1).ge.'A' .and. grid(1:1).le.'R' .and. &
grid(2:2).ge.'A' .and. grid(2:2).le.'R' .and. &
grid(3:3).ge.'0' .and. grid(3:3).le.'9' .and. &
grid(4:4).ge.'0' .and. grid(4:4).le.'9') then
ntxpol=mod(npol-nint(2.0*dpol(mygrid,grid))+720,180)
if(nxant.eq.0) then
cp='H'
if(ntxpol.gt.45 .and. ntxpol.le.135) cp='V'
else
cp='/'
if(ntxpol.ge.90 .and. ntxpol.lt.180) cp='\'
endif
endif
endif
call txpol(xpol,decoded,mygrid,npol,nxant,ntxpol,cp)
if(ndphi.eq.0) then
write(*,1010) nkHz,ndf,npol,nutc,dt,nsync2, &
@ -368,9 +347,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
q65b_called=.true.
f0=cand(icand)%f
call timer('q65b ',0)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
nagain,max_drift,idec)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid, hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,idec)
call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true.
enddo
@ -379,9 +358,9 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
ikhz=mousefqso
f0=freq - (nkhz_center-48.0-1.27046) !### ??? ###
call timer('q65b ',0)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
nagain,max_drift,idec)
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf, &
ntol,xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso, &
newdat,nagain,max_drift,idec)
call timer('q65b ',1)
endif
endif
@ -416,8 +395,8 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
ikhz=nint(freq)
f0=cand(icand)%f
call timer('q65b ',0)
call q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
call q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol, &
xpol,mycall,mygrid,hiscall,hisgrid,mode_q65,f0,fqso,newdat, &
nagain,max_drift,idec)
call timer('q65b ',1)
if(idec.ge.0) candec(icand)=.true.
@ -494,28 +473,8 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
if(npol.lt.0) npol=npol+180
endif
! If Tx station's grid is in decoded message, compute optimum TxPol
i1=index(decoded,' ')
i2=index(decoded(i1+1:),' ') + i1
grid=' '
if(i2.ge.8 .and. i2.le.18) grid=decoded(i2+1:i2+4)//'mm'
ntxpol=0
cp=' '
if(xpol) then
if(grid(1:1).ge.'A' .and. grid(1:1).le.'R' .and. &
grid(2:2).ge.'A' .and. grid(2:2).le.'R' .and. &
grid(3:3).ge.'0' .and. grid(3:3).le.'9' .and. &
grid(4:4).ge.'0' .and. grid(4:4).le.'9') then
ntxpol=mod(npol-nint(2.0*dpol(mygrid,grid))+720,180)
if(nxant.eq.0) then
cp='H'
if(ntxpol.gt.45 .and. ntxpol.le.135) cp='V'
else
cp='/'
if(ntxpol.ge.90 .and. ntxpol.lt.180) cp='\'
endif
endif
endif
call txpol(xpol,decoded,mygrid,npol,nxant,ntxpol,cp)
cmode='#A'
if(mode65.eq.2) cmode='#B'
if(mode65.eq.4) cmode='#C'

86
map65/libm65/polfit.f90 Normal file
View File

@ -0,0 +1,86 @@
subroutine polfit(y,npts,a)
! Input: y(npts) !Expect npts=4
! Output: a(1) = baseline
! a(2) = amplitude
! a(3) = theta (deg)
real y(npts)
real a(3)
real deltaa(3)
integer ipk(1)
save
! Set starting values:
a(1)=minval(y)
a(2)=maxval(y)-a(1)
ipk=maxloc(y)
a(3)=(ipk(1)-1)*45.0
deltaa(1:2)=0.1*(a(2)-a(1))
deltaa(3)=10.0
nterms=3
! Start the iteration
chisqr=0.
chisqr0=1.e6
iters=10
do iter=1,iters
do j=1,nterms
chisq1=fchisq_pol(y,npts,a)
fn=0.
delta=deltaa(j)
10 a(j)=a(j)+delta
chisq2=fchisq_pol(y,npts,a)
if(chisq2.eq.chisq1) go to 10
if(chisq2.gt.chisq1) then
delta=-delta !Reverse direction
a(j)=a(j)+delta
tmp=chisq1
chisq1=chisq2
chisq2=tmp
endif
20 fn=fn+1.0
a(j)=a(j)+delta
chisq3=fchisq_pol(y,npts,a)
if(chisq3.lt.chisq2) then
chisq1=chisq2
chisq2=chisq3
go to 20
endif
! Find minimum of parabola defined by last three points
delta=delta*(1./(1.+(chisq1-chisq2)/(chisq3-chisq2))+0.5)
a(j)=a(j)-delta
deltaa(j)=deltaa(j)*fn/3.
! write(*,4000) iter,j,a,deltaa,chisq2
!4000 format(2i2,2(2x,3f8.2),f12.5)
enddo
chisqr=fchisq_pol(y,npts,a)
! write(*,4000) 0,0,a,chisqr
if(deltaa(1).lt.0.01*(a(2)-a(1)) .and. deltaa(2).lt.0.01*(a(2)-a(1)) &
.and. deltaa(3).lt.1.0) exit
if(chisqr/chisqr0.gt.0.99) exit
a(3)=mod(a(3)+360.0,180.0)
chisqr0=chisqr
enddo
return
end subroutine polfit
real function fchisq_pol(y,npts,a)
real y(npts),a(3)
data rad/57.2957795/
chisq = 0.
do i=1,npts
theta=(i-1)*45.0
yfit=a(1) + a(2)*cos((theta-a(3))/rad)**2
chisq=chisq + (y(i) - yfit)**2
enddo
fchisq_pol=chisq
return
end function fchisq_pol

View File

@ -1,5 +1,6 @@
subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
mycall0,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain,max_drift,idec)
subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
mycall0,mygrid,hiscall0,hisgrid,mode_q65,f0,fqso,newdat,nagain, &
max_drift,idec)
! This routine provides an interface between MAP65 and the Q65 decoder
! in WSJT-X. All arguments are input data obtained from the MAP65 GUI.
@ -16,6 +17,7 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
parameter (MAXFFT1=5376000) !56*96000
parameter (MAXFFT2=336000) !56*6000 (downsampled by 1/16)
parameter (NMAX=60*12000)
parameter (RAD=57.2957795)
! type(hdr) h !Header for the .wav file
integer*2 iwave(60*12000)
complex ca(MAXFFT1),cb(MAXFFT1) !FFTs of raw x,y data
@ -25,10 +27,11 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
real*8 fcenter,freq0
character*12 mycall0,hiscall0
character*12 mycall,hiscall
character*6 hisgrid
character*6 mygrid,hisgrid
character*4 grid4
character*80 line
character*80 wsjtx_dir
character*1 cp,cmode*2
common/cacb/ca,cb
save
@ -88,10 +91,14 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
! 96000 5376000 0.017857143 336000 6000.000
! 95238 5120000 0.018601172 322560 5999.994
if(ipol.eq.1) cz(0:MAXFFT2-1)=cx
if(ipol.eq.2) cz(0:MAXFFT2-1)=0.707*(cx+cy)
if(ipol.eq.3) cz(0:MAXFFT2-1)=cy
if(ipol.eq.4) cz(0:MAXFFT2-1)=0.707*(cx-cy)
poldeg=0.
if(xpol) then
poldeg=sync(ipk)%pol
cz(0:MAXFFT2-1)=cos(poldeg/RAD)*cx + sin(poldeg/RAD)*cy
else
cz(0:MAXFFT2-1)=cx
endif
cz(MAXFFT2)=0.
! Roll off below 500 Hz and above 2500 Hz.
ja=nint(500.0/df)
@ -136,21 +143,30 @@ subroutine q65b(nutc,nqd,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
if(nsnr0.gt.-99) then
nq65df=nint(1000*(0.001*k0*df+nkhz_center-48.0+1.000-1.27046-ikhz))-nfcal
nq65df=nq65df + nfreq0 - 1000
npol=nint(poldeg)
if(nxant.ne.0) then
npol=npol-45
if(npol.lt.0) npol=npol+180
endif
call txpol(xpol,msg0(1:22),mygrid,npol,nxant,ntxpol,cp)
if(nqd.eq.1 .and. abs(nq65df-mousedf).lt.ntol) then
write(line,1020) ikhz,nq65df,45*(ipol-1),nutc,xdt0,nsnr0,msg0(1:27),cq0
1020 format('!',i3.3,i5,i4,i6.4,f5.1,i5,' : ',a27,a3)
write(line,1020) ikhz,nq65df,npol,nutc,xdt0,nsnr0,msg0(1:27),cq0, &
ntxpol,cp
1020 format('!',i3.3,i5,i4,i6.4,f5.1,i5,' : ',a27,a3,i4,1x,a1)
write(*,1100) trim(line)
1100 format(a)
endif
! Write to lu 26, for Messages and Band Map windows
write(26,1014) freq0,nq65df,0,0,0,xdt0,45*(ipol-1),0, &
nsnr0,nutc,msg0(1:22),':',char(ichar('A') + mode_q65-1)
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,':',a1)
cmode=': '
cmode(2:2)=char(ichar('A') + mode_q65-1)
write(26,1014) freq0,nq65df,0,0,0,xdt0,npol,0, &
nsnr0,nutc,msg0(1:22),':',cp,cmode
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2)
! Write to file map65_rx.log:
write(21,1110) freq0,nq65df,xdt0,45*(ipol-1),nsnr0,nutc,msg0(1:28),cq0
write(21,1110) freq0,nq65df,xdt0,npol,nsnr0,nutc,msg0(1:28),cq0
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': A',2x,a3)
endif

View File

@ -41,7 +41,7 @@ program synctest
call timer('synctest',0)
call timer('get_cand',0)
call get_candidates(ss,savg,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
call get_candidates(ss,savg,.true.,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
call timer('get_cand',1)
do k=1,ncand

33
map65/libm65/txpol.f90 Normal file
View File

@ -0,0 +1,33 @@
subroutine txpol(xpol,decoded,mygrid,npol,nxant,ntxpol,cp)
! If Tx station's grid is in decoded message, compute optimum TxPol
character*22 decoded
character*6 mygrid,grid
character*1 cp
logical xpol
ntxpol=0
i1=index(decoded,' ')
i2=index(decoded(i1+1:),' ') + i1
grid=' '
if(i2.ge.8 .and. i2.le.18) grid=decoded(i2+1:i2+4)//'mm'
ntxpol=0
cp=' '
if(xpol .and.grid(1:4).ne.'RR73') then
if(grid(1:1).ge.'A' .and. grid(1:1).le.'R' .and. &
grid(2:2).ge.'A' .and. grid(2:2).le.'R' .and. &
grid(3:3).ge.'0' .and. grid(3:3).le.'9' .and. &
grid(4:4).ge.'0' .and. grid(4:4).le.'9') then
ntxpol=mod(npol-nint(2.0*dpol(mygrid,grid))+720,180)
if(nxant.eq.0) then
cp='H'
if(ntxpol.gt.45 .and. ntxpol.le.135) cp='V'
else
cp='/'
if(ntxpol.ge.90 .and. ntxpol.lt.180) cp='\'
endif
endif
endif
return
end subroutine txpol

View File

@ -4,12 +4,14 @@ module wideband_sync
real :: snr !Relative S/N of sync detection
real :: f !Freq of sync tone, 0 to 96000 Hz
real :: xdt !DT of matching sync pattern, -1.0 to +4.0 s
real :: pol !Polarization angle, degrees
integer :: ipol !Polarization angle, 1 to 4 ==> 0, 45, 90, 135 deg
integer :: iflip !Sync type: JT65 = +/- 1, Q65 = 0
end type candidate
type sync_dat
real :: ccfmax
real :: xdt
real :: pol
integer :: ipol
integer :: iflip
logical :: birdie
@ -17,12 +19,13 @@ module wideband_sync
parameter (NFFT=32768)
parameter (MAX_CANDIDATES=50)
parameter (SNR1_THRESHOLD=4.5)
type(sync_dat) :: sync(NFFT)
integer nkhz_center
contains
subroutine get_candidates(ss,savg,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
subroutine get_candidates(ss,savg,xpol,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
! Search symbol spectra ss() over frequency range nfa to nfb (in kHz) for
! JT65 and Q65 sync patterns. The nts_* variables are the submode tone
@ -33,7 +36,7 @@ subroutine get_candidates(ss,savg,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
real ss(4,322,NFFT),savg(4,NFFT)
real pavg(-20:20)
integer indx(NFFT)
logical skip
logical xpol,skip
type(candidate) :: cand(MAX_CANDIDATES)
do j=322,1,-1 !Find end of data in ss()
@ -41,7 +44,7 @@ subroutine get_candidates(ss,savg,nfa,nfb,nts_jt65,nts_q65,cand,ncand)
enddo
jz=j
call wb_sync(ss,savg,jz,nfa,nfb)
call wb_sync(ss,savg,xpol,jz,nfa,nfb)
tstep=2048.0/11025.0 !0.185760 s: 0.5*tsym_jt65, 0.3096*tsym_q65
df3=96000.0/NFFT
@ -56,8 +59,7 @@ call wb_sync(ss,savg,jz,nfa,nfb)
n=indx(iz+1-i) + ia - 1
f0=0.001*(n-1)*df3
snr1=sync(n)%ccfmax
! print*,'=A',f0,snr1
if(snr1.lt.4.5) exit
if(snr1.lt.SNR1_THRESHOLD) exit
flip=sync(n)%iflip
if(flip.ne.0.0 .and. nts_jt65.eq.0) cycle
if(flip.eq.0.0 .and. nts_q65.eq.0) cycle
@ -94,6 +96,7 @@ call wb_sync(ss,savg,jz,nfa,nfb)
cand(k)%snr=snr1
cand(k)%f=f0
cand(k)%xdt=sync(n)%xdt
cand(k)%pol=sync(n)%pol
cand(k)%ipol=sync(n)%ipol
cand(k)%iflip=nint(flip)
if(k.ge.MAX_CANDIDATES) exit
@ -103,18 +106,21 @@ call wb_sync(ss,savg,jz,nfa,nfb)
return
end subroutine get_candidates
subroutine wb_sync(ss,savg,jz,nfa,nfb)
subroutine wb_sync(ss,savg,xpol,jz,nfa,nfb)
! Compute "orange sync curve" using the Q65 sync pattern
use timer_module, only: timer
parameter (NFFT=32768)
parameter (LAGMAX=30)
real ss(4,322,NFFT)
real savg(4,NFFT)
real savg_med(4)
logical first
real ccf4(4),ccf4best(4),a(3)
logical first,xpol
integer isync(22)
integer jsync0(63),jsync1(63)
integer ip(1)
! Q65 sync symbols
data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
@ -147,12 +153,14 @@ subroutine wb_sync(ss,savg,jz,nfa,nfb)
df3=96000.0/NFFT
ia=nint(1000*nfa/df3) + 1 !Flat frequency range for WSE converters
ib=nint(1000*nfb/df3) + 1
npol=1
if(xpol) npol=4
do i=1,4
do i=1,npol
call pctile(savg(i,ia:ib),ib-ia+1,50,savg_med(i))
enddo
! do i=ia,ib
! write(14,3014) 0.001*(i-1)*df3,savg(1:4,i)
! write(14,3014) 0.001*(i-1)*df3,savg(1:npol,i)
!3014 format(5f10.3)
! enddo
@ -162,57 +170,83 @@ subroutine wb_sync(ss,savg,jz,nfa,nfb)
do i=ia,ib
ccfmax=0.
do ipol=1,4
do lag=0,LAGMAX
do lag=0,LAGMAX
ccf=0.
do j=1,22
k=isync(j) + lag
ccf=ccf + ss(ipol,k,i+1) + ss(ipol,k+1,i+1) + ss(ipol,k+2,i+1)
enddo
ccf=ccf - savg(ipol,i+1)*3*22/float(jz)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
flip=0.
endif
ccf=0.
ccf4=0.
do j=1,22 !Test for Q65 sync
k=isync(j) + lag
ccf4(1:npol)=ccf4(1:npol) + ss(1:npol,k,i+1) + &
ss(1:npol,k+1,i+1) + ss(1:npol,k+2,i+1)
enddo
ccf4(1:npol)=ccf4(1:npol) - savg(1:npol,i+1)*3*22/float(jz)
ccf=maxval(ccf4)
ip=maxloc(ccf4)
ipol=ip(1)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
ccf4best=ccf4
flip=0.
endif
ccf=0.
do j=1,63
k=jsync0(j) + lag
ccf=ccf + ss(ipol,k,i+1) + ss(ipol,k+1,i+1)
enddo
ccf=ccf - savg(ipol,i+1)*2*63/float(jz)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
flip=1.0
endif
ccf=0.
ccf4=0.
do j=1,63 !Test for JT65 sync, std msg
k=jsync0(j) + lag
ccf4(1:npol)=ccf4(1:npol) + ss(1:npol,k,i+1) + ss(1:npol,k+1,i+1)
enddo
ccf4(1:npol)=ccf4(1:npol) - savg(1:npol,i+1)*2*63/float(jz)
ccf=maxval(ccf4)
ip=maxloc(ccf4)
ipol=ip(1)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
ccf4best=ccf4
flip=1.0
endif
ccf=0.
do j=1,63
k=jsync1(j) + lag
ccf=ccf + ss(ipol,k,i+1) + ss(ipol,k+1,i+1)
enddo
ccf=ccf - savg(ipol,i+1)*2*63/float(jz)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
flip=-1.0
endif
ccf=0.
ccf4=0.
do j=1,63 !Test for JT65 sync, OOO msg
k=jsync1(j) + lag
ccf4(1:npol)=ccf4(1:npol) + ss(1:npol,k,i+1) + ss(1:npol,k+1,i+1)
enddo
ccf4(1:npol)=ccf4(1:npol) - savg(1:npol,i+1)*2*63/float(jz)
ccf=maxval(ccf4)
ip=maxloc(ccf4)
ipol=ip(1)
if(ccf.gt.ccfmax) then
ipolbest=ipol
lagbest=lag
ccfmax=ccf
ccf4best=ccf4
flip=-1.0
endif
enddo ! lag
enddo !ipol
enddo ! lag
poldeg=0.
if(xpol .and. ccfmax.ge.SNR1_THRESHOLD) then
call polfit(ccf4best,4,a)
poldeg=a(3)
endif
sync(i)%ccfmax=ccfmax
sync(i)%xdt=lagbest*tstep-1.0
sync(i)%pol=poldeg
sync(i)%ipol=ipolbest
sync(i)%iflip=flip
sync(i)%birdie=.false.
if(ccfmax/(savg(ipolbest,i)/savg_med(ipolbest)).lt.3.0) sync(i)%birdie=.true.
! if(sync(i)%iflip.eq.0 .and. sync(i)%ccfmax .gt. 20.0) then
! write(50,3050) i,lagbest,sync(i)%ccfmax,sync(i)%xdt,sync(i)%ipol, &
! sync(i)%birdie,ccf4best
!3050 format(2i5,f10.3,f8.2,i5,1x,L3,4f7.1)
! endif
enddo ! i (frequency bin)
! do i=ia,ib
@ -223,7 +257,6 @@ subroutine wb_sync(ss,savg,jz,nfa,nfb)
call pctile(sync(ia:ib)%ccfmax,ib-ia+1,50,base)
sync(ia:ib)%ccfmax=sync(ia:ib)%ccfmax/base
! print*,base
return
end subroutine wb_sync

View File

@ -19,7 +19,7 @@ int main(int argc, char *argv[])
QApplication a {argc, argv};
// Override programs executable basename as application name.
a.setApplicationName ("MAP65");
a.setApplicationVersion ("3.0.0-rc1");
a.setApplicationVersion ("3.0.0-rc2");
// switch off as we share an Info.plist file with WSJT-X
a.setAttribute (Qt::AA_DontUseNativeMenuBar);
MainWindow w;

View File

@ -23,7 +23,7 @@
#define NFFT 32768
short int iwave[2*60*11025]; //Wave file for Tx audio
short int iwave[2*60*12000]; //Wave file for Tx audio
int nwave; //Length of Tx waveform
bool btxok; //True if OK to transmit
bool bTune;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>635</width>
<height>512</height>
<height>523</height>
</rect>
</property>
<property name="sizePolicy">
@ -1704,7 +1704,7 @@ p, li { white-space: pre-wrap; }
<customwidget>
<class>DisplayText</class>
<extends>QTextBrowser</extends>
<header>displaytext.h</header>
<header>widgets/displaytext.h</header>
</customwidget>
</customwidgets>
<resources/>

View File

@ -274,7 +274,7 @@ void CPlotter::UTCstr()
ihr=imin/60;
imin=imin % 60;
}
m_sutc = QString {"%1:%2"}.arg (ihr, 2).arg (imin, 2);
m_sutc = QString {"%1:%2"}.arg (ihr,2,10,QLatin1Char('0')).arg (imin,2,10,QLatin1Char('0'));
}
void CPlotter::DrawOverlay() //DrawOverlay()

View File

@ -1,45 +1,52 @@
#include "soundin.h"
#include <stdexcept>
#ifdef Q_OS_WIN32
#include <windows.h>
#else
#include <sys/socket.h>
#endif
#define NFFT 32768
#define FRAMES_PER_BUFFER 1024
extern "C" {
#include <portaudio.h>
extern struct {
double d8[2*60*96000]; //This is "common/datcom/..." in fortran
float ss[4*322*NFFT];
float savg[4*NFFT];
double fcenter;
int nutc;
int idphi; //Phase correction for Y pol'n, degrees
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.tf2 or *.iq file
int neme; //Hinted decoding tries only for EME calls
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntol; //+/- decoding range around fQSO (Hz)
int nxant; //1 ==> add 45 deg to measured pol angle
int map65RxLog; //Flags to control log files
int nfsample; //Input sample rate
int nxpol; //1 if using xpol antennas, 0 otherwise
int mode65; //JT65 sub-mode: A=1, B=2, C=4
int nfast; //1No longer used
int nsave; //Number of s3(64,63) spectra saved
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
} datcom_;
extern "C"
{
struct
{
double d8[2*60*96000]; //This is "common/datcom/..." in fortran
float ss[4*322*NFFT];
float savg[4*NFFT];
double fcenter;
int nutc;
int idphi; //Phase correction for Y pol'n, degrees
int mousedf; //User-selected DF
int mousefqso; //User-selected QSO freq (kHz)
int nagain; //1 ==> decode only at fQSO +/- Tol
int ndepth; //How much hinted decoding to do?
int ndiskdat; //1 ==> data read from *.tf2 or *.iq file
int neme; //Hinted decoding tries only for EME calls
int newdat; //1 ==> new data, must do long FFT
int nfa; //Low decode limit (kHz)
int nfb; //High decode limit (kHz)
int nfcal; //Frequency correction, for calibration (Hz)
int nfshift; //Shift of displayed center freq (kHz)
int mcall3; //1 ==> CALL3.TXT has been modified
int ntimeout; //Max for timeouts in Messages and BandMap
int ntol; //+/- decoding range around fQSO (Hz)
int nxant; //1 ==> add 45 deg to measured pol angle
int map65RxLog; //Flags to control log files
int nfsample; //Input sample rate
int nxpol; //1 if using xpol antennas, 0 otherwise
int mode65; //JT65 sub-mode: A=1, B=2, C=4
int nfast; //1No longer used
int nsave; //Number of s3(64,63) spectra saved
char mycall[12];
char mygrid[6];
char hiscall[12];
char hisgrid[6];
char datetime[20];
} datcom_;
}
typedef struct
@ -133,6 +140,26 @@ extern "C" int a2dCallback( const void *inputBuffer, void *outputBuffer,
return paContinue;
}
namespace
{
struct COMWrapper
{
explicit COMWrapper ()
{
#ifdef Q_OS_WIN32
// required because Qt only does this for GUI thread
CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
#endif
}
~COMWrapper ()
{
#ifdef Q_OS_WIN32
CoUninitialize ();
#endif
}
};
}
void SoundInThread::run() //SoundInThread::run()
{
quitExecution = false;
@ -144,8 +171,10 @@ void SoundInThread::run() //SoundInThread::run()
return;
}
//---------------------------------------------------- Soundcard Setup
// qDebug() << "Start souncard input";
COMWrapper c;
//---------------------------------------------------- Soundcard Setup
// qDebug() << "Start souncard input";
PaError paerr;
PaStreamParameters inParam;
@ -158,15 +187,27 @@ void SoundInThread::run() //SoundInThread::run()
udata.iqswap=m_IQswap;
udata.b10db=m_10db;
auto device_info = Pa_GetDeviceInfo (m_nDevIn);
inParam.device=m_nDevIn; //### Input Device Number ###
inParam.channelCount=2*m_nrx; //Number of analog channels
inParam.sampleFormat=paFloat32; //Get floats from Portaudio
inParam.suggestedLatency=0.05;
inParam.suggestedLatency=device_info->defaultHighInputLatency;
inParam.hostApiSpecificStreamInfo=NULL;
paerr=Pa_IsFormatSupported(&inParam,NULL,96000.0);
if(paerr<0) {
emit error("PortAudio says requested soundcard format not supported.");
QString error_message;
if (paUnanticipatedHostError == paerr)
{
auto const * last_host_error = Pa_GetLastHostErrorInfo ();
error_message = QString {"PortAudio Host API error: %1"}.arg (last_host_error->errorText);
}
else
{
error_message = "PortAudio says requested soundcard format not supported.";
}
emit error(error_message);
// return;
}
paerr=Pa_OpenStream(&inStream, //Input stream

View File

@ -6,12 +6,6 @@
#include <QDebug>
#include <valarray>
#ifdef Q_OS_WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#endif //Q_OS_WIN32
// Thread gets audio data from soundcard and signals when a buffer of
// specified size is available.
class SoundInThread : public QThread

View File

@ -1,10 +1,12 @@
#include "soundout.h"
#ifdef Q_OS_WIN32
#include <windows.h>
#endif
#define FRAMES_PER_BUFFER 256
extern "C" {
#include <portaudio.h>
}
extern float gran(); //Noise generator (for tests only)
@ -120,18 +122,42 @@ extern "C" int d2aCallback(const void * /*inputBuffer*/, void *outputBuffer,
return 0;
}
namespace
{
struct COMWrapper
{
explicit COMWrapper ()
{
#ifdef Q_OS_WIN32
// required because Qt only does this for GUI thread
CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
#endif
}
~COMWrapper ()
{
#ifdef Q_OS_WIN32
CoUninitialize ();
#endif
}
};
}
void SoundOutThread::run()
{
COMWrapper c;
PaError paerr;
PaStreamParameters outParam;
PaStream *outStream;
paUserData udata;
quitExecution = false;
auto device_info = Pa_GetDeviceInfo (m_nDevOut);
outParam.device=m_nDevOut; //Output device number
outParam.channelCount=2; //Number of analog channels
outParam.sampleFormat=paInt16; //Send short ints to PortAudio
outParam.suggestedLatency=0.05;
outParam.suggestedLatency=device_info->defaultLowOutputLatency;
outParam.hostApiSpecificStreamInfo=NULL;
udata.nTRperiod=m_TRperiod;

View File

@ -14,7 +14,7 @@ auto CallsignValidator::validate (QString& input, int& pos) const -> State
input.remove (0, 1);
if (pos > 0) --pos;
}
while (input.size () && input[input.size ()].isSpace ())
while (input.size () && input[input.size () - 1].isSpace ())
{
if (pos > input.size ()) --pos;
input.chop (1);

27
widgets/BandComboBox.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "BandComboBox.hpp"
#include <QAbstractItemView>
#include <QScrollBar>
#include <QDebug>
#include "models/FrequencyList.hpp"
BandComboBox::BandComboBox (QWidget * parent)
: QComboBox {parent}
{
}
// Fix up broken QComboBox item view rendering which doesn't allow for
// a vertical scroll bar in width calculations and ends up eliding the
// item text.
void BandComboBox::showPopup ()
{
auto minimum_width = view ()->sizeHintForColumn (FrequencyList_v2::frequency_mhz_column);
if (count () > maxVisibleItems ())
{
// for some as yet unknown reason, in FT8 mode the scrollbar
// width is oversize on the first call here
minimum_width += view ()->verticalScrollBar ()->width ();
}
view ()->setMinimumWidth (minimum_width);
QComboBox::showPopup ();
}

16
widgets/BandComboBox.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef BAND_COMBO_BOX_HPP__
#define BAND_COMBO_BOX_HPP__
#include <QComboBox>
class BandComboBox
: public QComboBox
{
public:
explicit BandComboBox (QWidget * = nullptr);
private:
void showPopup () override;
};
#endif

View File

@ -45,6 +45,7 @@
#include <QRandomGenerator>
#endif
#include "helper_functions.h"
#include "revision_utils.hpp"
#include "qt_helpers.hpp"
#include "Network/NetworkAccessManager.hpp"
@ -274,7 +275,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_freqNominal {0},
m_freqTxNominal {0},
m_reverse_Doppler {"1" == env.value ("WSJT_REVERSE_DOPPLER", "0")},
m_s6 {0.},
m_tRemaining {0.},
m_TRperiod {60.0},
m_DTtol {3.0},
@ -293,7 +293,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_idleMinutes {0},
m_nSubMode {0},
m_nclearave {1},
m_nseq {0},
m_nWSPRdecodes {0},
m_k0 {9999999},
m_nPick {0},
@ -755,10 +754,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->bandComboBox->setModel (m_config.frequencies ());
ui->bandComboBox->setModelColumn (FrequencyList_v2::frequency_mhz_column);
// combo box drop down width defaults to the line edit + decorator width,
// here we change that to the column width size hint of the model column
ui->bandComboBox->view ()->setMinimumWidth (ui->bandComboBox->view ()->sizeHintForColumn (FrequencyList_v2::frequency_mhz_column));
// Enable live band combo box entry validation and action.
auto band_validator = new LiveFrequencyValidator {ui->bandComboBox
, m_config.bands ()
@ -928,7 +923,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
QByteArray cfname=fname.toLocal8Bit();
fftwf_import_wisdom_from_filename(cfname);
//genStdMsgs(m_rpt);
m_ntx = 6;
ui->txrb6->setChecked(true);
@ -1008,7 +1002,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_fastGraph->setMode(m_mode);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
connect (&minuteTimer, &QTimer::timeout, this, &MainWindow::on_the_minute);
minuteTimer.setSingleShot (true);
@ -1031,6 +1024,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
void MainWindow::not_GA_warning_message ()
{
MessageBox::critical_message (this,
"This is a pre-release version of WSJT-X 2.5.0 made\n"
"available for testing purposes. By design it will\n"
@ -1139,7 +1133,6 @@ void MainWindow::writeSettings()
m_settings->beginGroup("Common");
m_settings->setValue("Mode",m_mode);
m_settings->setValue("ModeTx",m_modeTx);
m_settings->setValue("SaveNone",ui->actionNone->isChecked());
m_settings->setValue("SaveDecoded",ui->actionSave_decoded->isChecked());
m_settings->setValue("SaveAll",ui->actionSave_all->isChecked());
@ -1238,7 +1231,6 @@ void MainWindow::readSettings()
m_settings->beginGroup("Common");
m_mode=m_settings->value("Mode","JT9").toString();
m_modeTx=m_settings->value("ModeTx","JT9").toString();
ui->actionNone->setChecked(m_settings->value("SaveNone",true).toBool());
ui->actionSave_decoded->setChecked(m_settings->value("SaveDecoded",false).toBool());
ui->actionSave_all->setChecked(m_settings->value("SaveAll",false).toBool());
@ -2201,17 +2193,13 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
return;
}
break;
case Qt::Key_Z: //### Recover from hung decode() ?? ###
if(e->modifiers() & Qt::AltModifier) {
decodeDone();
return;
}
break; case Qt::Key_PageUp:
break;
case Qt::Key_PageDown:
band_changed(m_freqNominal-2000);
break; }
case Qt::Key_X:
if(e->modifiers() & Qt::AltModifier) {
// qDebug() << "Alt-X" << m_mode << m_TRperiod << m_nsps << m_bFast9
// << tx_duration(m_mode,m_TRperiod,m_nsps,m_bFast9);
return;
}
}
QMainWindow::keyPressEvent (e);
}
@ -2289,7 +2277,7 @@ void MainWindow::statusChanged()
if (!tmpGrid.size ()) tmpGrid="n/a"; // Not Available
out << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6)
<< ";" << m_mode << ";" << m_hisCall << ";"
<< ui->rptSpinBox->value() << ";" << m_modeTx << ";" << tmpGrid
<< ui->rptSpinBox->value() << ";" << m_mode << ";" << tmpGrid
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
@ -3142,7 +3130,6 @@ void MainWindow::decode() //decode()
if(dec_data.params.nutc < m_nutc0) m_RxLog = 1; //Date and Time to file "ALL.TXT".
if(dec_data.params.newdat==1 and !m_diskData) m_nutc0=dec_data.params.nutc;
dec_data.params.ntxmode=9;
if(m_modeTx=="JT65") dec_data.params.ntxmode=65;
dec_data.params.nmode=9;
if(m_mode=="JT65") dec_data.params.nmode=65;
if(m_mode=="JT65") dec_data.params.ljt65apon = ui->actionEnable_AP_JT65->isVisible () &&
@ -3163,6 +3150,7 @@ void MainWindow::decode() //decode()
}
if(m_mode=="FST4") dec_data.params.nmode=240;
if(m_mode=="FST4W") dec_data.params.nmode=241;
dec_data.params.ntxmode=dec_data.params.nmode; // Is this used any more?
dec_data.params.ntrperiod=m_TRperiod;
dec_data.params.nsubmode=m_nSubMode;
dec_data.params.minw=0;
@ -3807,42 +3795,14 @@ void MainWindow::guiUpdate()
static char message[38];
static char msgsent[38];
double txDuration;
QString rt;
if(m_TRperiod==0) m_TRperiod=60.0;
txDuration=0.0;
if(m_modeTx=="FT4") txDuration=1.0 + 105*576/12000.0; // FT4
if(m_modeTx=="FT8") txDuration=1.0 + 79*1920/12000.0; // FT8
if(m_modeTx=="JT4") txDuration=1.0 + 207.0*2520/11025.0; // JT4
if(m_modeTx=="JT9") txDuration=1.0 + 85.0*m_nsps/12000.0; // JT9
if(m_modeTx=="JT65") txDuration=1.0 + 126*4096/11025.0; // JT65
if(m_modeTx=="Q65") { // Q65
if(m_TRperiod==15) txDuration=0.5 + 85*1800/12000.0;
if(m_TRperiod==30) txDuration=0.5 + 85*3600/12000.0;
if(m_TRperiod==60) txDuration=1.0 + 85*7200/12000.0;
if(m_TRperiod==120) txDuration=1.0 + 85*16000/12000.0;
if(m_TRperiod==300) txDuration=1.0 + 85*41472/12000.0;
}
if(m_modeTx=="WSPR") txDuration=2.0 + 162*8192/12000.0; // WSPR
if(m_modeTx=="FST4" or m_mode=="FST4W") { //FST4, FST4W
if(m_TRperiod==15) txDuration=1.0 + 160*720/12000.0;
if(m_TRperiod==30) txDuration=1.0 + 160*1680/12000.0;
if(m_TRperiod==60) txDuration=1.0 + 160*3888/12000.0;
if(m_TRperiod==120) txDuration=1.0 + 160*8200/12000.0;
if(m_TRperiod==300) txDuration=1.0 + 160*21504/12000.0;
if(m_TRperiod==900) txDuration=1.0 + 160*66560/12000.0;
if(m_TRperiod==1800) txDuration=1.0 + 160*134400/12000.0;
}
if(m_mode=="MSK144" or m_bFast9) {
txDuration=m_TRperiod-0.25; // JT9-fast, MSK144
}
txDuration=tx_duration(m_mode,m_TRperiod,m_nsps,m_bFast9);
double tx1=0.0;
double tx2=txDuration;
if(m_mode=="FT8" or m_mode=="FT4") icw[0]=0; //No CW ID in FT4 or FT8 mode
if((icw[0]>0) and (!m_bFast9)) tx2 += icw[0]*2560.0/48000.0; //Full length including CW ID
if(tx2>m_TRperiod) tx2=m_TRperiod;
if(!m_txFirst and m_mode!="WSPR" and m_mode!="FST4W") {
tx1 += m_TRperiod;
tx2 += m_TRperiod;
@ -3852,20 +3812,19 @@ void MainWindow::guiUpdate()
int nsec=ms/1000;
double tsec=0.001*ms;
double t2p=fmod(tsec,2*m_TRperiod);
m_s6=fmod(tsec,6.0);
m_nseq = fmod(double(nsec),m_TRperiod);
double s6=fmod(tsec,6.0);
int nseq = fmod(double(nsec),m_TRperiod);
m_tRemaining=m_TRperiod - fmod(tsec,m_TRperiod);
if(m_mode=="Echo") {
txDuration=2.4;
tx1=0.0;
tx2=txDuration;
if(m_auto and m_s6>4.0) m_bEchoTxOK=true;
if(m_auto and s6>4.0) m_bEchoTxOK=true;
if(m_transmitting) m_bEchoTxed=true;
}
if(m_mode=="WSPR" or m_mode=="FST4W") {
if(m_nseq==0 and m_ntr==0) { //Decide whether to Tx or Rx
if(nseq==0 and m_ntr==0) { //Decide whether to Tx or Rx
m_tuneup=false; //This is not an ATU tuneup
bool btx = m_auto && m_WSPR_tx_next; // To Tx, we need m_auto and
// scheduled transmit
@ -3940,7 +3899,7 @@ void MainWindow::guiUpdate()
tx_watchdog (true); // disable transmit
}
float fTR=float((ms%int(1000.0*m_TRperiod)))/int(1000.0*m_TRperiod);
double fTR=float((ms%int(1000.0*m_TRperiod)))/int(1000.0*m_TRperiod);
QString txMsg;
if(m_ntx == 1) txMsg=ui->tx1->text();
@ -3952,7 +3911,7 @@ void MainWindow::guiUpdate()
int msgLength=txMsg.trimmed().length();
if(msgLength==0 and !m_tune) on_stopTxButton_clicked();
if(g_iptt==0 and ((m_bTxTime and fTR<0.75 and msgLength>0) or m_tune)) {
if(g_iptt==0 and ((m_bTxTime and (fTR < 0.75) and (msgLength>0)) or m_tune)) {
//### Allow late starts
icw[0]=m_ncw;
g_iptt = 1;
@ -4006,7 +3965,7 @@ void MainWindow::guiUpdate()
}
if((m_mode=="WSPR" or m_mode=="FST4W") and
((m_ntr==1 and m_rxDone) or (m_ntr==-1 and m_nseq>tx2))) {
((m_ntr==1 and m_rxDone) or (m_ntr==-1 and nseq>tx2))) {
if(m_monitoring) {
m_rxDone=false;
}
@ -4064,13 +4023,13 @@ void MainWindow::guiUpdate()
} else {
if(m_QSOProgress==REPORT || m_QSOProgress==ROGER_REPORT) m_bSentReport=true;
if(m_bSentReport and (m_QSOProgress<REPORT or m_QSOProgress>ROGER_REPORT)) m_bSentReport=false;
if(m_modeTx=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone),
if(m_mode=="JT4") gen4_(message, &ichk , msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22);
if(m_modeTx=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone),
if(m_mode=="JT9") gen9_(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22);
if(m_modeTx=="JT65") gen65_(message, &ichk, msgsent, const_cast<int *> (itone),
if(m_mode=="JT65") gen65_(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 22, 22);
if(m_modeTx=="Q65") {
if(m_mode=="Q65") {
int i3=-1;
int n3=-1;
genq65_(message,&ichk,msgsent,const_cast<int *>(itone),&i3,&n3,37,37);
@ -4089,15 +4048,15 @@ void MainWindow::guiUpdate()
genwave_(const_cast<int *>(itone),&nsym,&nsps4,&nwave,
&fsample,&hmod,&f0,&icmplx,foxcom_.wave,foxcom_.wave);
}
if(m_modeTx=="WSPR") genwspr_(message, msgsent, const_cast<int *> (itone),
if(m_mode=="WSPR") genwspr_(message, msgsent, const_cast<int *> (itone),
22, 22);
if(m_modeTx=="MSK144" or m_modeTx=="FT8" or m_modeTx=="FT4"
or m_modeTx=="FST4" or m_modeTx=="FST4W") {
if(m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4"
or m_mode=="FST4" or m_mode=="FST4W") {
char MyCall[6];
char MyGrid[6];
::memcpy(MyCall, (m_config.my_callsign()+" ").toLatin1(), sizeof MyCall);
::memcpy(MyGrid, (m_config.my_grid()+" ").toLatin1(), sizeof MyGrid);
if(m_modeTx=="MSK144") {
if(m_mode=="MSK144") {
genmsk_128_90_(message, &ichk, msgsent, const_cast<int *> (itone),
&m_currentMessageType, 37, 37);
if(m_restart) {
@ -4107,7 +4066,7 @@ void MainWindow::guiUpdate()
}
}
if(m_modeTx=="FT8") {
if(m_mode=="FT8") {
if(SpecOp::FOX==m_config.special_op_id() and ui->tabWidget->currentIndex()==1) {
foxTxSequencer();
} else {
@ -4138,7 +4097,7 @@ void MainWindow::guiUpdate()
}
}
}
if(m_modeTx=="FT4") {
if(m_mode=="FT4") {
int ichk=0;
char ft4msgbits[77];
genft4_(message, &ichk, msgsent, const_cast<char *> (ft4msgbits),
@ -4152,7 +4111,7 @@ void MainWindow::guiUpdate()
gen_ft4wave_(const_cast<int *>(itone),&nsym,&nsps,&fsample,&f0,foxcom_.wave,
foxcom_.wave,&icmplx,&nwave);
}
if(m_modeTx=="FST4" or m_modeTx=="FST4W") {
if(m_mode=="FST4" or m_mode=="FST4W") {
int ichk=0;
int iwspr=0;
char fst4msgbits[101];
@ -4230,7 +4189,7 @@ void MainWindow::guiUpdate()
if(m_restart) {
write_all("Tx",m_currentMessage);
if (m_config.TX_messages ()) {
ui->decodedTextBrowser2->displayTransmittedText(m_currentMessage.trimmed(),m_modeTx,
ui->decodedTextBrowser2->displayTransmittedText(m_currentMessage.trimmed(),m_mode,
ui->TxFreqSpinBox->value(),m_bFastMode,m_TRperiod);
}
}
@ -4314,6 +4273,7 @@ void MainWindow::guiUpdate()
m_sentFirst73 = false;
}
}
if (g_iptt == 1 && m_iptt0 == 0) {
auto const& current_message = QString::fromLatin1 (msgsent);
if(m_config.watchdog () && m_mode!="WSPR" && m_mode!="FST4W"
@ -4328,7 +4288,7 @@ void MainWindow::guiUpdate()
if (m_config.TX_messages () && !m_tune && SpecOp::FOX!=m_config.special_op_id())
{
ui->decodedTextBrowser2->displayTransmittedText(current_message.trimmed(),
m_modeTx,ui->TxFreqSpinBox->value(),m_bFastMode,m_TRperiod);
m_mode,ui->TxFreqSpinBox->value(),m_bFastMode,m_TRperiod);
}
}
@ -4346,15 +4306,14 @@ void MainWindow::guiUpdate()
transmitDisplay (true);
statusUpdate ();
}
if(!m_btxok && m_btxok0 && g_iptt==1)
{
stopTx();
if ("1" == m_env.value ("WSJT_TX_BOTH", "0"))
{
m_txFirst = !m_txFirst;
ui->txFirstCheckBox->setChecked (m_txFirst);
}
if(!m_btxok && m_btxok0 && g_iptt==1) {
stopTx();
if ("1" == m_env.value ("WSJT_TX_BOTH", "0")) {
m_txFirst = !m_txFirst;
ui->txFirstCheckBox->setChecked (m_txFirst);
}
}
if(m_startAnother) {
if(m_mode=="MSK144") {
@ -4368,16 +4327,16 @@ void MainWindow::guiUpdate()
}
if(m_mode=="FT8" or m_mode=="MSK144" or m_mode=="FT4") {
if(ui->txrb1->isEnabled() and
(SpecOp::NA_VHF==m_config.special_op_id() or
SpecOp::FIELD_DAY==m_config.special_op_id() or
SpecOp::RTTY==m_config.special_op_id() or
SpecOp::WW_DIGI==m_config.special_op_id()) ) {
if(ui->txrb1->isEnabled() and
(SpecOp::NA_VHF==m_config.special_op_id() or
SpecOp::FIELD_DAY==m_config.special_op_id() or
SpecOp::RTTY==m_config.special_op_id() or
SpecOp::WW_DIGI==m_config.special_op_id()) ) {
//We're in a contest-like mode other than EU_VHF: start QSO with Tx2.
ui->tx1->setEnabled(false);
ui->txb1->setEnabled(false);
}
if(!ui->tx1->isEnabled() and SpecOp::EU_VHF==m_config.special_op_id()) {
if(!ui->tx1->isEnabled() and SpecOp::EU_VHF==m_config.special_op_id()) {
//We're in EU_VHF mode: start QSO with Tx1.
ui->tx1->setEnabled(true);
ui->txb1->setEnabled(true);
@ -4387,6 +4346,7 @@ void MainWindow::guiUpdate()
//Once per second (onesec)
if(nsec != m_sec0) {
// qDebug() << "AAA" << nsec;
if(m_mode=="FST4") chk_FST4_freq_range();
m_currentBand=m_config.bands()->find(m_freqNominal);
if( SpecOp::HOUND == m_config.special_op_id() ) {
@ -4399,7 +4359,7 @@ void MainWindow::guiUpdate()
progressBar.setFormat ("%v/%m");
if(m_auto and m_mode=="Echo" and m_bEchoTxOK) {
progressBar.setMaximum(3);
progressBar.setValue(int(m_s6));
progressBar.setValue(int(s6));
}
if(m_mode!="Echo") {
if(m_monitoring or m_transmitting) {
@ -4890,8 +4850,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
return;
}
if ((message.isJT9 () and m_modeTx != "JT9" and m_mode != "JT4") or
(message.isJT65 () and m_modeTx != "JT65" and m_mode != "JT4")) {
if ((message.isJT9 () and m_mode != "JT9" and m_mode != "JT4") or
(message.isJT65 () and m_mode != "JT65" and m_mode != "JT4")) {
// We are not allowing mode change, so don't process decode
return;
}
@ -5279,27 +5239,32 @@ void MainWindow::setTxMsg(int n)
void MainWindow::genCQMsg ()
{
if(m_config.my_callsign().size () && m_config.my_grid().size ()) {
QString grid{m_config.my_grid()};
auto const& my_callsign = m_config.my_callsign ();
auto is_compound = my_callsign != m_baseCall;
auto is_type_two = !is77BitMode () && is_compound && stdCall (m_baseCall) && !shortList (my_callsign);
if(my_callsign.size () && m_config.my_grid().size ()) {
auto const& grid = m_config.my_grid ();
if (ui->cbCQTx->isEnabled () && ui->cbCQTx->isVisible () && ui->cbCQTx->isChecked ()) {
if(stdCall(m_config.my_callsign())) {
if(stdCall (my_callsign)
|| is_type_two) {
msgtype (QString {"CQ %1 %2 %3"}
.arg (m_freqNominal / 1000 - m_freqNominal / 1000000 * 1000, 3, 10, QChar {'0'})
.arg (m_config.my_callsign())
.arg (my_callsign)
.arg (grid.left (4)),
ui->tx6);
} else {
msgtype (QString {"CQ %1 %2"}
.arg (m_freqNominal / 1000 - m_freqNominal / 1000000 * 1000, 3, 10, QChar {'0'})
.arg (m_config.my_callsign()),
.arg (my_callsign),
ui->tx6);
}
} else {
if(stdCall(m_config.my_callsign())) {
msgtype (QString {"%1 %2 %3"}.arg(m_CQtype).arg(m_config.my_callsign())
if (stdCall (my_callsign)
|| is_type_two) {
msgtype (QString {"%1 %2 %3"}.arg(m_CQtype).arg(my_callsign)
.arg(grid.left(4)),ui->tx6);
} else {
msgtype (QString {"%1 %2"}.arg(m_CQtype).arg(m_config.my_callsign()),ui->tx6);
msgtype (QString {"%1 %2"}.arg(m_CQtype).arg(my_callsign),ui->tx6);
}
}
if ((m_mode=="JT4" or m_mode=="Q65") and ui->cbShMsgs->isChecked()) {
@ -5314,15 +5279,15 @@ void MainWindow::genCQMsg ()
QStringList tlist=t.split(" ");
if((m_mode=="FT4" or m_mode=="FT8" or m_mode=="MSK144") and
SpecOp::NONE != m_config.special_op_id() and
( tlist.at(1)==m_config.my_callsign() or
tlist.at(2)==m_config.my_callsign() ) and
stdCall(m_config.my_callsign())) {
( tlist.at(1)==my_callsign or
tlist.at(2)==my_callsign ) and
stdCall(my_callsign)) {
if(SpecOp::NA_VHF == m_config.special_op_id()) m_cqStr="TEST";
if(SpecOp::EU_VHF == m_config.special_op_id()) m_cqStr="TEST";
if(SpecOp::FIELD_DAY == m_config.special_op_id()) m_cqStr="FD";
if(SpecOp::RTTY == m_config.special_op_id()) m_cqStr="RU";
if(SpecOp::WW_DIGI == m_config.special_op_id()) m_cqStr="WW";
if( tlist.at(1)==m_config.my_callsign() ) {
if( tlist.at(1)==my_callsign ) {
t="CQ " + m_cqStr + " " + tlist.at(1) + " " + tlist.at(2);
} else {
t="CQ " + m_cqStr + " " + tlist.at(2) + " " + tlist.at(3);
@ -5355,6 +5320,12 @@ bool MainWindow::stdCall(QString const& w)
return standard_call_re.match (w).hasMatch ();
}
bool MainWindow::is77BitMode () const
{
return "FT8" == m_mode || "FT4" == m_mode || "MSK144" == m_mode
|| "FST4" == m_mode || "Q65" == m_mode;
}
void MainWindow::genStdMsgs(QString rpt, bool unconditional)
{
genCQMsg ();
@ -5371,7 +5342,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
}
auto const& my_callsign = m_config.my_callsign ();
auto is_compound = my_callsign != m_baseCall;
auto is_type_one = is_compound && shortList (my_callsign);
auto is_type_one = !is77BitMode () && is_compound && shortList (my_callsign);
auto const& my_grid = m_config.my_grid ().left (4);
auto const& hisBase = Radio::base_callsign (hisCall);
auto eme_short_codes = m_config.enable_VHF_features () && ui->cbShMsgs->isChecked ()
@ -5384,7 +5355,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
QString t0s=hisCall + " " + my_callsign + " ";
QString t0a,t0b;
if(bHisCall and bMyCall) t0=hisCall + " " + my_callsign + " ";
if (is77BitMode () && bHisCall && bMyCall) t0=hisCall + " " + my_callsign + " ";
t0a="<"+hisCall + "> " + my_callsign + " ";
t0b=hisCall + " <" + my_callsign + "> ";
@ -5402,7 +5373,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
int n=rpt.toInt();
rpt = rpt.asprintf("%+2.2d",n);
if(m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4" || m_mode=="FST4") {
if (is77BitMode ()) {
QString t2,t3;
QString sent=rpt;
QString rs,rst;
@ -5466,8 +5437,8 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
}
}
if((m_mode!="MSK144" and m_mode!="FT8" and m_mode!="FT4" && m_mode != "FST4")) {
t=t00 + rpt;
if (!is77BitMode ()) {
t=(is_type_one ? t0 : t00) + rpt;
msgtype(t, ui->tx2);
t=t0 + "R" + rpt;
msgtype(t, ui->tx3);
@ -5506,7 +5477,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
}
}
if(m_mode=="FT8" or m_mode=="FT4" or m_mode=="MSK144" || m_mode == "FST4") return;
if (is77BitMode ()) return;
if (is_compound) {
if (is_type_one) {
@ -5519,8 +5490,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
case Configuration::type_2_msg_1_full:
msgtype(t + my_grid, ui->tx1);
if (!eme_short_codes) {
if((m_mode=="MSK144" || m_mode=="FT8" || m_mode=="FT4" || m_mode == "FST4") &&
SpecOp::NA_VHF == m_config.special_op_id()) {
if(is77BitMode () && SpecOp::NA_VHF == m_config.special_op_id()) {
msgtype(t + "R " + my_grid, ui->tx3); // #### Unreachable code
} else {
msgtype(t + "R" + rpt, ui->tx3);
@ -5532,8 +5502,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
break;
case Configuration::type_2_msg_3_full:
if ((m_mode=="MSK144" || m_mode=="FT8" || m_mode=="FT4" || m_mode == "FST4") &&
SpecOp::NA_VHF == m_config.special_op_id()) {
if (is77BitMode () && SpecOp::NA_VHF == m_config.special_op_id()) {
msgtype(t + "R " + my_grid, ui->tx3);
msgtype(t + "RRR", ui->tx4);
} else {
@ -5548,8 +5517,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
case Configuration::type_2_msg_5_only:
msgtype(t00 + my_grid, ui->tx1);
if (!eme_short_codes) {
if ((m_mode=="MSK144" || m_mode=="FT8" || m_mode=="FT4" || m_mode == "FST4") &&
SpecOp::NA_VHF == m_config.special_op_id()) {
if (is77BitMode () && SpecOp::NA_VHF == m_config.special_op_id()) {
msgtype(t + "R " + my_grid, ui->tx3); // #### Unreachable code
msgtype(t + "RRR", ui->tx4);
} else {
@ -5584,7 +5552,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
}
}
m_rpt=rpt;
if(SpecOp::HOUND == m_config.special_op_id() and is_compound) ui->tx1->setText("DE " + m_config.my_callsign());
if(SpecOp::HOUND == m_config.special_op_id() and is_compound) ui->tx1->setText("DE " + my_callsign);
}
void MainWindow::TxAgain()
@ -5948,7 +5916,7 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
default: break;
}
m_logDlg->initLogQSO (m_hisCall, grid, m_modeTx, m_rptSent, m_rptRcvd,
m_logDlg->initLogQSO (m_hisCall, grid, m_mode, m_rptSent, m_rptRcvd,
m_dateTimeQSOOn, dateTimeQSOOff, m_freqNominal +
ui->TxFreqSpinBox->value(), m_noSuffix, m_xSent, m_xRcvd);
m_inQSOwith="";
@ -6087,7 +6055,7 @@ void MainWindow::displayWidgets(qint64 n)
void MainWindow::on_actionFST4_triggered()
{
m_mode="FST4";
m_modeTx="FST4";
m_mode="FST4";
ui->actionFST4->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -6111,7 +6079,6 @@ void MainWindow::on_actionFST4_triggered()
setup_status_bar(false);
ui->cbAutoSeq->setChecked(true);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_wideGraph->setPeriod(m_TRperiod,6912);
m_wideGraph->setRxFreq(ui->RxFreqSpinBox->value());
m_wideGraph->setTol(ui->sbFtol->value());
@ -6130,7 +6097,6 @@ void MainWindow::on_actionFST4_triggered()
void MainWindow::on_actionFST4W_triggered()
{
m_mode="FST4W";
m_modeTx="FST4W";
ui->actionFST4W->setChecked(true);
m_bFast9=false;
m_bFastMode=false;
@ -6149,7 +6115,6 @@ void MainWindow::on_actionFST4W_triggered()
ui->WSPRfreqSpinBox->setMinimum(100);
ui->WSPRfreqSpinBox->setMaximum(5000);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_wideGraph->setPeriod(m_TRperiod,6912);
m_wideGraph->setTxFreq(ui->WSPRfreqSpinBox->value());
m_wideGraph->setRxFreq(ui->sbFST4W_RxFreq->value());
@ -6162,7 +6127,6 @@ void MainWindow::on_actionFST4W_triggered()
void MainWindow::on_actionFT4_triggered()
{
m_mode="FT4";
m_modeTx="FT4";
m_TRperiod=7.5;
bool bVHF=m_config.enable_VHF_features();
m_bFast9=false;
@ -6177,7 +6141,6 @@ void MainWindow::on_actionFT4_triggered()
m_toneSpacing=12000.0/576.0;
ui->actionFT4->setChecked(true);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_send_RR73=true;
VHF_features_enabled(bVHF);
m_fastGraph->hide();
@ -6212,7 +6175,6 @@ void MainWindow::on_actionFT8_triggered()
m_bFastMode=false;
WSPR_config(false);
switch_mode (Modes::FT8);
m_modeTx="FT8";
m_nsps=6912;
m_FFTSize = m_nsps / 2;
Q_EMIT FFTSize (m_FFTSize);
@ -6221,7 +6183,6 @@ void MainWindow::on_actionFT8_triggered()
m_toneSpacing=0.0; //???
ui->actionFT8->setChecked(true); //???
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
VHF_features_enabled(bVHF);
ui->cbAutoSeq->setChecked(true);
m_TRperiod=15.0;
@ -6316,7 +6277,6 @@ void MainWindow::on_actionJT4_triggered()
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
switch_mode (Modes::JT4);
m_modeTx="JT4";
m_TRperiod=60.0;
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe
@ -6330,7 +6290,6 @@ void MainWindow::on_actionJT4_triggered()
VHF_features_enabled(true);
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_bFastMode=false;
m_bFast9=false;
setup_status_bar (bVHF);
@ -6362,7 +6321,6 @@ void MainWindow::on_actionJT9_triggered()
m_bFastMode=m_bFast9;
WSPR_config(false);
switch_mode (Modes::JT9);
m_modeTx="JT9";
m_nsps=6912;
m_FFTSize = m_nsps / 2;
Q_EMIT FFTSize (m_FFTSize);
@ -6372,7 +6330,6 @@ void MainWindow::on_actionJT9_triggered()
m_toneSpacing=0.0;
ui->actionJT9->setChecked(true);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
VHF_features_enabled(bVHF);
if(m_nSubMode>=4 and bVHF) {
ui->cbFast9->setEnabled(true);
@ -6419,7 +6376,6 @@ void MainWindow::on_actionJT65_triggered()
{
on_actionJT9_triggered();
m_mode="JT65";
m_modeTx="JT65";
bool bVHF=m_config.enable_VHF_features();
WSPR_config(false);
switch_mode (Modes::JT65);
@ -6436,7 +6392,6 @@ void MainWindow::on_actionJT65_triggered()
VHF_features_enabled(bVHF);
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_wideGraph->setRxFreq(ui->RxFreqSpinBox->value());
m_wideGraph->setTol(ui->sbFtol->value());
m_wideGraph->setTxFreq(ui->TxFreqSpinBox->value());
@ -6470,12 +6425,12 @@ void MainWindow::on_actionJT65_triggered()
void MainWindow::on_actionQ65_triggered()
{
m_mode="Q65";
m_modeTx="Q65";
ui->actionQ65->setChecked(true);
switch_mode(Modes::Q65);
fast_config(false);
WSPR_config(false);
setup_status_bar(true);
ui->actionQuickDecode->setChecked(true);
m_nsps=6912; //For symspec only
m_FFTSize = m_nsps / 2;
Q_EMIT FFTSize(m_FFTSize);
@ -6486,7 +6441,6 @@ void MainWindow::on_actionQ65_triggered()
QString fname {QDir::toNativeSeparators(m_config.temp_dir().absoluteFilePath ("red.dat"))};
m_wideGraph->setRedFile(fname);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_wideGraph->setPeriod(m_TRperiod,6912);
m_wideGraph->setTol(ui->sbFtol->value());
m_wideGraph->setRxFreq(ui->RxFreqSpinBox->value());
@ -6530,7 +6484,6 @@ void MainWindow::on_actionMSK144_triggered()
return;
}
m_mode="MSK144";
m_modeTx="MSK144";
ui->actionMSK144->setChecked(true);
switch_mode (Modes::MSK144);
m_nsps=6;
@ -6586,7 +6539,6 @@ void MainWindow::on_actionWSPR_triggered()
m_mode="WSPR";
WSPR_config(true);
switch_mode (Modes::WSPR);
m_modeTx="WSPR";
m_TRperiod=120.0;
m_modulator->setTRPeriod(m_TRperiod); // TODO - not thread safe
m_detector->setTRPeriod(m_TRperiod); // TODO - not thread safe
@ -6602,7 +6554,6 @@ void MainWindow::on_actionWSPR_triggered()
ui->WSPRfreqSpinBox->setMaximum(1600);
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
m_bFastMode=false;
m_bFast9=false;
ui->TxFreqSpinBox->setValue(ui->WSPRfreqSpinBox->value());
@ -6626,10 +6577,8 @@ void MainWindow::on_actionEcho_triggered()
m_hsymStop=9;
m_toneSpacing=1.0;
switch_mode(Modes::Echo);
m_modeTx="Echo";
setup_status_bar (true);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
ui->TxFreqSpinBox->setValue(1500);
ui->TxFreqSpinBox->setEnabled (false);
if(!m_echoGraph->isVisible()) m_echoGraph->show();
@ -7315,7 +7264,7 @@ void MainWindow::rigFailure (QString const& reason)
void MainWindow::transmit (double snr)
{
double toneSpacing=0.0;
if (m_modeTx == "JT65") {
if (m_mode == "JT65") {
if(m_nSubMode==0) toneSpacing=11025.0/4096.0;
if(m_nSubMode==1) toneSpacing=2*11025.0/4096.0;
if(m_nSubMode==2) toneSpacing=4*11025.0/4096.0;
@ -7325,7 +7274,7 @@ void MainWindow::transmit (double snr)
true, false, snr, m_TRperiod);
}
if (m_modeTx == "FT8") {
if (m_mode == "FT8") {
// toneSpacing=12000.0/1920.0;
toneSpacing=-3;
if(m_config.x2ToneSpacing()) toneSpacing=2*12000.0/1920.0;
@ -7337,7 +7286,7 @@ void MainWindow::transmit (double snr)
true, false, snr, m_TRperiod);
}
if (m_modeTx == "FT4") {
if (m_mode == "FT4") {
m_dateTimeSentTx3=QDateTime::currentDateTimeUtc();
toneSpacing=-2.0; //Transmit a pre-computed, filtered waveform.
Q_EMIT sendMessage (m_mode, NUM_FT4_SYMBOLS,
@ -7346,7 +7295,7 @@ void MainWindow::transmit (double snr)
true, false, snr, m_TRperiod);
}
if (m_modeTx == "FST4" or m_modeTx == "FST4W") {
if (m_mode == "FST4" or m_mode == "FST4W") {
m_dateTimeSentTx3=QDateTime::currentDateTimeUtc();
toneSpacing=-2.0; //Transmit a pre-computed, filtered waveform.
int nsps=720;
@ -7368,7 +7317,7 @@ void MainWindow::transmit (double snr)
true, false, snr, m_TRperiod);
}
if (m_modeTx == "Q65") {
if (m_mode == "Q65") {
int nsps=1800;
if(m_TRperiod==30) nsps=3600;
if(m_TRperiod==60) nsps=7200;
@ -7383,7 +7332,7 @@ void MainWindow::transmit (double snr)
true, false, snr, m_TRperiod);
}
if (m_modeTx == "JT9") {
if (m_mode == "JT9") {
int nsub=pow(2,m_nSubMode);
int nsps[]={480,240,120,60};
double sps=m_nsps;
@ -7402,7 +7351,7 @@ void MainWindow::transmit (double snr)
true, fastmode, snr, m_TRperiod);
}
if (m_modeTx == "MSK144") {
if (m_mode == "MSK144") {
m_nsps=6;
double f0=1000.0;
if(!m_bFastMode) {
@ -7420,7 +7369,7 @@ void MainWindow::transmit (double snr)
true, true, snr, m_TRperiod);
}
if (m_modeTx == "JT4") {
if (m_mode == "JT4") {
if(m_nSubMode==0) toneSpacing=4.375;
if(m_nSubMode==1) toneSpacing=2*4.375;
if(m_nSubMode==2) toneSpacing=4*4.375;
@ -7599,7 +7548,7 @@ void::MainWindow::VHF_features_enabled(bool b)
}
ui->actionInclude_averaging->setVisible (b);
ui->actionInclude_correlation->setVisible (b && m_mode!="Q65");
ui->actionMessage_averaging->setEnabled(b);
ui->actionMessage_averaging->setEnabled(b && (m_mode=="JT4" or m_mode=="JT65"));
ui->actionEnable_AP_JT65->setVisible (b && m_mode=="JT65");
if(!b && m_msgAvgWidget and (SpecOp::FOX != m_config.special_op_id()) and !m_config.autoLog()) {
@ -8423,7 +8372,7 @@ void MainWindow::statusUpdate () const
}
m_messageClient->status_update (m_freqNominal, m_mode, m_hisCall,
QString::number (ui->rptSpinBox->value ()),
m_modeTx, ui->autoButton->isChecked (),
m_mode, ui->autoButton->isChecked (),
m_transmitting, m_decoderBusy,
rx_frequency, ui->TxFreqSpinBox->value (),
m_config.my_callsign (), m_config.my_grid (),
@ -8556,7 +8505,7 @@ void MainWindow::write_transmit_entry (QString const& file_name)
time = time.addSecs (-fmod(double(time.time().second()),m_TRperiod));
out << time.toString("yyMMdd_hhmmss")
<< " Transmitting " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6)
<< " MHz " << m_modeTx
<< " MHz " << m_mode
<< ": " << m_currentMessage
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl

View File

@ -419,7 +419,6 @@ private:
Astro::Correction m_astroCorrection;
bool m_reverse_Doppler;
double m_s6;
double m_tRemaining;
double m_TRperiod;
@ -454,7 +453,6 @@ private:
qint32 m_nclearave;
qint32 m_minSync;
qint32 m_dBm;
qint32 m_nseq;
qint32 m_nWSPRdecodes;
qint32 m_k0;
qint32 m_kdone;
@ -612,7 +610,6 @@ private:
QString m_palette;
QString m_dateTime;
QString m_mode;
QString m_modeTx;
QString m_fnameWE; // save path without extension
QString m_rpt;
QString m_nextRpt;
@ -781,6 +778,7 @@ private:
void foxGenWaveform(int i,QString fm);
void writeFoxQSO (QString const& msg);
void to_jt9(qint32 n, qint32 istart, qint32 idone);
bool is77BitMode () const;
};
extern int killbyname(const char* progName);

View File

@ -644,7 +644,7 @@ QPushButton[state=&quot;ok&quot;] {
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="bandComboBox">
<widget class="BandComboBox" name="bandComboBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select operating band or enter frequency in MHz or enter kHz increment followed by k.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
@ -661,7 +661,7 @@ QPushButton[state=&quot;ok&quot;] {
<enum>QComboBox::NoInsert</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
</widget>
</item>
@ -3434,7 +3434,7 @@ Double-click to reset to the standard 73 message</string>
<customwidgets>
<customwidget>
<class>DisplayText</class>
<extends>QTextEdit</extends>
<extends>QTextBrowser</extends>
<header>widgets/displaytext.h</header>
</customwidget>
<customwidget>
@ -3468,6 +3468,11 @@ Double-click to reset to the standard 73 message</string>
<extends>QPushButton</extends>
<header>widgets/DoubleClickablePushButton.hpp</header>
</customwidget>
<customwidget>
<class>BandComboBox</class>
<extends>QComboBox</extends>
<header>widgets/BandComboBox.hpp</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>decodedTextBrowser</tabstop>

View File

@ -479,7 +479,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
}
}
if(m_modeTx=="JT9" and m_nSubMode>0) { //JT9
if(m_mode=="JT9" and m_nSubMode>0) { //JT9
bw=8.0*12000.0/m_nsps;
if(m_nSubMode==1) bw=2*bw; //B
if(m_nSubMode==2) bw=4*bw; //C
@ -500,7 +500,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
float baud=12000.0/nsps;
bw=65.0*h*baud;
}
if(m_modeTx=="JT65") { //JT65
if(m_mode=="JT65") { //JT65
bw=65.0*11025.0/4096.0;
if(m_nSubMode==1) bw=2*bw; //B
if(m_nSubMode==2) bw=4*bw; //C
@ -817,11 +817,6 @@ void CPlotter::setSubMode(int n) //setSubMode
m_nSubMode=n;
}
void CPlotter::setModeTx(QString modeTx) //setModeTx
{
m_modeTx=modeTx;
}
int CPlotter::Fmax()
{
return m_fMax;

View File

@ -61,7 +61,6 @@ public:
void setTxFreq(int n);
void setMode(QString mode);
void setSubMode(int n);
void setModeTx(QString modeTx);
void SetPercent2DScreen(int percent);
int Fmax();
void setDialFreq(double d);
@ -149,7 +148,6 @@ private:
QString m_HDivText[483];
QString m_mode;
QString m_mode0;
QString m_modeTx;
QString m_rxBand;
QString m_redFile;

View File

@ -305,13 +305,6 @@ void WideGraph::setSubMode(int n) //setSubMode
ui->widePlot->DrawOverlay();
ui->widePlot->update();
}
void WideGraph::setModeTx(QString modeTx) //setModeTx
{
m_modeTx=modeTx;
ui->widePlot->setModeTx(modeTx);
ui->widePlot->DrawOverlay();
ui->widePlot->update();
}
void WideGraph::on_spec2dComboBox_currentIndexChanged(int index)
{

View File

@ -39,7 +39,6 @@ public:
void setTxFreq(int n);
void setMode(QString mode);
void setSubMode(int n);
void setModeTx(QString modeTx);
bool flatten();
bool useRef();
void setTol(int n);
@ -116,7 +115,6 @@ private:
QString m_rxBand;
QString m_mode;
QString m_modeTx;
QString m_waterfallPalette;
float m_swide[MAX_SCREENSIZE];
QString m_user_defined;

View File

@ -65,6 +65,7 @@ SOURCES += \
getfile.cpp \
WFPalette.cpp \
WsprTxScheduler.cpp \
helper_functions.cpp \
main.cpp decodedtext.cpp wsprnet.cpp \
WSPRBandHopping.cpp MessageAggregator.cpp SampleDownloader.cpp qt_helpers.cpp\
MultiSettings.cpp PhaseEqualizationDialog.cpp \
@ -72,6 +73,7 @@ SOURCES += \
LotWUsers.cpp TraceFile.cpp
HEADERS += qt_helpers.hpp qt_db_helpers.hpp \
helper_functions.h \
pimpl_h.hpp pimpl_impl.hpp \
ExceptionCatchingApplication.hpp Logger.hpp WSJTXLogging.hpp \
Radio.hpp NetworkServerLookup.hpp revision_utils.hpp \