diff --git a/WSJT-X_Users_Guide_v1.1.docx b/WSJT-X_Users_Guide_v1.1.docx new file mode 100644 index 000000000..a648fe049 Binary files /dev/null and b/WSJT-X_Users_Guide_v1.1.docx differ diff --git a/commons.h b/commons.h index 31e8c68e8..e521841ca 100644 --- a/commons.h +++ b/commons.h @@ -1,7 +1,8 @@ #ifndef COMMONS_H #define COMMONS_H -#define NSMAX 1365 +//#define NSMAX 1365 +#define NSMAX 6827 #define NTMAX 120 extern "C" { @@ -9,7 +10,6 @@ extern "C" { extern struct { float ss[184*NSMAX]; //This is "common/jt9com/..." in fortran float savg[NSMAX]; - float c0[2*NTMAX*1500]; short int d2[NTMAX*12000]; int nutc; //UTC as integer, HHMM int ndiskdat; //1 ==> data read from *.wav file @@ -25,8 +25,8 @@ extern struct { int nsave; int nagain; int ndepth; - int nrxlog; - int nfsample; + int ntxmode; + int nmode; char datetime[20]; } jt9com_; diff --git a/devsetup.cpp b/devsetup.cpp index f8cb16dde..57171346f 100644 --- a/devsetup.cpp +++ b/devsetup.cpp @@ -1,10 +1,13 @@ #include "devsetup.h" #include +#include #include #define MAXDEVICES 100 extern double dFreq[16]; +qint32 g2_iptt; +qint32 g2_COMportOpen; //----------------------------------------------------------- DevSetup() DevSetup::DevSetup(QWidget *parent) : QDialog(parent) @@ -13,10 +16,10 @@ DevSetup::DevSetup(QWidget *parent) : QDialog(parent) m_restartSoundIn=false; m_restartSoundOut=false; m_firstCall=true; - m_iptt=0; + g2_iptt=0; m_test=0; m_bRigOpen=false; - m_COMportOpen=0; + g2_COMportOpen=0; } DevSetup::~DevSetup() @@ -25,6 +28,13 @@ DevSetup::~DevSetup() void DevSetup::initDlg() { + QString m_appDir = QApplication::applicationDirPath(); + QString inifile = m_appDir + "/wsjtx.ini"; + QSettings settings(inifile, QSettings::IniFormat); + settings.beginGroup("Common"); + QString catPortDriver = settings.value("CATdriver","None").toString(); + settings.endGroup(); + int k,id; int numDevices=Pa_GetDeviceCount(); @@ -40,6 +50,8 @@ void DevSetup::initDlg() nchin=pdi->maxInputChannels; if(nchin>0) { m_inDevList[k]=id; + if (id == m_paInDevice) + m_nDevIn = k; k++; sprintf((char*)(pa_device_name),"%s",pdi->name); sprintf((char*)(pa_device_hostapi),"%s", @@ -77,6 +89,8 @@ void DevSetup::initDlg() nchout=pdi->maxOutputChannels; if(nchout>0) { m_outDevList[k]=id; + if (id == m_paOutDevice) + m_nDevOut = k; k++; sprintf((char*)(pa_device_name),"%s",pdi->name); sprintf((char*)(pa_device_hostapi),"%s", @@ -115,6 +129,7 @@ void DevSetup::initDlg() this, SLOT(p4Error())); p4.start("rigctl -l"); p4.waitForFinished(1000); + ui.rigComboBox->addItem(" 9998 Commander"); ui.rigComboBox->addItem(" 9999 Ham Radio Deluxe"); QPalette pal(ui.myCallEntry->palette()); @@ -136,8 +151,9 @@ void DevSetup::initDlg() ui.comboBoxSndOut->setCurrentIndex(m_nDevOut); ui.cbID73->setChecked(m_After73); ui.cbPSKReporter->setChecked(m_pskReporter); - m_paInDevice=m_inDevList[m_nDevIn]; - m_paOutDevice=m_outDevList[m_nDevOut]; + ui.cbSplit->setChecked(m_bSplit); + ui.cbXIT->setChecked(m_bXIT); + ui.cbXIT->setVisible(false); enableWidgets(); @@ -176,6 +192,7 @@ void DevSetup::initDlg() ui.catPortComboBox->addItem("/dev/ttyUSB1"); ui.catPortComboBox->addItem("/dev/ttyUSB2"); ui.catPortComboBox->addItem("/dev/ttyUSB3"); + ui.catPortComboBox->addItem(catPortDriver); ui.pttComboBox->addItem("/dev/ttyS0"); ui.pttComboBox->addItem("/dev/ttyS1"); @@ -280,7 +297,7 @@ void DevSetup::accept() if(m_bRigOpen) { rig->close(); - if(m_rig!=9999) delete rig; + if(m_rig<9900) delete rig; m_bRigOpen=false; } @@ -414,18 +431,22 @@ void DevSetup::on_testCATButton_clicked() if(!m_catEnabled) return; if(m_bRigOpen) { rig->close(); - if(m_rig!=9999) delete rig; + if(m_rig<9900) delete rig; m_bRigOpen=false; } rig = new Rig(); - if(m_rig != 9999) { + if(m_rig<9900) { if (!rig->init(m_rig)) { msgBox("Rig init failure"); return; } - rig->setConf("rig_pathname", m_catPort.toLatin1().data()); + QString sCATport=m_catPort; +#ifdef WIN32 + sCATport="\\\\.\\" + m_catPort; //Allow COM ports above 9 +#endif + rig->setConf("rig_pathname", sCATport.toLatin1().data()); char buf[80]; sprintf(buf,"%d",m_serialRate); rig->setConf("serial_speed",buf); @@ -470,7 +491,9 @@ void DevSetup::on_testPTTButton_clicked() { m_test=1-m_test; if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { - ptt(m_pttPort,m_test,&m_iptt,&m_COMportOpen); +// qDebug() << "devsetup line 492:" << m_pttPort << m_test << &g2_iptt << &g2_COMportOpen; + ptt(m_pttPort,m_test,&g2_iptt,&g2_COMportOpen); +// qDebug() << "devsetup line 494:" << m_pttPort << m_test << &g2_iptt << &g2_COMportOpen; } if(m_pttMethodIndex==0 and !m_bRigOpen) { on_testCATButton_clicked(); @@ -522,8 +545,10 @@ void DevSetup::enableWidgets() ui.testCATButton->setEnabled(m_catEnabled); ui.label_4->setEnabled(m_catEnabled); ui.label_47->setEnabled(m_catEnabled); + ui.cbSplit->setEnabled(m_catEnabled); + ui.cbXIT->setEnabled(m_catEnabled); - bool bSerial=m_catEnabled and (m_rig!=9999); + bool bSerial=m_catEnabled and (m_rig<9900); ui.catPortComboBox->setEnabled(bSerial); ui.serialRateComboBox->setEnabled(bSerial); ui.dataBitsComboBox->setEnabled(bSerial); @@ -541,9 +566,21 @@ void DevSetup::enableWidgets() ui.pollSpinBox->setEnabled(m_catEnabled); bool b1=(m_pttMethodIndex==1 or m_pttMethodIndex==2); ui.pttComboBox->setEnabled(b1); - bool b2 = (m_catEnabled and m_pttMethodIndex==1 and m_rig!=9999) or - (m_catEnabled and m_pttMethodIndex==2 and m_rig!=9999); - bool b3 = (m_catEnabled and m_pttMethodIndex==0 and m_rig==9999); + bool b2 = (m_catEnabled and m_pttMethodIndex==1 and m_rig<9900) or + (m_catEnabled and m_pttMethodIndex==2 and m_rig<9900); + bool b3 = (m_catEnabled and m_pttMethodIndex==0 and m_rig>=9900); // ui.testPTTButton->setEnabled(b1 or b2); - ui.testPTTButton->setEnabled(b1 or b2 or b3); //Include PTT via HRD + ui.testPTTButton->setEnabled(b1 or b2 or b3); //Include PTT via HRD or Commander +} + +void DevSetup::on_cbSplit_toggled(bool checked) +{ + m_bSplit=checked; + if(m_bSplit and m_bXIT) ui.cbXIT->setChecked(false); +} + +void DevSetup::on_cbXIT_toggled(bool checked) +{ + m_bXIT=checked; + if(m_bSplit and m_bXIT) ui.cbSplit->setChecked(false); } diff --git a/devsetup.h b/devsetup.h index d5a2649f6..392010498 100644 --- a/devsetup.h +++ b/devsetup.h @@ -35,9 +35,7 @@ public: qint32 m_stopBits; qint32 m_stopBitsIndex; qint32 m_handshakeIndex; - qint32 m_iptt; qint32 m_test; - qint32 m_COMportOpen; qint32 m_poll; qint32 m_tmp; @@ -50,6 +48,8 @@ public: bool m_bRigOpen; bool m_bDTRoff; bool m_pttData; + bool m_bSplit; + bool m_bXIT; QString m_myCall; QString m_myGrid; @@ -93,6 +93,10 @@ private slots: void on_pttComboBox_currentIndexChanged(int index); void on_pttMethodComboBox_currentIndexChanged(int index); + void on_cbSplit_toggled(bool checked); + + void on_cbXIT_toggled(bool checked); + private: Rig* rig; void msgBox(QString t); diff --git a/devsetup.ui b/devsetup.ui index 4f79c3890..930ae83fd 100644 --- a/devsetup.ui +++ b/devsetup.ui @@ -6,7 +6,7 @@ 0 0 - 548 + 569 493 @@ -584,6 +584,32 @@ Qt::Horizontal + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + RTS/DTR OFF + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + 40 @@ -741,6 +767,9 @@ Qt::Horizontal + + QSizePolicy::Fixed + 40 @@ -750,9 +779,25 @@ - + + + Use special Tx command for "data" + - RTS/DTR OFF + Data + + + + + + + Use normal Tx command + + + Mic + + + true @@ -899,7 +944,7 @@ - + Qt::Horizontal @@ -915,25 +960,9 @@ - - - Use special Tx command for "data" - + - Data - - - - - - - Use normal Tx command - - - Mic - - - true + Split Tx @@ -1010,6 +1039,29 @@ + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + XIT + + + @@ -1313,6 +1365,9 @@ 16777215 + + 5W DPL 73 GL + @@ -1360,6 +1415,9 @@ 16777215 + + 20W DPL 73 GL + @@ -1554,6 +1612,9 @@ 16777215 + + + @@ -1576,6 +1637,9 @@ 16777215 + + TNX 73 GL + @@ -1598,6 +1662,9 @@ 16777215 + + 10W DPL 73 GL + @@ -2457,11 +2524,8 @@ catPortComboBox dataBitsComboBox serialRateComboBox - cbDTRoff stopBitsComboBox handshakeComboBox - rbData - rbMic testCATButton testPTTButton pollSpinBox diff --git a/getfile.cpp b/getfile.cpp index 79a3de405..9ad871fe8 100644 --- a/getfile.cpp +++ b/getfile.cpp @@ -1,11 +1,19 @@ #include "getfile.h" #include -#include #include #include #ifdef WIN32 #include +#else +#include +#include +#include +#include +#include +#include +#include +#include #endif void getfile(QString fname, int ntrperiod) @@ -123,6 +131,7 @@ float gran() int ptt(int nport, int ntx, int* iptt, int* nopen) { +// qDebug() << "getfile ptt(), line 129:" << nport << ntx << *iptt << *nopen; #ifdef WIN32 static HANDLE hFile; char s[10]; @@ -130,7 +139,7 @@ int ptt(int nport, int ntx, int* iptt, int* nopen) if(nport==0) { *iptt=ntx; - return(0); + return 0; } if(ntx && (!(*nopen))) { @@ -160,6 +169,34 @@ int ptt(int nport, int ntx, int* iptt, int* nopen) *nopen=0; } if((i3+i4+i5+i6+i9+i00)==-999) return 1; //Silence compiler warning +// qDebug() << "getfile ptt(), line 167:" << nport << ntx << *iptt << *nopen; + return 0; +#else +// qDebug() << "getfile ptt(), line 170:" << nport << ntx << *iptt << *nopen; +// ptt_(nport,ntx, iptt, nopen); + +// 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 diff --git a/getfile.h b/getfile.h index 2d4ffed07..39a5c7d1a 100644 --- a/getfile.h +++ b/getfile.h @@ -10,5 +10,4 @@ float gran(); //int ptt(int* nport, int* ntx, int* iptt); int ptt(int nport, int ntx, int* iptt, int* nopen); - #endif // GETFILE_H diff --git a/lib/Makefile.MinGW b/lib/Makefile.MinGW index cfd909493..e09924b6f 100644 --- a/lib/Makefile.MinGW +++ b/lib/Makefile.MinGW @@ -20,7 +20,7 @@ CFLAGS = -I. -fbounds-check -mno-stack-arg-probe %.o: %.F90 ${FC} ${FFLAGS} -c $< -all: libjt9.a jt9sim.exe jt9.exe jt9code.exe test9.exe +all: libjt9.a jt9sim.exe jt9.exe jt9code.exe jt65.exe OBJS1 = pctile.o graycode.o sort.o ssort.o \ unpackmsg.o igray.o unpackcall.o unpackgrid.o \ @@ -30,10 +30,15 @@ OBJS1 = pctile.o graycode.o sort.o ssort.o \ symspec.o analytic.o db.o genjt9.o \ packbits.o unpackbits.o encode232.o interleave9.o \ entail.o fano232.o gran.o sync9.o decode9.o \ - fil3.o redsync.o decoder.o grid2n.o n2grid.o timer.o \ + fil3.o decoder.o grid2n.o n2grid.o timer.o \ softsym.o getlags.o afc9.o fchisq.o twkfreq.o downsam9.o \ peakdt9.o symspec2.o stdmsg.o morse.o azdist.o geodist.o \ - fillcom.o chkss2.o zplot9.o + fillcom.o chkss2.o zplot9.o flat2.o \ + jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ + filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ + extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ + move.o indexx.o graycode65.o twkfreq65.o smo121.o \ + wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o libjt9.a: $(OBJS1) ar cr libjt9.a $(OBJS1) @@ -54,15 +59,9 @@ OBJS4 = jt9code.o jt9code.exe: $(OBJS4) libjt9.a $(FC) -o jt9code.exe $(OBJS4) libjt9.a -OBJS5 = test9.o -test9.exe: $(OBJS5) libjt9.a - $(FC) -o test9.exe $(OBJS5) libjt9.a ../libfftw3f_win.a - -OBJS6 = wsjt24d.o wsjt24.o sync24.o decode24.o ps24.o flat1.o \ - xcor24.o slope.o peakup.o interleave24.o getmet24.o smo.o \ - deep24.o encode4.o chkmsg.o avemsg4.o extract4.o -wsjt24d.exe: $(OBJS6) libjt9.a - $(FC) -o wsjt24d.exe $(OBJS6) libjt9.a ../libfftw3f_win.a +OBJS5 = jt65.o +jt65.exe: $(OBJS5) libjt9.a + $(FC) -o jt65.exe $(OBJS5) libjt9.a ../libfftw3f_win.a INCPATH = -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include/QtCore' \ -I'c:/QtSDK/Desktop/Qt/4.7.4/mingw/include' \ @@ -75,9 +74,6 @@ sync9.o: sync9.f90 jt9sync.f90 spec9.o: spec9.f90 jt9sync.f90 $(FC) $(FFLAGS) -c spec9.f90 -peakdf9.o: peakdf9.f90 jt9sync.f90 - $(FC) $(FFLAGS) -c peakdf9.f90 - peakdt9.o: peakdt9.f90 jt9sync.f90 $(FC) $(FFLAGS) -c peakdt9.f90 @@ -105,7 +101,17 @@ sec_midn.o: sec_midn.f90 tstrig.o: tstrig.c $(CC) -c -Wall -I..\..\..\hamlib-1.2.15.3\include tstrig.c +init_rs.o: init_rs.c + $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c + +encode_rs.o: encode_rs.c + $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c + +decode_rs.o: decode_rs.c + $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c + + .PHONY : clean clean: - rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt9test.exe + rm -f *.o libjt9.a wsjtx.exe jt9sim.exe jt9.exe jt65.exe diff --git a/lib/Makefile.linux b/lib/Makefile.linux index 086d310b0..19e6096e7 100644 --- a/lib/Makefile.linux +++ b/lib/Makefile.linux @@ -23,14 +23,19 @@ OBJS1 = pctile.o graycode.o sort.o ssort.o \ grid2k.o unpacktext.o getpfx2.o packmsg.o deg2grid.o \ packtext.o getpfx1.o packcall.o k2grid.o packgrid.o \ nchar.o four2a.o grid2deg.o pfxdump.o f77_wisdom.o \ - symspec.o analytic.o db.o genjt9.o ptt_unix.o \ + symspec.o analytic.o db.o genjt9.o \ packbits.o unpackbits.o encode232.o interleave9.o \ entail.o fano232.o gran.o sync9.o decode9.o \ - fil3.o redsync.o decoder.o grid2n.o n2grid.o timer.o \ + fil3.o decoder.o grid2n.o n2grid.o timer.o \ softsym.o peakdt9.o getlags.o afc9.o fchisq.o \ twkfreq.o downsam9.o symspec2.o ipcomm.o sleep_msec.o \ stdmsg.o sec_midn.o cutil.o azdist.o geodist.o morse.o \ - fillcom.o chkss2.o + fillcom.o chkss2.o zplot9.o flat2.o \ + jt65a.o symspec65.o flat65.o ccf65.o decode65a.o \ + filbig.o fil6521.o afc65b.o decode65b.o setup65.o \ + extract.o fchisq65.o demod64a.o chkhist.o interleave63.o ccf2.o \ + move.o indexx.o graycode65.o twkfreq65.o smo121.o \ + wrapkarn.o init_rs.o encode_rs.o decode_rs.o gen65.o libjt9.a: $(OBJS1) ar cr libjt9.a $(OBJS1) @@ -38,7 +43,7 @@ libjt9.a: $(OBJS1) OBJS2 = jt9.o jt9a.o jt9b.o jt9c.o -jt9: $(OBJS2) libjt9.a +jt9: $(OBJS2) libjt9.a g++ -o jt9 $(OBJS2) libjt9.a -lfftw3f -lgfortran -lQtCore cp jt9 ../../wsjtx_install @@ -84,6 +89,15 @@ ipcomm.o: ipcomm.cpp sec_midn.o: sec_midn.f90 $(FC) -c -fno-second-underscore sec_midn.f90 +init_rs.o: init_rs.c + $(CC) -c -DBIGSYM=1 -o init_rs.o init_rs.c + +encode_rs.o: encode_rs.c + $(CC) -c -DBIGSYM=1 -o encode_rs.o encode_rs.c + +decode_rs.o: decode_rs.c + $(CC) -c -DBIGSYM=1 -o decode_rs.o decode_rs.c + .PHONY : clean clean: diff --git a/lib/afc65b.f90 b/lib/afc65b.f90 new file mode 100644 index 000000000..f78f27527 --- /dev/null +++ b/lib/afc65b.f90 @@ -0,0 +1,59 @@ +subroutine afc65b(cx,npts,fsample,nflip,a,ccfbest,dtbest) + +! Find delta f, f1, f2 ==> a(1:3) + + complex cx(npts) + real a(5),deltaa(5) + + a(1)=0. + a(2)=0. + a(3)=0. + a(4)=0. + deltaa(1)=2.0 + deltaa(2)=2.0 + deltaa(3)=2.0 + deltaa(4)=0.05 + nterms=3 !Maybe 2 is enough? + +! Start the iteration + chisqr=0. + chisqr0=1.e6 + do iter=1,3 !One iteration is enough? + do j=1,nterms + chisq1=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + fn=0. + delta=deltaa(j) +10 a(j)=a(j)+delta + chisq2=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + 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=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + 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. + enddo + chisqr=fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + if(chisqr/chisqr0.gt.0.9999) go to 30 + chisqr0=chisqr + enddo + +30 ccfbest=ccfmax * (1378.125/fsample)**2 + dtbest=dtmax + + return +end subroutine afc65b diff --git a/lib/ccf2.f90 b/lib/ccf2.f90 new file mode 100644 index 000000000..4e74a52ef --- /dev/null +++ b/lib/ccf2.f90 @@ -0,0 +1,45 @@ +subroutine ccf2(ss,nz,nflip,ccfbest,lagpk) + + parameter (LAGMAX=60) +! parameter (LAGMAX=200) + real ss(nz) + real ccf(-LAGMAX:LAGMAX) + integer npr(126) + +! The JT65 pseudo-random sync pattern: + data npr/ & + 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, & + 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, & + 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, & + 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, & + 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, & + 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, & + 1,1,1,1,1,1/ + save + + ccfbest=0. + lag1=-LAGMAX + lag2=LAGMAX + do lag=lag1,lag2 + s0=0. + s1=0. + do i=1,126 + j=2*(8*i + 43) + lag + if(j.ge.1 .and. j.le.nz-8) then + x=ss(j)+ss(j+8) !Add two half-symbol contributions + if(npr(i).eq.0) then + s0=s0 + x + else + s1=s1 + x + endif + endif + enddo + ccf(lag)=nflip*(s1-s0) + if(ccf(lag).gt.ccfbest) then + ccfbest=ccf(lag) + lagpk=lag + endif + enddo + + return +end subroutine ccf2 diff --git a/lib/ccf65.f90 b/lib/ccf65.f90 new file mode 100644 index 000000000..9e667df87 --- /dev/null +++ b/lib/ccf65.f90 @@ -0,0 +1,117 @@ +subroutine ccf65(ss,nhsym,ssmax,sync1,dt1,flipk,syncshort,snr2,dt2) + + parameter (NFFT=512,NH=NFFT/2) + real ss(322) !Input: half-symbol normalized powers + real s(NFFT) !CCF = ss*pr + complex cs(0:NH) !Complex FT of s + real s2(NFFT) !CCF = ss*pr2 + complex cs2(0:NH) !Complex FT of s2 + real pr(NFFT) !JT65 pseudo-random sync pattern + complex cpr(0:NH) !Complex FT of pr + real pr2(NFFT) !JT65 shorthand pattern + complex cpr2(0:NH) !Complex FT of pr2 + real tmp1(322) + real ccf(-11:54) + logical first + integer npr(126) + data first/.true./ + equivalence (s,cs),(pr,cpr),(s2,cs2),(pr2,cpr2) + save + +! The JT65 pseudo-random sync pattern: + data npr/ & + 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, & + 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, & + 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, & + 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, & + 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, & + 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, & + 1,1,1,1,1,1/ + + if(first) then +! Initialize pr, pr2; compute cpr, cpr2. + fac=1.0/NFFT + do i=1,NFFT + pr(i)=0. + pr2(i)=0. + k=2*mod((i-1)/8,2)-1 + if(i.le.NH) pr2(i)=fac*k + enddo + do i=1,126 + j=2*i + pr(j)=fac*(2*npr(i)-1) +! Not sure why, but it works significantly better without the following line: +! pr(j-1)=pr(j) + enddo + call four2a(cpr,NFFT,1,-1,0) + call four2a(cpr2,NFFT,1,-1,0) + first=.false. + endif + +! Look for JT65 sync pattern and shorthand square-wave pattern. + ccfbest=0. + ccfbest2=0. + do i=1,nhsym-1 + s(i)=min(ssmax,ss(i)+ss(i+1)) +! s(i)=ss(i)+ss(i+1) + enddo + + call pctile(s,nhsym-1,50,base) + s(1:nhsym-1)=s(1:nhsym-1)-base + s(nhsym:NFFT)=0. + call four2a(cs,NFFT,1,-1,0) !Real-to-complex FFT + do i=0,NH +! cs2(i)=cs(i)*conjg(cpr2(i)) !Mult by complex FFT of pr2 + cs(i)=cs(i)*conjg(cpr(i)) !Mult by complex FFT of pr + enddo + call four2a(cs,NFFT,1,1,-1) !Complex-to-real inv-FFT +! call four2a(cs2,NFFT,1,1,-1) !Complex-to-real inv-FFT + + do lag=-11,54 !Check for best JT65 sync + j=lag + if(j.lt.1) j=j+NFFT + ccf(lag)=s(j) +! if(abs(ccf(lag)).gt.ccfbest) then + if(ccf(lag).gt.ccfbest) then !No inverted sync for use at HF +! ccfbest=abs(ccf(lag)) + ccfbest=ccf(lag) + lagpk=lag + flipk=1.0 +! if(ccf(lag).lt.0.0) flipk=-1.0 + endif + enddo + +! do lag=-11,54 !Check for best shorthand +! ccf2=s2(lag+28) +! if(ccf2.gt.ccfbest2) then +! ccfbest2=ccf2 +! lagpk2=lag +! endif +! enddo + +! Find rms level on baseline of "ccfblue", for normalization. + sum=0. + do lag=-11,54 + if(abs(lag-lagpk).gt.1) sum=sum + ccf(lag) + enddo + base=sum/50.0 + sq=0. + do lag=-11,54 + if(abs(lag-lagpk).gt.1) sq=sq + (ccf(lag)-base)**2 + enddo + rms=sqrt(sq/49.0) + sync1=ccfbest/rms - 4.0 + dt1=lagpk*(2048.0/11025.0) - 2.5 + +! Find base level for normalizing snr2. + do i=1,nhsym + tmp1(i)=ss(i) + enddo + call pctile(tmp1,nhsym,40,base) + snr2=0.398107*ccfbest2/base !### empirical + syncshort=0.5*ccfbest2/rms - 4.0 !### better normalizer than rms? +! dt2=(2.5 + lagpk2*(2048.0/11025.0)) + dt2=0. + + return +end subroutine ccf65 diff --git a/lib/char.h b/lib/char.h new file mode 100644 index 000000000..cc477ec7c --- /dev/null +++ b/lib/char.h @@ -0,0 +1,57 @@ +/* Include file to configure the RS codec for character symbols + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define DTYPE unsigned char + +/* Reed-Solomon codec control block */ +struct rs { + int mm; /* Bits per symbol */ + int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define PAD (rs->pad) +#define A0 (NN) + +#define ENCODE_RS encode_rs_char +#define DECODE_RS decode_rs_char +#define INIT_RS init_rs_char +#define FREE_RS free_rs_char + +void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); +void *INIT_RS(int symsize,int gfpoly,int fcr, + int prim,int nroots,int pad); +void FREE_RS(void *p); + + + + + diff --git a/lib/chkhist.f90 b/lib/chkhist.f90 new file mode 100644 index 000000000..6aa4a8072 --- /dev/null +++ b/lib/chkhist.f90 @@ -0,0 +1,21 @@ +subroutine chkhist(mrsym,nmax,ipk) + + integer mrsym(63) + integer hist(0:63) + + hist=0 + do j=1,63 + i=mrsym(j) + hist(i)=hist(i)+1 + enddo + + nmax=0 + do i=0,63 + if(hist(i).gt.nmax) then + nmax=hist(i) + ipk=i+1 + endif + enddo + + return +end subroutine chkhist diff --git a/lib/constants.f90 b/lib/constants.f90 new file mode 100644 index 000000000..2acf6bbdc --- /dev/null +++ b/lib/constants.f90 @@ -0,0 +1,5 @@ + parameter (NTMAX=120) + parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes + parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate + parameter (NSMAX=6827) !Max length of saved spectra + parameter (MAXFFT3=16384) diff --git a/lib/decode24.f90 b/lib/decode24.f90 deleted file mode 100644 index 77ab76475..000000000 --- a/lib/decode24.f90 +++ /dev/null @@ -1,176 +0,0 @@ -subroutine decode24(dat,npts,dtx,dfx,flip,mode,mode4,decoded,ncount, & - deepbest,qbest,submode) - -! Decodes JT65 data, assuming that DT and DF have already been determined. - - parameter (MAXAVE=120) - real dat(npts) !Raw data - character decoded*22,deepmsg*22,deepbest*22 - character*12 mycall,hiscall - character*6 hisgrid - character*72 c72 - character submode*1 - real*8 dt,df,phi,f0,dphi,twopi,phi1,dphi1 - complex*16 cz,cz1,c0,c1 - integer*1 symbol(207) - real*4 rsymbol(207,7) - real*4 sym(207) - integer nsum(7) - integer*1 data1(13) !Decoded data (8-bit bytes) - integer data4a(9) !Decoded data (8-bit bytes) - integer data4(12) !Decoded data (6-bit bytes) - integer amp,delta - integer mettab(0:255,0:1) !Metric table - integer nch(7) - integer npr2(207) - common/ave/ppsave(207,7,MAXAVE),nflag(MAXAVE),nsave,iseg(MAXAVE) - data mode0/-999/ - data nsum/7*0/,rsymbol/1449*0.0/ - data npr2/ & - 0,0,0,0,1,1,0,0,0,1,1,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0, & - 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,0,0, & - 1,0,0,1,0,0,1,1,1,1,1,0,0,0,1,0,1,0,0,0,1,1,1,1,0,1,1,0,0,1, & - 0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0,1,0,1, & - 0,1,1,1,0,0,1,0,1,1,0,1,1,1,1,0,0,0,0,1,1,0,1,1,0,0,0,1,1,1, & - 0,1,1,1,0,1,1,1,0,0,1,0,0,0,1,1,0,1,1,0,0,1,0,0,0,1,1,1,1,1, & - 1,0,0,1,1,0,0,0,0,1,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,1/ - - data nch/1,2,4,9,18,36,72/ - save mettab,mode0,nsum,rsymbol - - if(mode.ne.mode0) call getmet24(mode,mettab) - mode0=mode - twopi=8*atan(1.d0) - dt=2.d0/11025 !Sample interval (2x downsampled data) - df=11025.d0/2520.d0 - nsym=206 - amp=15 - istart=nint(dtx/dt) !Start index for synced FFTs - if(istart.lt.0) istart=0 - nchips=0 - ich=0 - qbest=0. - deepmsg=' ' - ichbest=-1 - -! Should amp be adjusted according to signal strength? - -! Compute soft symbols using differential BPSK demodulation - c0=0. !### C0=amp ??? - k=istart - phi=0.d0 - phi1=0.d0 - -40 ich=ich+1 - nchips=nch(ich) - nspchip=1260/nchips - k=istart - phi=0.d0 - phi1=0.d0 - fac2=1.e-8 * sqrt(float(mode4)) - do j=1,nsym+1 - if(flip.gt.0.0) then - f0=1270.46 + dfx + (npr2(j)-1.5)*mode4*df - f1=1270.46 + dfx + (2+npr2(j)-1.5)*mode4*df - else - f0=1270.46 + dfx + (1-npr2(j)-1.5)*mode4*df - f1=1270.46 + dfx + (3-npr2(j)-1.5)*mode4*df - endif - dphi=twopi*dt*f0 - dphi1=twopi*dt*f1 - sq0=0. - sq1=0. - do nc=1,nchips - phi=0.d0 - phi1=0.d0 - c0=0. - c1=0. - do i=1,nspchip - k=k+1 - phi=phi+dphi - phi1=phi1+dphi1 - cz=dcmplx(cos(phi),-sin(phi)) - cz1=dcmplx(cos(phi1),-sin(phi1)) - if(k.le.npts) then - c0=c0 + dat(k)*cz - c1=c1 + dat(k)*cz1 - endif - enddo - sq0=sq0 + real(c0)**2 + aimag(c0)**2 - sq1=sq1 + real(c1)**2 + aimag(c1)**2 - enddo - sq0=fac2*sq0 - sq1=fac2*sq1 - rsym=amp*(sq1-sq0) - r=rsym+128. - if(r.gt.255.0) r=255.0 - if(r.lt.0.0) r=0.0 - i4=nint(r) - if(i4.gt.127) i4=i4-256 - if(j.ge.1) then - symbol(j)=i4 -! rsymbol(j,ich)=rsymbol(j,ich) + rsym - rsymbol(j,ich)=rsym - sym(j)=rsym - endif - enddo - -!### The following does simple message averaging: -! nsum(ich)=nsum(ich)+1 -! do j=1,207 -! sym(j)=rsymbol(j,ich)/nsum(ich) -! r=sym(j) + 128. -! if(r.gt.255.0) r=255.0 -! if(r.lt.0.0) r=0.0 -! i4=nint(r) -! if(i4.gt.127) i4=i4-256 -! symbol(j)=i4 -! enddo -!### - - call extract4(sym,nadd,ncount,decoded) !Do the KV decode - - qual=0. !Now try deep search - neme=1 - mycall='VK7MO' - hiscall='W5LUA' - hisgrid='EM13' - call deep24(sym(2),neme,flip,mycall,hiscall,hisgrid,deepmsg,qual) - if(qual.gt.qbest) then - qbest=qual - deepbest=deepmsg - ichbest=ich - endif - - if(ncount.ge.0) go to 100 - if(mode.eq.7 .and. nchips.lt.mode4) go to 40 - -100 continue -!100 do i=1,9 -! i4=data1(i) -! if(i4.lt.0) i4=i4+256 -! data4a(i)=i4 -! enddo -! write(c72,1100) (data4a(i),i=1,9) -!1100 format(9b8.8) -! read(c72,1102) data4 -!1102 format(12b6) - -! decoded=' ' -! submode=' ' - - if(ncount.lt.0) then - decoded=deepbest - submode=char(ichar('A')+ichbest-1) - qual=qbest - endif -! if(decoded(1:6).eq.'000AAA') then -! decoded='***WRONG MODE?***' -! ncount=-1 -! endif - -! Save symbol spectra for possible decoding of average. - ppsave(1:207,1:7,nsave)=rsymbol(1:207,1:7) - - return -end subroutine decode24 diff --git a/lib/decode65a.f90 b/lib/decode65a.f90 new file mode 100644 index 000000000..ea61d359f --- /dev/null +++ b/lib/decode65a.f90 @@ -0,0 +1,95 @@ +subroutine decode65a(dd,npts,newdat,f0,nflip,mode65,sync2,a,dt, & + nbmkv,nhist,decoded) + +! Apply AFC corrections to a candidate JT65 signal, then decode it. + + parameter (NMAX=60*12000) !Samples per 60 s + real*4 dd(NMAX) !92 MB: raw data from Linrad timf2 + complex cx(NMAX/8) !Data at 1378.125 samples/s + complex c5x(NMAX/32) !Data at 344.53125 Hz + complex c5a(512) + real s2(66,126) + real a(5) + logical first + character decoded*22 + data first/.true./,jjjmin/1000/,jjjmax/-1000/ + data nhz0/-9999999/ + save + +! Mix sync tone to baseband, low-pass filter, downsample to 1378.125 Hz + dt00=dt + call timer('filbig ',0) + call filbig(dd,npts,f0,newdat,cx,n5,sq0) + call timer('filbig ',1) + +! NB: cx has sample rate 12000*77125/672000 = 1378.125 Hz + +! Find best DF, f1, f2, and DT. Start by downsampling to 344.53125 Hz + call timer('fil6521 ',0) +! Add some zeros at start of c5 arrays -- empirical fix for negative DT's + nadd=1089 + c5x(:nadd)=0. + call fil6521(cx,n5,c5x(nadd+1),n6) + n6=n6+nadd + call timer('fil6521 ',1) + + fsample=1378.125/4. + a(5)=dt00 + i0=nint((a(5)+0.5)*fsample) - 2 + nadd + if(i0.lt.1) then +! write(23,*) 'i0 too small in decode1a:',i0,f0,a(5),fsample,nadd +! flush(23) + i0=1 + endif + nz=n6+1-i0 + +! We're looking only at sync tone here... so why not downsample by another +! factor of 1/8, say? Should be a significant execution speed-up. + call timer('afc65b ',0) +! Best fit for DF, f1, and f2 + call afc65b(c5x(i0),nz,fsample,nflip,a,ccfbest,dtbest) + call timer('afc65b ',1) + + sync2=3.7e-4*ccfbest/sq0 !Constant is empirical + +! Apply AFC corrections to the time-domain signal +! Now we are back to using the 1378.125 Hz sample rate, enough to +! accommodate the full JT65C bandwidth. + + call timer('twkfreq ',0) + call twkfreq65(cx,n5,a) + call timer('twkfreq ',1) + +! Compute spectrum for each half symbol. +! Adding or subtracting a small number (e.g., 5) to j may make it decode.\ +! NB: might want to try computing full-symbol spectra (nfft=512, even for +! submodes B and C). + + nsym=126 + nfft=512 + j=(dt00+dtbest+2.685)*1378.125 + if(j.lt.0) j=0 + + call timer('sh_ffts ',0) + do k=1,nsym + do i=1,nfft + j=j+1 + c5a(i)=cx(j) + enddo + call four2a(c5a,nfft,1,1,1) + do i=1,66 + jj=i + if(mode65.eq.2) jj=2*i-1 + if(mode65.eq.4) jj=4*i-3 + s2(i,k)=real(c5a(jj))**2 + aimag(c5a(jj))**2 + enddo + enddo + call timer('sh_ffts ',1) + + call timer('dec65b ',0) + call decode65b(s2,nflip,mode65,nbmkv,nhist,decoded) + dt=dt00 + dtbest + 1.7 + call timer('dec65b ',1) + + return +end subroutine decode65a diff --git a/lib/decode65b.f90 b/lib/decode65b.f90 new file mode 100644 index 000000000..729a218ec --- /dev/null +++ b/lib/decode65b.f90 @@ -0,0 +1,36 @@ +subroutine decode65b(s2,nflip,mode65,nbmkv,nhist,decoded) + + real s2(66,126) + real s3(64,63) + logical first,ltext + character decoded*22 + common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2) + data first/.true./ + save + + if(first) call setup65 + first=.false. + + do j=1,63 + k=mdat(j) !Points to data symbol + if(nflip.lt.0) k=mdat2(j) + do i=1,64 + s3(i,j)=s2(i+2,k) + enddo + k=mdat2(j) !Points to data symbol + if(nflip.lt.0) k=mdat(j) + enddo + + nadd=mode65 + call extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv) !Extract the message +! Suppress "birdie messages" and other garbage decodes: + if(decoded(1:7).eq.'000AAA ') ncount=-1 + if(decoded(1:7).eq.'0L6MWK ') ncount=-1 + if(nflip.lt.0 .and. ltext) ncount=-1 + if(ncount.lt.0) then + nbmkv=0 + decoded=' ' + endif + + return +end subroutine decode65b diff --git a/lib/decode9.f90 b/lib/decode9.f90 index b68d742c8..06809eb76 100644 --- a/lib/decode9.f90 +++ b/lib/decode9.f90 @@ -16,7 +16,7 @@ subroutine decode9(i1SoftSymbols,limit,nlim,msg) logical first integer*4 mettab(0:255,0:1) data first/.true./ - data xx0/ & + data xx0/ & !Metric table 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, & 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, & 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, 1.000, & @@ -53,9 +53,8 @@ subroutine decode9(i1SoftSymbols,limit,nlim,msg) if(first) then ! Get the metric table -! bias=0.37 !To be optimized, in decoder program bias=0.5 - scale=10 ! ... ditto ... + scale=10 do i=0,255 mettab(i,0)=nint(scale*(xx0(i)-bias)) if(i.ge.1) mettab(256-i,1)=mettab(i,0) diff --git a/lib/decode_rs.c b/lib/decode_rs.c index aecc47faf..ac85eddd7 100644 --- a/lib/decode_rs.c +++ b/lib/decode_rs.c @@ -9,7 +9,7 @@ #include -#define NULL ((void *)0) +//#define NULL ((void *)0) #define min(a,b) ((a) < (b) ? (a) : (b)) #ifdef FIXED diff --git a/lib/decoder.f90 b/lib/decoder.f90 index 35e7e8f55..9bda7b64b 100644 --- a/lib/decoder.f90 +++ b/lib/decoder.f90 @@ -1,23 +1,21 @@ -subroutine decoder(ss,c0,nstandalone) +subroutine decoder(ss,id2) ! Decoder for JT9. - parameter (NTMAX=120) - parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes - parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate - parameter (NSMAX=1365) !Max length of saved spectra + include 'constants.f90' real ss(184,NSMAX) character*22 msg - character*80 fmt character*20 datetime real*4 ccfred(NSMAX) real*4 red2(NSMAX) logical ccfok(NSMAX) logical done(NSMAX) + logical done65 + integer*2 id2(NTMAX*12000) + real*4 dd(NTMAX*12000) integer*1 i1SoftSymbols(207) - complex c0(NDMAX) common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, & - kin,nzhsym,nsave,nagain,ndepth,nrxlog,nfsample,datetime + kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime common/tracer/limtrace,lu save @@ -27,48 +25,40 @@ subroutine decoder(ss,c0,nstandalone) ndecodes0=0 ndecodes1=0 - call timer('decoder ',0) - open(13,file='decoded.txt',status='unknown') - ntrMinutes=ntrperiod/60 - newdat=1 + open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown') + + npts65=52*12000 + ntol65=20 + done65=.false. + if(nmode.ge.65 .and. ntxmode.eq.65) then + if(newdat.ne.0) dd(1:npts65)=id2(1:npts65) + call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded) + done65=.true. + endif + + if(nmode.eq.65) go to 800 + nsynced=0 ndecoded=0 nsps=0 - if(ntrMinutes.eq.1) then - nsps=6912 - df3=1500.0/2048.0 - fmt='(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22)' - else if(ntrMinutes.eq.2) then - nsps=15360 - df3=1500.0/2048.0 - fmt='(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22)' - else if(ntrMinutes.eq.5) then - nsps=40960 - df3=1500.0/6144.0 - fmt='(i4.4,i4,i5,f6.1,f8.1,i4,3x,a22)' - else if(ntrMinutes.eq.10) then - nsps=82944 - df3=1500.0/12288.0 - fmt='(i4.4,i4,i5,f6.1,f8.2,i4,3x,a22)' - else if(ntrMinutes.eq.30) then - nsps=252000 - df3=1500.0/32768.0 - fmt='(i4.4,i4,i5,f6.1,f8.2,i4,3x,a22)' - endif - if(nsps.eq.0) stop 'Error: bad TRperiod' !Better: return an error code### + nsps=6912 !Params for JT9-1 + df3=1500.0/2048.0 tstep=0.5*nsps/12000.0 !Half-symbol step (seconds) done=.false. - ia=max(1,nint((nfa-1000)/df3)) - ib=min(NSMAX,nint((nfb-1000)/df3)) + nf0=0 + ia=max(1,nint((nfa-nf0)/df3)) + ib=min(NSMAX,nint((nfb-nf0)/df3)) lag1=-(2.5/tstep + 0.9999) lag2=5.0/tstep + 0.9999 - call timer('sync9 ',0) - call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk) - call timer('sync9 ',1) + if(newdat.ne.0) then + call timer('sync9 ',0) + call sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipk) + call timer('sync9 ',1) + endif nsps8=nsps/8 df8=1500.0/nsps8 @@ -94,24 +84,22 @@ subroutine decoder(ss,c0,nstandalone) ccfok(ia:ib)=.true. nfa1=nfqso-ntol nfb1=nfqso+ntol - ia=max(1,nint((nfa1-1000)/df3)) - ib=min(NSMAX,nint((nfb1-1000)/df3)) + ia=max(1,nint((nfa1-nf0)/df3)) + ib=min(NSMAX,nint((nfb1-nf0)/df3)) ia1=ia ib1=ib else nfa1=nfa nfb1=nfb - ia=max(1,nint((nfa1-1000)/df3)) - ib=min(NSMAX,nint((nfb1-1000)/df3)) + ia=max(1,nint((nfa1-nf0)/df3)) + ib=min(NSMAX,nint((nfb1-nf0)/df3)) do i=ia,ib ccfok(i)=ccfred(i).gt.ccflim .and. red2(i).gt.red2lim enddo ccfok(ia1:ib1)=.false. endif - nRxLog=0 fgood=0. - do i=ia,ib f=(i-1)*df3 if(done(i) .or. (.not.ccfok(i)) .or. (ccfred(i).lt.ccflim-1.0)) cycle @@ -122,9 +110,9 @@ subroutine decoder(ss,c0,nstandalone) if(nqd.eq.1) nfreqs1=nfreqs1+1 call timer('softsym ',0) - fpk=1000.0 + df3*(i-1) - call softsym(c0,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,freq, & - drift,schk,i1SoftSymbols) + fpk=nf0 + df3*(i-1) + call softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt, & + freq,drift,schk,i1SoftSymbols) call timer('softsym ',1) if(schk.ge.schklim) then @@ -140,16 +128,14 @@ subroutine decoder(ss,c0,nstandalone) nsnr=nint(snrdb) ndrift=nint(drift/df3) -! write(38,3002) nutc,nqd,nsnr,i,freq,ndrift,ccfred(i), & -! red2(i),schk,nlim,msg -!3002 format(i4.4,i2,i4,i5,f7.1,i4,f5.1,f6.1,f5.1,i8,1x,a22) - if(msg.ne.' ') then if(nqd.eq.0) ndecodes0=ndecodes0+1 if(nqd.eq.1) ndecodes1=ndecodes1+1 - write(*,fmt) nutc,nsync,nsnr,xdt,freq,ndrift,msg - write(13,fmt) nutc,nsync,nsnr,xdt,freq,ndrift,msg + write(*,1000) nutc,nsnr,xdt,nint(freq),msg +1000 format(i4.4,i4,f5.1,i5,1x,'@',1x,a22) + write(13,1002) nutc,nsync,nsnr,xdt,freq,ndrift,msg +1002 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT9') iaa=max(1,i-1) ibb=min(NSMAX,i+22) @@ -160,8 +146,6 @@ subroutine decoder(ss,c0,nstandalone) done(iaa:ibb)=.true. call flush(6) endif - else -! write(38,3002) nutc,nqd,-99,i,freq,ndrift,ccfred(i),red2(i),schk,0 endif endif enddo @@ -169,21 +153,17 @@ subroutine decoder(ss,c0,nstandalone) if(nagain.ne.0) exit enddo - write(*,1010) nsynced,ndecoded + if(nmode.ge.65 .and. (.not.done65)) then + if(newdat.ne.0) dd(1:npts65)=id2(1:npts65) + call jt65a(dd,npts65,newdat,nutc,nfa,nfqso,ntol65,nagain,ndecoded) + endif + +!### JT65 is not yet producing info for nsynced, ndecoded. +800 write(*,1010) nsynced,ndecoded 1010 format('',2i4) call flush(6) close(13) -! call flush(14) - - call timer('decoder ',1) - if(nstandalone.eq.0) call timer('decoder ',101) - - call system_clock(iclock,iclock_rate,iclock_max) -! write(39,3001) nutc,nfreqs1,nfreqs0,ndecodes1,ndecodes0, & -! float(iclock-iclock0)/iclock_rate -!3001 format(5i8,f10.3) -! call flush(38) -! call flush(39) + close(22) return end subroutine decoder diff --git a/lib/demod64a.f90 b/lib/demod64a.f90 new file mode 100644 index 000000000..9d1a37942 --- /dev/null +++ b/lib/demod64a.f90 @@ -0,0 +1,73 @@ +subroutine demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow) + +! Demodulate the 64-bin spectra for each of 63 symbols in a frame. + +! Parameters +! nadd number of spectra already summed +! mrsym most reliable symbol value +! mr2sym second most likely symbol value +! mrprob probability that mrsym was the transmitted value +! mr2prob probability that mr2sym was the transmitted value + + implicit real*8 (a-h,o-z) + real*4 s3(64,63) + real*8 fs(64) + integer mrsym(63),mrprob(63),mr2sym(63),mr2prob(63) +! common/mrscom/ mrs(63),mrs2(63) + + if(nadd.eq.-999) return + afac=1.1 * float(nadd)**0.64 + scale=255.999 + +! Compute average spectral value + sum=0. + do j=1,63 + do i=1,64 + sum=sum+s3(i,j) + enddo + enddo + ave=sum/(64.*63.) + i1=1 !Silence warning + i2=1 + +! Compute probabilities for most reliable symbol values + do j=1,63 + s1=-1.e30 + fsum=0. + do i=1,64 + x=min(afac*s3(i,j)/ave,50.d0) + fs(i)=exp(x) + fsum=fsum+fs(i) + if(s3(i,j).gt.s1) then + s1=s3(i,j) + i1=i !Most reliable + endif + enddo + + s2=-1.e30 + do i=1,64 + if(i.ne.i1 .and. s3(i,j).gt.s2) then + s2=s3(i,j) + i2=i !Second most reliable + endif + enddo + p1=fs(i1)/fsum !Normalized probabilities + p2=fs(i2)/fsum + mrsym(j)=i1-1 + mr2sym(j)=i2-1 + mrprob(j)=scale*p1 + mr2prob(j)=scale*p2 +! mrs(j)=i1 +! mrs2(j)=i2 + enddo + + sum=0. + nlow=0 + do j=1,63 + sum=sum+mrprob(j) + if(mrprob(j).le.5) nlow=nlow+1 + enddo + ntest=sum/63 + + return +end subroutine demod64a diff --git a/lib/downsam9.f90 b/lib/downsam9.f90 index 413ad2c7b..89932d6ae 100644 --- a/lib/downsam9.f90 +++ b/lib/downsam9.f90 @@ -1,58 +1,60 @@ -subroutine downsam9(c0,npts8,nsps8,newdat,nspsd,fpk,c2,nz2) +subroutine downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2) -!Downsample to nspsd samples per symbol, info centered at fpk +!Downsample from id2() into C2() so as to yield nspsd samples per symbol, +!mixing from fpk down to zero frequency. - parameter (NMAX=128*31500) - complex c0(0:npts8-1) - complex c1(0:NMAX-1) + include 'constants.f90' + parameter (NMAX1=1024*1920) + integer*2 id2(0:8*npts8-1) + real*4 x1(0:NMAX1-1) + complex c1(0:NMAX1/2) complex c2(0:4096-1) - real s(1000) + real s(5000) + equivalence (c1,x1) save - nfft1=128*nsps8 !Forward FFT length - nh1=nfft1/2 - df1=1500.0/nfft1 + nfft1=1024*nsps8 !Forward FFT length + df1=12000.0/nfft1 + npts=8*npts8 if(newdat.eq.1) then - fac=1.e-4 - do i=0,npts8-1,2 - c1(i)=fac*conjg(c0(i)) - c1(i+1)=-fac*conjg(c0(i+1)) + fac=6.963e-6 !Why this weird constant? + do i=0,npts-1 + x1(i)=fac*id2(i) enddo - c1(npts8:)=0. !Zero the rest of c1 - call four2a(c1,nfft1,1,-1,1) !Forward FFT - + x1(npts:nfft1-1)=0. !Zero the rest of x1 + call four2a(c1,nfft1,1,-1,0) !Forward FFT, r2c + nadd=1.0/df1 - j=250/df1 s=0. - do i=1,1000 + do i=1,5000 + j=(i-1)/df1 do n=1,nadd j=j+1 s(i)=s(i)+real(c1(j))**2 + aimag(c1(j))**2 enddo -! write(37,3001) i+1000,s(i),db(s(i)),nadd -!3001 format(i5,2f12.3,i8) enddo - call pctile(s,1000,40,avenoise) endif - ndown=nsps8/16 !Downsample factor + ndown=8*nsps8/nspsd !Downsample factor nfft2=nfft1/ndown !Backward FFT length nh2=nfft2/2 - - fshift=fpk-1500.0 - i0=nh1 + fshift/df1 + nf=nint(fpk) + i0=fpk/df1 + + nw=100 + ia=max(1,nf-nw) + ib=min(5000,nf+nw) + call pctile(s(ia),ib-ia+1,40,avenoise) + fac=sqrt(1.0/avenoise) do i=0,nfft2-1 j=i0+i if(i.gt.nh2) j=j-nfft2 c2(i)=fac*c1(j) enddo - - call four2a(c2,nfft2,1,1,1) !Backward FFT - - nspsd=nsps8/ndown - nz2=npts8/ndown + call four2a(c2,nfft2,1,1,1) !FFT back to time domain + nz2=8*npts8/ndown return end subroutine downsam9 diff --git a/lib/extract.F90 b/lib/extract.F90 new file mode 100644 index 000000000..7a4abf257 --- /dev/null +++ b/lib/extract.F90 @@ -0,0 +1,102 @@ +subroutine extract(s3,nadd,ncount,nhist,decoded,ltext,nbmkv) + + real s3(64,63) + character decoded*22 + integer era(51),dat4(12),indx(64) + integer mrsym(63),mr2sym(63),mrprob(63),mr2prob(63) + logical nokv,ltext + data nokv/.false./,nsec1/0/ + save + + nbmkv=0 + nfail=0 +1 continue + call demod64a(s3,nadd,mrsym,mrprob,mr2sym,mr2prob,ntest,nlow) + if(ntest.lt.50 .or. nlow.gt.20) then + ncount=-999 !Flag bad data + go to 900 + endif + call chkhist(mrsym,nhist,ipk) + + if(nhist.ge.20) then + nfail=nfail+1 + call pctile(s3,4032,50,base) ! ### or, use ave from demod64a + do j=1,63 + s3(ipk,j)=base + enddo + if(nfail.gt.30) then + decoded=' ' + ncount=-1 + go to 900 + endif + go to 1 + endif + + call graycode65(mrsym,63,-1) + call interleave63(mrsym,-1) + call interleave63(mrprob,-1) + +! Decode using Berlekamp-Massey algorithm + nemax=30 !Max BM erasures + call indexx(63,mrprob,indx) + do i=1,nemax + j=indx(i) + if(mrprob(j).gt.120) then + ne2=i-1 + go to 2 + endif + era(i)=j-1 + enddo + ne2=nemax +2 decoded=' ' + do nerase=0,ne2,2 + call rs_decode(mrsym,era,nerase,dat4,ncount) + if(ncount.ge.0) then + call unpackmsg(dat4,decoded) + if(iand(dat4(10),8).ne.0) ltext=.true. + nbmkv=1 + go to 900 + endif + enddo + +! Berlekamp-Massey algorithm failed, try Koetter-Vardy + + if(nokv) go to 900 + + maxe=8 !Max KV errors in 12 most reliable symbols + xlambda=10.0 + call graycode65(mr2sym,63,-1) + call interleave63(mr2sym,-1) + call interleave63(mr2prob,-1) + + nsec1=nsec1+1 + write(22,rec=1) nsec1,xlambda,maxe,200,mrsym,mrprob,mr2sym,mr2prob + call flush(22) + call timer('kvasd ',0) +#ifdef UNIX + iret=system('./kvasd -q > dev_null') +#else + iret=system('kvasd -q > dev_null') +#endif + call timer('kvasd ',1) + if(iret.ne.0) then + if(.not.nokv) write(*,1000) +1000 format('Error in KV decoder, or no KV decoder present.') + nokv=.true. + go to 900 + endif + + read(22,rec=2,err=900) nsec2,ncount,dat4 + j=nsec2 !Silence compiler warning + decoded=' ' + ltext=.false. + if(ncount.ge.0) then + call unpackmsg(dat4,decoded) !Unpack the user message + if(iand(dat4(10),8).ne.0) ltext=.true. + nbmkv=2 + endif + +900 continue + + return +end subroutine extract diff --git a/lib/fchisq65.f90 b/lib/fchisq65.f90 new file mode 100644 index 000000000..b91444e5b --- /dev/null +++ b/lib/fchisq65.f90 @@ -0,0 +1,68 @@ +real function fchisq65(cx,npts,fsample,nflip,a,ccfmax,dtmax) + + parameter (NMAX=60*12000) !Samples per 60 s + complex cx(npts) + real a(5) + complex w,wstep,z + real ss(3000) + complex csx(0:NMAX/8) + data twopi/6.283185307/a1,a2,a3/99.,99.,99./ + save + + call timer('fchisq65',0) + baud=11025.0/4096.0 + nsps=nint(fsample/baud) !Samples per symbol + nsph=nsps/2 !Samples per half-symbol + ndiv=16 !Output ss() steps per symbol + nout=ndiv*npts/nsps + dtstep=1.0/(ndiv*baud) !Time per output step + + if(a(1).ne.a1 .or. a(2).ne.a2 .or. a(3).ne.a3) then + a1=a(1) + a2=a(2) + a3=a(3) + +! Mix and integrate the complex signal + csx(0)=0. + w=1.0 + x0=0.5*(npts+1) + s=2.0/npts + do i=1,npts + x=s*(i-x0) + if(mod(i,100).eq.1) then + p2=1.5*x*x - 0.5 + dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample) + wstep=cmplx(cos(dphi),sin(dphi)) + endif + w=w*wstep + csx(i)=csx(i-1) + w*cx(i) + enddo + endif + +! Compute 1/2-symbol powers at 1/16-symbol steps. + fac=1.e-4 + + do i=1,nout + j=i*nsps/ndiv + k=j-nsph + ss(i)=0. + if(k.ge.1) then + z=csx(j)-csx(k) + ss(i)=fac*(real(z)**2 + aimag(z)**2) + endif + enddo + + ccfmax=0. + call timer('ccf2 ',0) + call ccf2(ss,nout,nflip,ccf,lagpk) + call timer('ccf2 ',1) + if(ccf.gt.ccfmax) then + ccfmax=ccf + dtmax=lagpk*dtstep + endif + fchisq65=-ccfmax + + call timer('fchisq65',1) + + return +end function fchisq65 diff --git a/lib/fil6521.f90 b/lib/fil6521.f90 new file mode 100644 index 000000000..6e78e63ab --- /dev/null +++ b/lib/fil6521.f90 @@ -0,0 +1,44 @@ +subroutine fil6521(c1,n1,c2,n2) + +! FIR lowpass filter designed using ScopeFIR + +! Pass #1 Pass #2 +! ----------------------------------------------- +! fsample (Hz) 1378.125 Input sample rate +! Ntaps 21 Number of filter taps +! fc (Hz) 40 Cutoff frequency +! fstop (Hz) 172.266 Lower limit of stopband +! Ripple (dB) 0.1 Ripple in passband +! Stop Atten (dB) 38 Stopband attenuation +! fout (Hz) 344.531 Output sample rate + + parameter (NTAPS=21) + parameter (NH=NTAPS/2) + parameter (NDOWN=4) !Downsample ratio = 1/4 + complex c1(n1) + complex c2(n1/NDOWN) + +! Filter coefficients: + real a(-NH:NH) + data a/ & + -0.011958606980,-0.013888627387,-0.015601306443,-0.010602249570, & + 0.003804023436, 0.028320058273, 0.060903935217, 0.096841904411, & + 0.129639871228, 0.152644580853, 0.160917511283, 0.152644580853, & + 0.129639871228, 0.096841904411, 0.060903935217, 0.028320058273, & + 0.003804023436,-0.010602249570,-0.015601306443,-0.013888627387, & + -0.011958606980/ + + n2=(n1-NTAPS+NDOWN)/NDOWN + k0=NH-NDOWN+1 + +! Loop over all output samples + do i=1,n2 + c2(i)=0. + k=k0 + NDOWN*i + do j=-NH,NH + c2(i)=c2(i) + c1(j+k)*a(j) + enddo + enddo + + return +end subroutine fil6521 diff --git a/lib/filbig.f90 b/lib/filbig.f90 new file mode 100644 index 000000000..cb59b2f12 --- /dev/null +++ b/lib/filbig.f90 @@ -0,0 +1,127 @@ +subroutine filbig(dd,npts,f0,newdat,c4a,n4,sq0) + +! Filter and downsample the real data in array dd(npts), sampled at 12000 Hz. +! Output is complex, sampled at 1378.125 Hz. + + parameter (NSZ=3413) + parameter (NFFT1=672000,NFFT2=77175) + parameter (NZ2=1000) + real*4 dd(npts) !Input data + complex ca(NFFT1) !FFT of input + complex c4a(NFFT2) !Output data + real*4 s(NZ2) + real*8 df + real halfpulse(8) !Impulse response of filter (one sided) + complex cfilt(NFFT2) !Filter (complex; imag = 0) + real rfilt(NFFT2) !Filter (real) + integer*8 plan1,plan2,plan3 + logical first + include 'fftw3.f90' + equivalence (rfilt,cfilt) + data first/.true./,npatience/0/ + data halfpulse/114.97547150,36.57879257,-20.93789101, & + 5.89886379,1.59355187,-2.49138308,0.60910773,-0.04248129/ + common/refspec/dfref,ref(NSZ) + save + + if(npts.lt.0) go to 900 !Clean up at end of program + + if(first) then + nflags=FFTW_ESTIMATE + if(npatience.eq.1) nflags=FFTW_ESTIMATE_PATIENT + if(npatience.eq.2) nflags=FFTW_MEASURE + if(npatience.eq.3) nflags=FFTW_PATIENT + if(npatience.eq.4) nflags=FFTW_EXHAUSTIVE +! Plan the FFTs just once + call timer('FFTplans ',0) + call sfftw_plan_dft_1d(plan1,nfft1,ca,ca,FFTW_BACKWARD,nflags) + call sfftw_plan_dft_1d(plan2,nfft2,c4a,c4a,FFTW_FORWARD,nflags) + call sfftw_plan_dft_1d(plan3,nfft2,cfilt,cfilt,FFTW_BACKWARD,nflags) + call timer('FFTplans ',1) + +! Convert impulse response to filter function + do i=1,nfft2 + cfilt(i)=0. + enddo + fac=0.00625/nfft1 + cfilt(1)=fac*halfpulse(1) + do i=2,8 + cfilt(i)=fac*halfpulse(i) + cfilt(nfft2+2-i)=fac*halfpulse(i) + enddo + call timer('FFTfilt ',0) + call sfftw_execute(plan3) + call timer('FFTfilt ',1) + + base=cfilt(nfft2/2+1) + do i=1,nfft2 + rfilt(i)=real(cfilt(i))-base + enddo + + df=12000.d0/nfft1 + first=.false. + endif + +! When new data comes along, we need to compute a new "big FFT" +! If we just have a new f0, continue with the existing data in ca. + + if(newdat.ne.0) then + nz=min(npts,nfft1) + ca(1:nz)=dd(1:nz) + ca(nz+1:)=0. !### Should change this to r2c FFT ### + call timer('FFTbig ',0) + call sfftw_execute(plan1) + call timer('FFTbig ',1) + + do i=1,NFFT1/2 !Flatten the spectrum + j=nint(i*df/dfref) + if(j.lt.1) j=1 + if(j.gt.NSZ) j=NSZ + fac=sqrt(min(30.0,1.0/ref(j))) + ca(i)=fac * ca(i) + enddo + endif + +! NB: f0 is the frequency at which we want our filter centered. +! i0 is the bin number in ca closest to f0. + + i0=nint(f0/df) + 1 + nh=nfft2/2 + do i=1,nh !Copy data into c4a and apply + j=i0+i-1 !the filter function + if(j.ge.1 .and. j.le.nfft1) then + c4a(i)=rfilt(i)*ca(j) + else + c4a(i)=0. + endif + enddo + do i=nh+1,nfft2 + j=i0+i-1-nfft2 + if(j.lt.1) j=j+nfft1 !nfft1 was nfft2 + c4a(i)=rfilt(i)*ca(j) + enddo + + nadd=nfft2/NZ2 + i=0 + do j=1,NZ2 + s(j)=0. + do n=1,nadd + i=i+1 + s(j)=s(j) + real(c4a(i))**2 + aimag(c4a(i))**2 + enddo + enddo + call pctile(s,NZ2,30,sq0) + +! Do the short reverse transform, to go back to time domain. + call timer('FFTsmall',0) + call sfftw_execute(plan2) + call timer('FFTsmall',1) + n4=min(npts/8,nfft2) + return + +900 call sfftw_destroy_plan(plan1) + call sfftw_destroy_plan(plan2) + call sfftw_destroy_plan(plan3) + + return +end subroutine filbig diff --git a/lib/fillcom.f90 b/lib/fillcom.f90 index 16e45b0fc..fd5804887 100644 --- a/lib/fillcom.f90 +++ b/lib/fillcom.f90 @@ -1,24 +1,24 @@ subroutine fillcom(nutc0,ndepth0) character*20 datetime common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, & - kin,nzhsym,nsave,nagain,ndepth,nrxlog,nfsample,datetime + kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime save nutc=nutc0 ndiskdat=1 ntrperiod=60 - nfqso=1500 + nfqso=1197 newdat=1 npts8=74736 - nfa=1000 - nfb=2000 + nfa=2700 + nfb=4007 ntol=3 kin=1024 nzhsym=173 nsave=0 ndepth=ndepth0 - nrxlog=1 - nfsample=12000 + ntxmode=9 + nmode=9+65 datetime="2013-Apr-16 15:13" return diff --git a/lib/flat2.f90 b/lib/flat2.f90 new file mode 100644 index 000000000..cebd989f7 --- /dev/null +++ b/lib/flat2.f90 @@ -0,0 +1,18 @@ +subroutine flat2(s,nz,ref) + + parameter (NSMAX=6827) + real s(NSMAX) + real ref(NSMAX) + + nsmo=10 + ia=nsmo+1 + ib=nz-nsmo-1 + do i=ia,ib + call pctile(s(i-nsmo),2*nsmo+1,5,ref(i)) + enddo + + ref(:ia-1)=ref(ia) + ref(ib+1:)=ref(ib) + + return +end subroutine flat2 diff --git a/lib/flat65.f90 b/lib/flat65.f90 new file mode 100644 index 000000000..7aa106c4f --- /dev/null +++ b/lib/flat65.f90 @@ -0,0 +1,25 @@ +subroutine flat65(ss,nhsym,maxhsym,nsz,ref) + + real stmp(nsz) + real ss(maxhsym,nsz) + real ref(nsz) + + npct=28 !Somewhat arbitrary + do i=1,nsz + call pctile(ss(1,i),nhsym,npct,stmp(i)) + enddo + + nsmo=33 + ia=nsmo/2 + 1 + ib=nsz - nsmo/2 - 1 + do i=ia,ib + call pctile(stmp(i-nsmo/2),nsmo,npct,ref(i)) + enddo + ref(:ia-1)=ref(ia) + ref(ib+1:)=ref(ib) + ref=4.0*ref + + return +end subroutine flat65 + + diff --git a/lib/gen65.f90 b/lib/gen65.f90 new file mode 100644 index 000000000..85802384b --- /dev/null +++ b/lib/gen65.f90 @@ -0,0 +1,65 @@ +subroutine gen65(msg0,ichk,msgsent,itone,itext) + +! Encodes a JT65 message to yieild itone(1:126) +! Temporarily, does not implement EME shorthands + + character*22 msg0 + character*22 message !Message to be generated + character*22 msgsent !Message as it will be received + integer itone(126) +! character*3 cok !' ' or 'OOO' + integer dgen(13) + integer sent(63) + logical text + integer nprc(126) + data nprc/1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, & + 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, & + 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, & + 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, & + 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, & + 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, & + 1,1,1,1,1,1/ + save + + message=msg0 + do i=1,22 + if(ichar(message(i:i)).eq.0) then + message(i:)=' ' + exit + endif + enddo + + do i=1,22 !Strip leading blanks + if(message(1:1).ne.' ') exit + message=message(i+1:) + enddo + + nspecial=0 +! call chkmsg(message,cok,nspecial,flip) + if(nspecial.eq.0) then + call packmsg(message,dgen,text) !Pack message into 72 bits + itext=0 + if(text) itext=1 + call unpackmsg(dgen,msgsent) !Unpack to get message sent + if(ichk.ne.0) go to 999 !Return if checking only + + call rs_encode(dgen,sent) !Apply Reed-Solomon code + call interleave63(sent,1) !Apply interleaving + call graycode65(sent,63,1) !Apply Gray code + nsym=126 !Symbols per transmission + else + nsym=32 + endif + + k=0 + do j=1,nsym + if(nprc(j).eq.0) then + k=k+1 + itone(j)=sent(k)+2 + else + itone(j)=0 + endif + enddo + +999 return +end subroutine gen65 diff --git a/lib/genjt9.f90 b/lib/genjt9.f90 index 25be708d0..90427e1ce 100644 --- a/lib/genjt9.f90 +++ b/lib/genjt9.f90 @@ -26,7 +26,7 @@ subroutine genjt9(msg0,ichk,msgsent,i4tone,itext) endif enddo - do i=1,22 !Omit leading blanks + do i=1,22 !Strip leading blanks if(message(1:1).ne.' ') exit message=message(i+1:) enddo diff --git a/lib/graycode65.f90 b/lib/graycode65.f90 new file mode 100644 index 000000000..3ee9a42f6 --- /dev/null +++ b/lib/graycode65.f90 @@ -0,0 +1,9 @@ +subroutine graycode65(dat,n,idir) + + integer dat(n) + do i=1,n + dat(i)=igray(dat(i),idir) + enddo + + return +end subroutine graycode65 diff --git a/lib/init_rs.c b/lib/init_rs.c index 7e1e09e5b..eb2711949 100644 --- a/lib/init_rs.c +++ b/lib/init_rs.c @@ -13,7 +13,7 @@ #include "char.h" #endif -#define NULL ((void *)0) +//#define NULL ((void *)0) void FREE_RS(void *p){ struct rs *rs = (struct rs *)p; diff --git a/lib/interleave63.f90 b/lib/interleave63.f90 new file mode 100644 index 000000000..048244e63 --- /dev/null +++ b/lib/interleave63.f90 @@ -0,0 +1,25 @@ +subroutine interleave63(d1,idir) + +! Interleave (idir=1) or de-interleave (idir=-1) the array d1. + + integer d1(0:6,0:8) + integer d2(0:8,0:6) + + if(idir.ge.0) then + do i=0,6 + do j=0,8 + d2(j,i)=d1(i,j) + enddo + enddo + call move(d2,d1,63) + else + call move(d1,d2,63) + do i=0,6 + do j=0,8 + d1(i,j)=d2(j,i) + enddo + enddo + endif + + return +end subroutine interleave63 diff --git a/lib/jt65.f90 b/lib/jt65.f90 new file mode 100644 index 000000000..23777155b --- /dev/null +++ b/lib/jt65.f90 @@ -0,0 +1,68 @@ +program jt65 + +! Test the JT65 decoder for WSJT-X + + parameter (NZMAX=60*12000) + integer*4 ihdr(11) + integer*2 id2(NZMAX) + real*4 dd(NZMAX) + character*80 infile + integer*2 nfmt2,nchan2,nbitsam2,nbytesam2 + character*4 ariff,awave,afmt,adata + common/hdr/ariff,lenfile,awave,afmt,lenfmt,nfmt2,nchan2, & + nsamrate,nbytesec,nbytesam2,nbitsam2,adata,ndata + common/tracer/limtrace,lu + equivalence (ariff,ihdr) + + nargs=iargc() + if(nargs.lt.1) then + print*,'Usage: jt65 file1 [file2 ...]' + go to 999 + endif + limtrace=0 + lu=12 + + newdat=1 + ntol=50 + nfa=2700 +! nfb=4000 + nfqso=933 + nagain=0 + + open(12,file='timer.out',status='unknown') + open(22,file='kvasd.dat',access='direct',recl=1024,status='unknown') + + call timer('jt65 ',0) + + do ifile=1,nargs + call getarg(ifile,infile) + open(10,file=infile,access='stream',status='old',err=998) + + call timer('read ',0) + read(10) ihdr + nutc=ihdr(1) !Silence compiler warning + i1=index(infile,'.wav') + read(infile(i1-4:i1-1),*,err=10) nutc + go to 20 +10 nutc=0 +20 npts=52*12000 + read(10) id2(1:npts) + call timer('read ',1) + dd(1:npts)=id2(1:npts) + dd(npts+1:)=0. + + call timer('jt65a ',0) + call jt65a(dd,npts,newdat,nutc,ntol,nfa,nfqso,nagain,ndecoded) + call timer('jt65a ',1) + enddo + + call timer('jt65 ',1) + call timer('jt65 ',101) + call four2a(a,-1,1,1,1) !Free the memory used for plans + call filbig(a,-1,1,0.0,0,0,0,0,0) ! (ditto) + go to 999 + +998 print*,'Cannot open file:' + print*,infile + +999 end program jt65 diff --git a/lib/jt65a.f90 b/lib/jt65a.f90 new file mode 100644 index 000000000..4dba69241 --- /dev/null +++ b/lib/jt65a.f90 @@ -0,0 +1,91 @@ +subroutine jt65a(dd,npts,newdat,nutc,nfa,nfqso,ntol,nagain,ndecoded) + +! Process dd() data to find and decode JT65 signals. + + parameter (NSZ=3413) + parameter (NZMAX=60*12000) + parameter (NFFT=8192) + real dd(NZMAX) + real*4 ss(322,NSZ) + real*4 savg(NSZ) + logical done(NSZ) + real a(5) + character decoded*22 + save + + if(newdat.ne.0) then + call timer('symsp65 ',0) + call symspec65(dd,npts,ss,nhsym,savg) !Get normalized symbol spectra + call timer('symsp65 ',1) + endif + + df=12000.0/NFFT !df = 12000.0/16384 = 0.732 Hz + ftol=15.0 !Frequency tolerance (Hz) + mode65=1 !Decoding JT65A only, for now. + done=.false. + + do nqd=1,0,-1 + if(nqd.eq.1) then !Quick decode, at fQSO + fa=nfqso - ntol + fb=nfqso + ntol + else !Wideband decode at all freqs + fa=200 + fb=nfa + endif + ia=max(51,nint(fa/df)) + ib=min(NSZ-51,nint(fb/df)) + + freq0=-999. + thresh0=1.5 + + do i=ia,ib !Search over freq range + if(savg(i).lt.thresh0 .or. done(i)) cycle + freq=i*df + + call timer('ccf65 ',0) + call ccf65(ss(1,i),nhsym,savg(i),sync1,dt,flipk,syncshort,snr2,dt2) + call timer('ccf65 ',1) + +! ########################### Search for Shorthand Messages ################# +! include 'shorthand1.f90' + +! ########################### Search for Normal Messages ########### + thresh1=1.0 +! Use lower thresh1 at fQSO + if(nqd.eq.1 .and. ntol.le.100) thresh1=0. + +! Is sync1 above threshold? + if(sync1.lt.thresh1) cycle + +! Keep only the best candidate within ftol. + if(freq-freq0.lt.ftol) cycle + + nflip=nint(flipk) + call timer('decod65a',0) + call decode65a(dd,npts,newdat,freq,nflip,mode65,sync2,a,dt, & + nbmkv,nhist,decoded) + call timer('decod65a',1) + + if(decoded.ne.' ') then + ndecoded=1 + nfreq=nint(freq+a(1)) + ndrift=nint(2.0*a(2)) + s2db=10.0*log10(sync2) - 32 !### empirical (was 40) ### + nsnr=nint(s2db) + if(nsnr.lt.-30) nsnr=-30 + if(nsnr.gt.-1) nsnr=-1 + write(*,1010) nutc,nsnr,dt,nfreq,decoded +1010 format(i4.4,i4,f5.1,i5,1x,'#',1x,a22) + write(13,1012) nutc,nint(sync1),nsnr,dt,float(nfreq),ndrift, & + decoded,nbmkv +1012 format(i4.4,i4,i5,f6.1,f8.0,i4,3x,a22,' JT65',i4) + freq0=freq + i2=min(NSZ,i+15) !### ??? ### + done(i:i2)=.true. + endif + enddo + if(nagain.eq.1) exit + enddo + + return +end subroutine jt65a diff --git a/lib/jt9.f90 b/lib/jt9.f90 index 1f01a11e5..3e273e4e5 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -3,18 +3,12 @@ program jt9 ! Decoder for JT9. Can run stand-alone, reading data from *.wav files; ! or as the back end of wsjt-x, with data placed in a shared memory region. - parameter (NTMAX=120) - parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes - parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate - parameter (NSMAX=1365) !Max length of saved spectra + include 'constants.f90' integer*4 ihdr(11) real*4 s(NSMAX) - real*4 ccfred(NSMAX) - logical*1 lstrong(0:1023) integer*2 id2 - complex c0 character*80 arg,infile - common/jt9com/ss(184,NSMAX),savg(NSMAX),c0(NDMAX),id2(NMAX),nutc,ndiskdat, & + common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, & ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded common/tracer/limtrace,lu @@ -39,11 +33,6 @@ program jt9 limtrace=0 lu=12 - nfa=1000 - nfb=2000 - mousefqso=1500 - newdat=1 - ndiskdat=1 do ifile=ifile1,nargs call getarg(ifile,infile) @@ -82,10 +71,6 @@ program jt9 call timer('jt9 ',0) endif -! do i=1,npts -! id2(i)=100.0*sin(6.283185307*1600.0*i/12000.0) -! enddo - id2=0 !??? Why is this necessary ??? do iblk=1,npts/kstep @@ -99,8 +84,7 @@ program jt9 ! Emit signal readyForFFT ingain=0 call timer('symspec ',0) - call symspec(k,ntrperiod,nsps,ingain,pxdb,s,ccfred,df3, & - ihsym,nzap,slimit,lstrong,npts8) + call symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8) call timer('symspec ',1) nhsym0=nhsym if(ihsym.ge.173) go to 10 @@ -109,7 +93,7 @@ program jt9 10 close(10) call fillcom(nutc0,ndepth) - call decoder(ss,c0,1) + call decoder(ss,id2) enddo call timer('jt9 ',1) diff --git a/lib/jt9a.f90 b/lib/jt9a.f90 index 94f24fdcc..052073208 100644 --- a/lib/jt9a.f90 +++ b/lib/jt9a.f90 @@ -20,6 +20,7 @@ subroutine jt9a open(12,file='timer.out',status='unknown') limtrace=0 +! limtrace=-1 !Disable all calls to timer() lu=12 i1=attach_jt9() @@ -44,12 +45,16 @@ subroutine jt9a go to 999 endif p_jt9=>address_jt9() + call timer('jt9b ',0) call jt9b(p_jt9,nbytes) + call timer('jt9b ',1) 100 inquire(file=trim(cwd)//'/.lock',exist=fileExists) if(fileExists) go to 10 call sleep_msec(100) go to 100 -999 return +999 call timer('jt9b ',101) + + return end subroutine jt9a diff --git a/lib/jt9b.f90 b/lib/jt9b.f90 index f446f765c..63de536b6 100644 --- a/lib/jt9b.f90 +++ b/lib/jt9b.f90 @@ -1,14 +1,12 @@ subroutine jt9b(jt9com,nbytes) - parameter (NTMAX=120) - parameter (NSMAX=1365) + include 'constants.f90' integer*1 jt9com(0:nbytes-1) kss=0 ksavg=kss + 4*184*NSMAX - kc0=ksavg + 4*NSMAX - kid2=kc0 + 2*4*NTMAX*1500 + kid2=ksavg + 4*NSMAX knutc=kid2 + 2*NTMAX*12000 - call jt9c(jt9com(kss),jt9com(ksavg),jt9com(kc0),jt9com(kid2),jt9com(knutc)) + call jt9c(jt9com(kss),jt9com(ksavg),jt9com(kid2),jt9com(knutc)) return end subroutine jt9b diff --git a/lib/jt9c.f90 b/lib/jt9c.f90 index ada658be3..57b3cb25a 100644 --- a/lib/jt9c.f90 +++ b/lib/jt9c.f90 @@ -1,21 +1,21 @@ -subroutine jt9c(ss,savg,c0,id2,nparams0) +subroutine jt9c(ss,savg,id2,nparams0) - parameter (NSMAX=22000) + include 'constants.f90' real*4 ss(184*NSMAX),savg(NSMAX) - complex c0(1800*1500) - integer*2 id2(1800*12000) + integer*2 id2(NTMAX*12000) integer nparams0(21),nparams(21) character*20 datetime common/npar/nutc,ndiskdat,ntrperiod,nfqso,newdat,npts8,nfa,nfb,ntol, & - kin,nzhsym,nsave,nagain,ndepth,nrxlog,nfsample,datetime + kin,nzhsym,nsave,nagain,ndepth,ntxmode,nmode,datetime equivalence (nparams,nutc) nutc=id2(1)+int(savg(1)) !Silence compiler warning nparams=nparams0 !Copy parameters into common/npar/ call flush(6) - if(sum(nparams).ne.0) call decoder(ss,c0,0) +! if(sum(nparams).ne.0) call decoder(ss,id2) + call decoder(ss,id2) return end subroutine jt9c diff --git a/lib/jt9test.f90 b/lib/jt9test.f90 deleted file mode 100644 index 3651593b2..000000000 --- a/lib/jt9test.f90 +++ /dev/null @@ -1,183 +0,0 @@ -program jt9test - -! Decoder for JT9. Can run stand-alone, reading data from *.wav files; -! or as the back end of wsjt-x, with data placed in a shared memory region. - -! NB: For unknown reason, ***MUST*** be compiled by g95 with -O0 !!! - - parameter (NTMAX=120) - parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes - parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate - parameter (NSMAX=1365) !Max length of saved spectra - integer*4 ihdr(11) - real*4 s(NSMAX) - real*4 ccfred(NSMAX) - logical*1 lstrong(0:1023) - integer*1 i1SoftSymbols(207) - character*22 msg - character*33 line - character*80 arg,infile - integer*2 id2 - complex c0 - complex c1(0:2700000) - common/jt9com/ss(184,NSMAX),savg(NSMAX),c0(NDMAX),id2(NMAX),nutc,ndiskdat, & - ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded - common/tracer/limtrace,lu - - nargs=iargc() - if(nargs.lt.1) then - print*,'Usage: jt9 TRperiod file1 [file2 ...]' - print*,' Reads data from *.wav files.' - print*,'' - print*,' jt9 -s' - print*,' Gets data from shared memory region.' - go to 999 - endif - call getarg(1,arg) - if(arg(1:2).eq.'-s') then -! call jt9a -! call ftnquit - go to 999 - endif - read(arg,*) ntrperiod - - ifile1=2 - - limtrace=0 - lu=12 - nfa=1000 - nfb=2000 - ntol=500 - nfqso=1500 - newdat=1 - nb=0 - nbslider=100 - limit=20000 - ndiskdat=1 - - do ifile=ifile1,nargs - call getarg(ifile,infile) - open(10,file=infile,access='stream',status='old',err=998) - read(10) ihdr - i1=index(infile,'.wav') - read(infile(i1-4:i1-1),*,err=1) nutc0 - go to 2 -1 nutc0=0 -2 nsps=0 - if(ntrperiod.eq.1) then - nsps=6912 - nzhsym=181 - else if(ntrperiod.eq.2) then - nsps=15360 - nzhsym=178 - else if(ntrperiod.eq.5) then - nsps=40960 - nzhsym=172 - else if(ntrperiod.eq.10) then - nsps=82944 - nzhsym=171 - else if(ntrperiod.eq.30) then - nsps=252000 - nzhsym=167 - endif - if(nsps.eq.0) stop 'Error: bad TRperiod' - - kstep=nsps/2 - tstep=kstep/12000.0 - k=0 - nhsym0=-999 - npts=(60*ntrperiod-6)*12000 - if(ifile.eq.ifile1) then - open(12,file='timer.out',status='unknown') - call timer('jt9 ',0) - endif - -! do i=1,npts -! id2(i)=100.0*sin(6.283185307*1600.0*i/12000.0) -! enddo - - do iblk=1,npts/kstep - k=iblk*kstep - call timer('read_wav',0) - read(10,end=10) id2(k-kstep+1:k) - call timer('read_wav',1) - - nhsym=(k-2048)/kstep - if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then -! Emit signal readyForFFT - ingain=0 - call timer('symspec ',0) - call symspec(k,ntrperiod,nsps,ingain,nb,nbslider,pxdb, & - s,ccfred,df3,ihsym,nzap,slimit,lstrong,npts8) - call timer('symspec ',1) - nhsym0=nhsym - if(ihsym.ge.184) go to 10 - endif - enddo -10 close(10) - - nsps8=nsps/8 - iz=1000.0/df3 - nutc=nutc0 - - call timer('sync9 ',0) - call sync9(ss,nzhsym,tstep,df3,ccfred,ia,ib,ipk) !Get sync, freq - call timer('sync9 ',1) - - fgood=0. - df8=1500.0/(nsps/8) - sbest=0. - do i=ia,ib - f=(i-1)*df3 - if((i.eq.ipk .or. ccfred(i).ge.3.0) .and. f.gt.fgood+10.0*df8) then - - call timer('test9 ',0) - fpk=1000.0 + df3*(i-1) - c1(0:npts8-1)=conjg(c0(1:npts8)) - call test9(c1,npts8,nsps8,fpk,syncpk,snrdb,xdt,freq,drift, & - i1SoftSymbols) - call timer('test9 ',1) - - call timer('decode9 ',0) - call decode9(i1SoftSymbols,limit,nlim,msg) - call timer('decode9 ',1) - snr=snrdb - sync=syncpk - 2.0 - if(sync.lt.0.0) sync=0.0 - nsync=sync - if(nsync.gt.10) nsync=10 - nsnr=nint(snr) - width=0.0 - - if(sync.gt.sbest .and. fgood.eq.0.0) then - sbest=sync - write(line,1010) nutc,nsync,nsnr,xdt,1000.0+fpk,width - if(nsync.gt.0) nsynced=1 - endif - - if(msg.ne.' ') then - write(*,1010) nutc,nsync,nsnr,xdt,freq,drift,msg -1010 format(i4.4,i4,i5,f6.1,f8.2,f6.2,3x,a22) - fgood=f - nsynced=1 - ndecoded=1 - endif - endif - enddo - - if(fgood.eq.0.0) then - write(*,1020) line -1020 format(a33) - endif - - enddo - - call timer('jt9 ',1) - call timer('jt9 ',101) -! call ftnquit - go to 999 - -998 print*,'Cannot open file:' - print*,infile - -999 end program jt9test diff --git a/lib/move.f90 b/lib/move.f90 new file mode 100644 index 000000000..13783dc76 --- /dev/null +++ b/lib/move.f90 @@ -0,0 +1,7 @@ +subroutine move(x,y,n) + real x(n),y(n) + do i=1,n + y(i)=x(i) + enddo + return +end subroutine move diff --git a/lib/peakdf9.f90 b/lib/peakdf9.f90 deleted file mode 100644 index 5db762ca0..000000000 --- a/lib/peakdf9.f90 +++ /dev/null @@ -1,32 +0,0 @@ -subroutine peakdf9(c0,npts8,nsps8,istart,foffset,idfpk) - - complex c0(0:npts8-1) - complex zsum - include 'jt9sync.f90' - - twopi=8.0*atan(1.0) - df=1500.0/nsps8 - smax=0. - do idf=-5,5 - f0=foffset + 0.1*df*idf - dphi=twopi*f0/1500.0 - sum=0. - do j=1,16 - i1=(ii(j)-1)*nsps8 + istart - phi=0. - zsum=0. - do i=i1,i1+nsps8-1 - if(i.lt.0 .or. i.gt.npts8-1) cycle - phi=phi + dphi - zsum=zsum + c0(i) * cmplx(cos(phi),-sin(phi)) - enddo - sum=sum + real(zsum)**2 + aimag(zsum)**2 - enddo - if(sum.gt.smax) then - idfpk=idf - smax=sum - endif - enddo - - return -end subroutine peakdf9 diff --git a/lib/peakdt9.f90 b/lib/peakdt9.f90 index 675b312dd..eac256efd 100644 --- a/lib/peakdt9.f90 +++ b/lib/peakdt9.f90 @@ -9,11 +9,8 @@ subroutine peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt) p=0. i0=5*nspsd do i=0,nz2-1 - z=1.e-3*sum(c2(max(i-(nspsd-1),0):i)) !Integrate - p(i0+i)=real(z)**2 + aimag(z)**2 !Symbol power at freq=0 -! Option here for coherent processing ? -! write(53,3301) i,z,p(i0+i),atan2(aimag(z),real(z)) -!3301 format(i6,4e12.3) + z=1.e-3*sum(c2(max(i-(nspsd-1),0):i)) + p(i0+i)=real(z)**2 + aimag(z)**2 !Integrated symbol power at freq=0 enddo call getlags(nsps8,lag0,lag1,lag2) @@ -35,8 +32,6 @@ subroutine peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt) enddo ss=(sum1/16.0)/(sum0/69.0) - 1.0 xdt=(lag-lag0)*dtlag -! write(52,3001) lag,xdt,ss -!3001 format(i5,2f12.3) if(ss.gt.smax) then smax=ss lagpk=lag diff --git a/lib/ptt_unix.c b/lib/ptt_unix.c index cce8e592f..532921368 100644 --- a/lib/ptt_unix.c +++ b/lib/ptt_unix.c @@ -68,7 +68,7 @@ int lp_ptt (int fd, int onoff); /* parport functions */ int dev_is_parport(int fd); -int ptt_parallel(int fd, int *ntx, int *iptt); +int ptt_parallel(int fd, int ntx, int *iptt); int ptt_serial(int fd, int *ntx, int *iptt); int fd=-1; /* Used for both serial and parallel */ @@ -91,53 +91,42 @@ int fd=-1; /* Used for both serial and parallel */ #define STATE_PORT_OPEN_PARALLEL 1 #define STATE_PORT_OPEN_SERIAL 2 -//int ptt_(int *unused, char *ptt_port, int *ntx, int *iptt) -int ptt_(int *unused, int *ntx, int *iptt) +//int ptt_(int *unused, int *ntx, int *iptt) +int ptt_(int nport, int ntx, int *iptt, int *nopen) { static int state=0; char *p; + char ptt_port[]="/dev/ttyUSB0"; + fflush(stdout); -// ### Temporary: - char* ptt_port; - if(*unused != -99) { - *iptt=*ntx; - return 0; - } -// ### - - /* In the very unlikely event of a NULL pointer, just return. - * Yes, I realise this should not be possible in WSJT. - */ + // In the very unlikely event of a NULL pointer, just return. if (ptt_port == NULL) { - *iptt = *ntx; + *iptt = ntx; return (0); } - switch (state) { case STATE_PORT_CLOSED: - - /* Remove trailing ' ' */ + + // Remove trailing ' ' if ((p = strchr(ptt_port, ' ')) != NULL) *p = '\0'; - /* If all that is left is a '\0' then also just return */ + // If all that is left is a '\0' then also just return if (*ptt_port == '\0') { - *iptt = *ntx; + *iptt = ntx; return(0); } - if ((fd = open(ptt_port, O_RDWR|O_NONBLOCK)) < 0) { fprintf(stderr, "Can't open %s.\n", ptt_port); return (1); } - if (dev_is_parport(fd)) { state = STATE_PORT_OPEN_PARALLEL; lp_reset(fd); ptt_parallel(fd, ntx, iptt); } else { state = STATE_PORT_OPEN_SERIAL; - ptt_serial(fd, ntx, iptt); + ptt_serial(fd, &ntx, iptt); } break; @@ -146,7 +135,7 @@ int ptt_(int *unused, int *ntx, int *iptt) break; case STATE_PORT_OPEN_SERIAL: - ptt_serial(fd, ntx, iptt); + ptt_serial(fd, &ntx, iptt); break; default: @@ -155,9 +144,11 @@ int ptt_(int *unused, int *ntx, int *iptt) state = STATE_PORT_CLOSED; break; } + *iptt=ntx; return(0); } + /* * ptt_serial * @@ -180,6 +171,8 @@ ptt_serial(int fd, int *ntx, int *iptt) ioctl(fd, TIOCMBIC, &control); *iptt = 0; } + printf("ptt_serial: %d %d",*ntx,*iptt); + fflush(stdout); return(0); } @@ -379,10 +372,9 @@ lp_ptt (int fd, int onoff) * iptt - pointer to fortran command status on or off */ -int -ptt_parallel(int fd, int *ntx, int *iptt) +int ptt_parallel(int fd, int ntx, int *iptt) { - if(*ntx) { + if(ntx) { lp_ptt(fd, 1); *iptt=1; } else { diff --git a/lib/redsync.f90 b/lib/redsync.f90 deleted file mode 100644 index 68a5e5dc0..000000000 --- a/lib/redsync.f90 +++ /dev/null @@ -1,44 +0,0 @@ -subroutine redsync(ss,ntrperiod,ihsym,iz,red) - -! Compute the red curve (approx JT9 sync amplitude). -! NB: red() is used for real-time display only. A better ccfred() is -! computed during the decode procedure. - - Parameter (NSMAX=1365) - real*4 ss(184,NSMAX) - real*4 red(NSMAX) - include 'jt9sync.f90' - - lagmax=9 - if(ntrperiod.eq.2) lagmax=5 - if(ntrperiod.eq.5) lagmax=2 - if(ntrperiod.eq.10) lagmax=1 - if(ntrperiod.eq.30) lagmax=1 - - do i=1,iz !Loop over frequency range - smax=0. - do lag=-lagmax,lagmax !Loop over DT lags - sig=0. - do j=1,16 - k=ii2(j)+lag - if(k.ge.5 .and. k.le.ihsym) then - sig=sig + ss(k,i) - 0.5*(ss(k-2,i)+ss(k-4,i)) - endif - enddo - if(sig.gt.smax) smax=sig - enddo - red(i)=smax - enddo - call pctile(red,iz,40,xmed) - if(xmed.le.0.0) xmed=1.0 - red=red/xmed - smax=0. - do i=1,iz - red(i)=0.2*db(red(i)) - smax=max(smax,red(i)) - enddo - h=10. - if(smax.gt.h) red=red*(h/smax) - - return -end subroutine redsync diff --git a/lib/s3avg.f90 b/lib/s3avg.f90 new file mode 100644 index 000000000..f8f68ac56 --- /dev/null +++ b/lib/s3avg.f90 @@ -0,0 +1,60 @@ +subroutine s3avg(nsave,mode65,nutc,nhz,xdt,npol,ntol,s3,nsum,nkv,decoded) + +! Save the current synchronized spectra, s3(64,63), for possible +! decoding of average. + + real s3(64,63) !Synchronized spectra for 63 symbols + real s3a(64,63,64) !Saved spectra + real s3b(64,63) !Average spectra + integer iutc(64),ihz(64),ipol(64) + real dt(64) + character*22 decoded + logical ltext,first + data first/.true./ + save + + if(first) then + iutc=-1 + ihz=0 + ipol=0 + first=.false. + ihzdiff=min(100,ntol) + dtdiff=0.2 + endif + + do i=1,64 + if(nutc.eq.iutc(i) .and. abs(nhz-ihz(i)).lt.ihzdiff) then + nsave=mod(nsave-1+64,64)+1 + go to 10 + endif + enddo + + iutc(nsave)=nutc !Save UTC + ihz(nsave)=nhz !Save freq in Hz + ipol(nsave)=npol !Save pol + dt(nsave)=xdt !Save DT + s3a(1:64,1:63,nsave)=s3 !Save the spectra + +10 s3b=0. + do i=1,64 !Accumulate avg spectra + if(iutc(i).lt.0) cycle + if(mod(iutc(i),2).ne.mod(nutc,2)) cycle !Use only same sequence + if(abs(nhz-ihz(i)).gt.ihzdiff) cycle !Freq must match + if(abs(xdt-dt(i)).gt.dtdiff) cycle !DT must match + s3b=s3b + s3a(1:64,1:63,i) + nsum=nsum+1 + enddo + + decoded=' ' + if(nsum.ge.2) then !Try decoding the sverage + nadd=mode65*nsum + call extract(s3b,nadd,ncount,nhist,decoded,ltext) !Extract the message + nkv=nsum + if(ncount.lt.0) then + nkv=0 + decoded=' ' + endif + endif + + return +end subroutine s3avg diff --git a/lib/setup65.f90 b/lib/setup65.f90 new file mode 100644 index 000000000..608b41b91 --- /dev/null +++ b/lib/setup65.f90 @@ -0,0 +1,96 @@ +subroutine setup65 + +! Defines arrays related to the JT65 pseudo-random synchronizing pattern. +! Executed at program start. + + integer nprc(126) + common/prcom/pr(126),mdat(126),mref(126,2),mdat2(126),mref2(126,2) + +! JT65 + data nprc/ & + 1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,1,0,1,0,0, & + 0,1,0,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,1,1, & + 0,1,1,0,1,1,1,1,0,0,0,1,1,0,1,0,1,0,1,1, & + 0,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1, & + 1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1, & + 0,1,0,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,1, & + 1,1,1,1,1,1/ + data mr2/0/ !Silence compiler warning + +! Put the appropriate pseudo-random sequence into pr + nsym=126 + do i=1,nsym + pr(i)=2*nprc(i)-1 + enddo + +! Determine locations of data and reference symbols + k=0 + mr1=0 + do i=1,nsym + if(pr(i).lt.0.0) then + k=k+1 + mdat(k)=i + else + mr2=i + if(mr1.eq.0) mr1=i + endif + enddo + nsig=k + +! Determine the reference symbols for each data symbol. + do k=1,nsig + m=mdat(k) + mref(k,1)=mr1 + do n=1,10 !Get ref symbol before data + if((m-n).gt.0) then + if (pr(m-n).gt.0.0) go to 10 + endif + enddo + go to 12 +10 mref(k,1)=m-n +12 mref(k,2)=mr2 + do n=1,10 !Get ref symbol after data + if((m+n).le.nsym) then + if (pr(m+n).gt.0.0) go to 20 + endif + enddo + cycle +20 mref(k,2)=m+n + enddo + +! Now do it all again, using opposite logic on pr(i) + k=0 + mr1=0 + do i=1,nsym + if(pr(i).gt.0.0) then + k=k+1 + mdat2(k)=i + else + mr2=i + if(mr1.eq.0) mr1=i + endif + enddo + nsig=k + + do k=1,nsig + m=mdat2(k) + mref2(k,1)=mr1 + do n=1,10 + if((m-n).gt.0) then + if (pr(m-n).lt.0.0) go to 110 + endif + enddo + go to 112 +110 mref2(k,1)=m-n +112 mref2(k,2)=mr2 + do n=1,10 + if((m+n).le.nsym) then + if (pr(m+n).lt.0.0) go to 120 + endif + enddo + cycle +120 mref2(k,2)=m+n + enddo + + return +end subroutine setup65 diff --git a/lib/smo121.f90 b/lib/smo121.f90 new file mode 100644 index 000000000..7ae30ad13 --- /dev/null +++ b/lib/smo121.f90 @@ -0,0 +1,13 @@ +subroutine smo121(x,nz) + + real x(nz) + + x0=x(1) + do i=2,nz-1 + x1=x(i) + x(i)=0.5*x(i) + 0.25*(x0+x(i+1)) + x0=x1 + enddo + + return +end subroutine smo121 diff --git a/lib/softsym.f90 b/lib/softsym.f90 index a17186774..399db36f2 100644 --- a/lib/softsym.f90 +++ b/lib/softsym.f90 @@ -1,9 +1,8 @@ -subroutine softsym(c0,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,freq,drift, & - schk,i1SoftSymbols) +subroutine softsym(id2,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt, & + freq,drift,schk,i1SoftSymbols) ! Compute the soft symbols - complex c0(0:npts8-1) complex c2(0:4096-1) complex c3(0:4096-1) complex c5(0:4096-1) @@ -16,7 +15,7 @@ subroutine softsym(c0,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,freq,drift, & ndown=nsps8/nspsd ! Mix, low-pass filter, and downsample to 16 samples per symbol - call downsam9(c0,npts8,nsps8,newdat,nspsd,fpk,c2,nz2) + call downsam9(id2,npts8,nsps8,newdat,nspsd,fpk,c2,nz2) call peakdt9(c2,nz2,nsps8,nspsd,c3,nz3,xdt) !Find DT @@ -26,7 +25,7 @@ subroutine softsym(c0,npts8,nsps8,newdat,fpk,syncpk,snrdb,xdt,freq,drift, & freq=fpk - a(1) drift=-2.0*a(2) - call twkfreq(c3,c5,nz3,fsample,a) !Correct for deltaF, fDot, fDDot + call twkfreq(c3,c5,nz3,fsample,a) !Correct for delta f, f1, f2 ==> a(1:3) ! Compute soft symbols (in scrambled order) call symspec2(c5,nz3,nsps8,nspsd,fsample,freq,drift,snrdb,schk, & diff --git a/lib/symspec.f90 b/lib/symspec.f90 index a428fb0a4..c6846b283 100644 --- a/lib/symspec.f90 +++ b/lib/symspec.f90 @@ -1,4 +1,4 @@ -subroutine symspec(k,ntrperiod,nsps,ingain,pxdb,s,red,df3,ihsym,npts8) +subroutine symspec(k,ntrperiod,nsps,ingain,slope,pxdb,s,df3,ihsym,npts8) ! Input: ! k pointer to the most recent new data @@ -10,111 +10,89 @@ subroutine symspec(k,ntrperiod,nsps,ingain,pxdb,s,red,df3,ihsym,npts8) ! Output: ! pxdb power (0-60 dB) -! s() spectrum for waterfall display -! red() first cut at JT9 sync amplitude +! s() current spectrum for waterfall display ! ihsym index number of this half-symbol (1-184) - parameter (NTMAX=120) - parameter (NMAX=NTMAX*12000) !Total sample intervals per 30 minutes - parameter (NDMAX=NTMAX*1500) !Sample intervals at 1500 Hz rate - parameter (NSMAX=1365) !Max length of saved spectra - parameter (NFFT1=1024) - parameter (NFFT2=1024,NFFT2A=NFFT2/8) - parameter (MAXFFT3=32768) - real*4 s(NSMAX),w3(MAXFFT3) - real*4 x1(NFFT1) - real*4 x2(NFFT1+105) +! jt9com +! ss() JT9 symbol spectra at half-symbol steps +! savg() average spectra for waterfall display + + include 'constants.f90' + real*4 w3(MAXFFT3) + real*4 s(NSMAX) + real*4 scale(NSMAX) real*4 ssum(NSMAX) - real*4 red(NSMAX) - complex cx(0:MAXFFT3-1) + real*4 xc(0:MAXFFT3-1) + complex cx(0:MAXFFT3/2) integer*2 id2 - complex c0 - common/jt9com/ss(184,NSMAX),savg(NSMAX),c0(NDMAX),id2(NMAX),nutc,ndiskdat, & + common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, & ntr,mousefqso,newdat,nfa,nfb,ntol,kin,nzhsym,nsynced,ndecoded - data rms/999.0/,k0/99999999/,ntrperiod0/0/,nfft3z/0/ + data rms/999.0/,k0/99999999/,nfft3z/0/,slope0/0.0/ + equivalence (xc,cx) save - if(ntrperiod.eq.1) nfft3=2048 - if(ntrperiod.eq.2) nfft3=2048 - if(ntrperiod.eq.5) nfft3=6144 - if(ntrperiod.eq.10) nfft3=12288 - if(ntrperiod.eq.30) nfft3=32768 - - jstep=nsps/16 !Step size = half-symbol in c0() - if(k.gt.NMAX) go to 999 - if(k.lt.nfft3) then + if(ntrperiod.eq.-999) stop !Silence compiler warning + nfft3=16384 !df=12000.0/16384 = 0.732422 + jstep=nsps/2 !Step size = half-symbol in id2() + if(k.gt.NMAX) go to 900 + if(k.lt.2048) then !(2048 was nfft3) (Any need for this ???) ihsym=0 - go to 999 !Wait for enough samples to start + go to 900 !Wait for enough samples to start endif - if(nfft3.ne.nfft3z) then !New nfft3, compute window + + if(nfft3.ne.nfft3z .or. slope.ne.slope0) then !New nfft3, compute window pi=4.0*atan(1.0) - if(ntrperiod.eq.1) then !Compute window for nfft3 spectrun - do i=1,nfft3 - xx=float(i-1)/(nfft3-1) - w3(i)=0.40897 -0.5*cos(2.0*pi*xx) + 0.09103*cos(4.0*pi*xx) -! w3(i)=0.355768 - 0.487306*cos(2.0*pi*xx) + 0.144232*cos(4.0*pi*xx) & -! - 0.012604*cos(6.0*pi*xx) - enddo - else - do i=1,nfft3 - w3(i)=2.0*(sin(i*pi/nfft3))**2 !Window for nfft3 spectrum - enddo - endif + do i=1,nfft3 + w3(i)=2.0*(sin(i*pi/nfft3))**2 !Window for nfft3 spectrum + enddo nfft3z=nfft3 + nh=NSMAX/2 + do i=1,NSMAX + x=slope*float(i)/nh - 1.0 + 2.6 + scale(i)=10.0**x + enddo + slope0=slope endif if(k.lt.k0) then !Start a new data block ja=0 ssum=0. ihsym=0 - k1=0 - k8=0 - x2=0. - if(ndiskdat.eq.0) then - id2(k+1:)=0 - c0=0. !This is necessary to prevent "ghosts". Not sure why. - endif + if(ndiskdat.eq.0) id2(k+1:)=0 !Needed to prevent "ghosts". Not sure why. endif - k0=k - kstep1=NFFT1 - fac=2.0/NFFT1 - nblks=(k-k1)/kstep1 gain=10.0**(0.05*ingain) sq=0. - do nblk=1,nblks - do i=1,NFFT1 - x1(i)=gain*id2(k1+i) - enddo - sq=sq + dot_product(x1,x1) -! Mix at 1500 Hz, lowpass at +/-750 Hz, and downsample to 1500 Hz complex. - x2(106:105+kstep1)=x1(1:kstep1) - call fil3(x2,kstep1+105,c0(k8+1),n2) - x2(1:105)=x1(kstep1-104:kstep1) !Save 105 trailing samples - k1=k1+kstep1 - k8=k8+kstep1/8 + do i=k0+1,k + x1=id2(i) + sq=sq + x1*x1 enddo - - npts8=k8 - ja=ja+jstep !Index of first sample - rms=sqrt(sq/(nblks*NFFT1)) + sq=sq * gain**2 + rms=sqrt(sq/(k-k0)) pxdb=0. if(rms.gt.0.0) pxdb=20.0*log10(rms) if(pxdb.gt.60.0) pxdb=60.0 + + k0=k + ja=ja+jstep !Index of first sample + + fac0=0.1 do i=0,nfft3-1 !Copy data into cx j=ja+i-(nfft3-1) - cx(i)=0. - if(j.ge.1 .and. j.le.NDMAX) cx(i)=c0(j) + xc(i)=0. + if(j.ge.1) xc(i)=fac0*id2(j) enddo if(ihsym.lt.184) ihsym=ihsym+1 - cx(0:nfft3-1)=w3(1:nfft3)*cx(0:nfft3-1) !Apply window w3 - call four2a(cx,nfft3,1,1,1) !Third FFT (forward) + + xc(0:nfft3-1)=w3(1:nfft3)*xc(0:nfft3-1) !Apply window w3 + call four2a(xc,nfft3,1,-1,0) !Real-to-complex FFT n=min(184,ihsym) - df3=1500.0/nfft3 !JT9-a: 0.732 Hz = 0.42 * tone spacing - i0=nint(-500.0/df3) - iz=min(NSMAX,nint(1000.0/df3)) + df3=12000.0/nfft3 !JT9-1: 0.732 Hz = 0.42 * tone spacing +! i0=nint(1000.0/df3) + i0=0 + iz=min(NSMAX,nint(5000.0/df3)) fac=(1.0/nfft3)**2 do i=1,iz j=i0+i-1 @@ -125,18 +103,11 @@ subroutine symspec(k,ntrperiod,nsps,ingain,pxdb,s,red,df3,ihsym,npts8) s(i)=sx enddo -999 continue +! s=0.05*s/ref + s=scale*s + savg=scale*ssum/ihsym - fac00=0.35 - npct=20 - call pctile(s,iz,npct,xmed0) - fac0=fac00/max(xmed0,0.006) - s(1:iz)=fac0*s(1:iz) - call pctile(ssum,iz,npct,xmed1) - fac1=fac00/max(xmed1,0.006*ihsym) - savg(1:iz)=fac1*ssum(1:iz) -! savg(iz+1:iz+20)=savg(iz) - call redsync(ss,ntrperiod,ihsym,iz,red) +900 npts8=k/8 return end subroutine symspec diff --git a/lib/symspec65.f90 b/lib/symspec65.f90 new file mode 100644 index 000000000..5f6da88fd --- /dev/null +++ b/lib/symspec65.f90 @@ -0,0 +1,47 @@ +subroutine symspec65(dd,npts,ss,nhsym,savg) + +! Compute JT65 symbol spectra at half-symbol steps + + parameter (NFFT=8192) + parameter (NSZ=3413) !NFFT*5000/12000 + parameter (MAXHSYM=322) + real*8 hstep + real*4 dd(npts) + real*4 ss(MAXHSYM,NSZ) + real*4 savg(NSZ) + real*4 x(NFFT) + complex c(0:NFFT/2) + common/refspec/dfref,ref(NSZ) + equivalence (x,c) + save /refspec/ + + hstep=2048.d0*12000.d0/11025.d0 !half-symbol = 2229.116 samples + nsps=nint(2*hstep) + df=12000.0/NFFT + nhsym=npts/hstep - 1.0 + savg=0. + fac1=1.e-3 + + do j=1,nhsym + i0=(j-1)*hstep + x(1:nsps)=fac1*dd(i0+1:i0+nsps) + x(nsps+1:)=0. + call four2a(c,NFFT,1,-1,0) !r2c forward FFT + do i=1,NSZ + s=real(c(i))**2 + aimag(c(i))**2 + ss(j,i)=s + savg(i)=savg(i)+s + enddo + enddo + savg=savg/nhsym + + call flat65(ss,nhsym,MAXHSYM,NSZ,ref) !Flatten the 2d spectrum, saving + dfref=df ! the reference spectrum ref() + + savg=savg/ref + do j=1,nhsym + ss(j,1:NSZ)=ss(j,1:NSZ)/ref + enddo + + return +end subroutine symspec65 diff --git a/lib/sync9.f90 b/lib/sync9.f90 index 8953587a6..433e11f76 100644 --- a/lib/sync9.f90 +++ b/lib/sync9.f90 @@ -1,6 +1,7 @@ subroutine sync9(ss,nzhsym,lag1,lag2,ia,ib,ccfred,red2,ipkbest) - parameter (NSMAX=1365) !Max length of saved spectra + include 'constants.f90' +! parameter (NSMAX=1365) !Max length of saved spectra real ss(184,NSMAX) real ss1(184) real ccfred(NSMAX) diff --git a/lib/timer.f90 b/lib/timer.f90 index 5aa92d9c4..16374932e 100644 --- a/lib/timer.f90 +++ b/lib/timer.f90 @@ -7,7 +7,7 @@ subroutine timer(dname,k) character*8 dname,name(50),space,ename character*16 sname logical on(50) - real ut(50),ut0(50),dut(50),tt(2) + real ut(50),ut0(50),dut(50) integer ncall(50),nlevel(50),nparent(50) integer onlevel(0:10) common/tracer/ limtrace,lu @@ -36,7 +36,8 @@ subroutine timer(dname,k) if(on(n)) print*,'Error in timer: ',dname,' already on.' level=level+1 !Increment the level on(n)=.true. - ut0(n)=etime(tt) + call system_clock(icount,irate) + ut0(n)=float(icount)/irate ncall(n)=ncall(n)+1 if(ncall(n).gt.1.and.nlevel(n).ne.level) then nlevel(n)=-1 @@ -49,7 +50,8 @@ subroutine timer(dname,k) else if(k.eq.1) then !Get stop times and accumulate sums. (k=1) if(on(n)) then on(n)=.false. - ut1=etime(tt) + call system_clock(icount,irate) + ut1=float(icount)/irate ut(n)=ut(n)+ut1-ut0(n) endif level=level-1 diff --git a/lib/twkfreq.f90 b/lib/twkfreq.f90 index 656a77a5e..0a9b34d20 100644 --- a/lib/twkfreq.f90 +++ b/lib/twkfreq.f90 @@ -13,13 +13,13 @@ subroutine twkfreq(c3,c4,npts,fsample,a) s=2.0/npts do i=1,npts x=s*(i-x0) -! if(mod(i,100).eq.1) then + if(mod(i,100).eq.1) then p2=1.5*x*x - 0.5 ! p3=2.5*(x**3) - 1.5*x ! p4=4.375*(x**4) - 3.75*(x**2) + 0.375 dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/fsample) wstep=cmplx(cos(dphi),sin(dphi)) -! endif + endif w=w*wstep c4(i)=w*c3(i) enddo diff --git a/lib/twkfreq65.f90 b/lib/twkfreq65.f90 new file mode 100644 index 000000000..85847c7bc --- /dev/null +++ b/lib/twkfreq65.f90 @@ -0,0 +1,25 @@ +subroutine twkfreq65(c4aa,n5,a) + + complex c4aa(n5) + real a(5) + complex w,wstep + data twopi/6.283185307/ + +! Apply AFC corrections to the c4aa data + w=1.0 + wstep=1.0 + x0=0.5*(n5+1) + s=2.0/n5 + do i=1,n5 + x=s*(i-x0) + if(mod(i,100).eq.1) then + p2=1.5*x*x - 0.5 + dphi=(a(1) + x*a(2) + p2*a(3)) * (twopi/1378.125) + wstep=cmplx(cos(dphi),sin(dphi)) + endif + w=w*wstep + c4aa(i)=w*c4aa(i) + enddo + + return +end subroutine twkfreq65 diff --git a/lib/wrapkarn.c b/lib/wrapkarn.c new file mode 100644 index 000000000..1b1a6311f --- /dev/null +++ b/lib/wrapkarn.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include "rs.h" + +static void *rs; +static int first=1; + +void rs_encode_(int *dgen, int *sent) +// Encode JT65 data dgen[12], producing sent[63]. +{ + int dat1[12]; + int b[51]; + int i; + + if(first) { + // Initialize the JT65 codec + rs=init_rs_int(6,0x43,3,1,51,0); + first=0; + } + + // Reverse data order for the Karn codec. + for(i=0; i<12; i++) { + dat1[i]=dgen[11-i]; + } + // Compute the parity symbols + encode_rs_int(rs,dat1,b); + + // Move parity symbols and data into sent[] array, in reverse order. + for (i = 0; i < 51; i++) sent[50-i] = b[i]; + for (i = 0; i < 12; i++) sent[i+51] = dat1[11-i]; +} + +void rs_decode_(int *recd0, int *era0, int *numera0, int *decoded, int *nerr) +// Decode JT65 received data recd0[63], producing decoded[12]. +// Erasures are indicated in era0[numera]. The number of corrected +// errors is *nerr. If the data are uncorrectable, *nerr=-1 is returned. +{ + int numera; + int i; + int era_pos[50]; + int recd[63]; + + if(first) { + rs=init_rs_int(6,0x43,3,1,51,0); + first=0; + } + + numera=*numera0; + for(i=0; i<12; i++) recd[i]=recd0[62-i]; + for(i=0; i<51; i++) recd[12+i]=recd0[50-i]; + if(numera) + for(i=0; i #endif -int itone[85]; //Tx audio tones for 85 symbols +int itone[126]; //Audio tones for all Tx symbols int icw[250]; //Dits for CW ID int outBufSize; int rc; +qint32 g_COMportOpen; +qint32 g_iptt; static int nc1=1; wchar_t buffer[256]; bool btxok; //True if OK to transmit @@ -31,9 +33,10 @@ WideGraph* g_pWideGraph = NULL; LogQSO* logDlg = NULL; Rig* rig = NULL; QTextEdit* pShortcuts; +QTcpSocket* socket = new QTcpSocket(0); QString rev="$Rev$"; -QString Program_Title_Version=" WSJT-X v1.0, r" + rev.mid(6,4) + +QString Program_Title_Version=" WSJT-X v1.1, r" + rev.mid(6,4) + " by K1JT"; //-------------------------------------------------- MainWindow constructor @@ -52,14 +55,12 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QWidget *parent) : QActionGroup* modeGroup = new QActionGroup(this); ui->actionJT9_1->setActionGroup(modeGroup); - ui->actionJT9_2->setActionGroup(modeGroup); - ui->actionJT9_5->setActionGroup(modeGroup); - ui->actionJT9_10->setActionGroup(modeGroup); - ui->actionJT9_30->setActionGroup(modeGroup); + ui->actionJT65->setActionGroup(modeGroup); + ui->actionJT9_JT65->setActionGroup(modeGroup); + QActionGroup* saveGroup = new QActionGroup(this); ui->actionNone->setActionGroup(saveGroup); - ui->actionSave_synced->setActionGroup(saveGroup); ui->actionSave_decoded->setActionGroup(saveGroup); ui->actionSave_all->setActionGroup(saveGroup); @@ -150,24 +151,24 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QWidget *parent) : m_myGrid="FN20qi"; m_appDir = QApplication::applicationDirPath(); m_saveDir="/users/joe/wsjtx/install/save"; + m_rxFreq=1500; m_txFreq=1500; m_setftx=0; m_loopall=false; m_startAnother=false; - m_saveSynced=false; m_saveDecoded=false; m_saveAll=false; m_sec0=-1; - m_palette="CuteSDR"; + m_palette="Linrad"; m_RxLog=1; //Write Date and Time to RxLog m_nutc0=9999; - m_mode="JT9-1"; + m_mode="JT9"; m_rpt="-15"; m_TRperiod=60; m_inGain=0; m_dataAvailable=false; - m_iptt=0; - m_COMportOpen=0; + g_iptt=0; + g_COMportOpen=0; m_secID=0; m_promptToLog=false; m_blankLine=false; @@ -185,11 +186,14 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QWidget *parent) : m_secBandChanged=0; m_bMultipleOK=false; m_dontReadFreq=false; + m_lockTxFreq=false; ui->readFreq->setEnabled(false); m_QSOmsg=""; + m_CATerror=false; decodeBusy(false); - ui->xThermo->setFillBrush(Qt::green); + ui->xThermo->setMaximumWidth(12); + ui->xThermo->setTextVisible(false); ui->labAz->setStyleSheet("border: 0px;"); ui->labDist->setStyleSheet("border: 0px;"); @@ -236,14 +240,20 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QWidget *parent) : genStdMsgs(m_rpt); on_actionWide_Waterfall_triggered(); //### + g_pWideGraph->setRxFreq(m_rxFreq); g_pWideGraph->setTxFreq(m_txFreq); - g_pWideGraph->m_lockTxFreq=m_lockTxFreq; + g_pWideGraph->setLockTxFreq(m_lockTxFreq); + g_pWideGraph->setFmin(m_fMin); + g_pWideGraph->setModeTx(m_mode); + g_pWideGraph->setModeTx(m_modeTx); + + connect(g_pWideGraph, SIGNAL(setFreq3(int,int)),this, + SLOT(setFreq4(int,int))); + + if(m_mode=="JT9") on_actionJT9_1_triggered(); + if(m_mode=="JT65") on_actionJT65_triggered(); + if(m_mode=="JT9+JT65") on_actionJT9_JT65_triggered(); - if(m_mode=="JT9-1") on_actionJT9_1_triggered(); - if(m_mode=="JT9-2") on_actionJT9_2_triggered(); - if(m_mode=="JT9-5") on_actionJT9_5_triggered(); - if(m_mode=="JT9-10") on_actionJT9_10_triggered(); - if(m_mode=="JT9-30") on_actionJT9_30_triggered(); future1 = new QFuture; watcher1 = new QFutureWatcher; connect(watcher1, SIGNAL(finished()),this,SLOT(diskDat())); @@ -281,7 +291,7 @@ MainWindow::MainWindow(QSharedMemory *shdmem, QWidget *parent) : ui->decodedTextLabel->setFont(ui->decodedTextBrowser2->font()); ui->decodedTextLabel2->setFont(ui->decodedTextBrowser->font()); - t="UTC dB DT Freq Message"; + t="UTC dB DT Freq Message"; ui->decodedTextLabel->setText(t); ui->decodedTextLabel2->setText(t); @@ -352,6 +362,7 @@ void MainWindow::writeSettings() if(g_pWideGraph->isVisible()) { m_wideGraphGeom = g_pWideGraph->geometry(); settings.setValue("WideGraphGeom",m_wideGraphGeom); + m_fMin=g_pWideGraph->getFmin(); } settings.endGroup(); @@ -362,23 +373,32 @@ void MainWindow::writeSettings() settings.setValue("PTTmethod",m_pttMethodIndex); settings.setValue("PTTport",m_pttPort); settings.setValue("SaveDir",m_saveDir); - settings.setValue("SoundInIndex",m_nDevIn); - settings.setValue("paInDevice",m_paInDevice); - settings.setValue("SoundOutIndex",m_nDevOut); - settings.setValue("paOutDevice",m_paOutDevice); + char soundName[128]; + if (Pa_GetDeviceInfo( m_paInDevice)) { // store name, number may be different next time + snprintf( soundName, sizeof( soundName), "%s:%s", + Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name, + Pa_GetDeviceInfo( m_paInDevice)->name); + settings.setValue("SoundInName", soundName); + } + if (Pa_GetDeviceInfo( m_paOutDevice)) { // store name, number may be different next time + snprintf( soundName, sizeof( soundName), "%s:%s", + Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name, + Pa_GetDeviceInfo( m_paOutDevice)->name); + settings.setValue("SoundOutName", soundName); + } settings.setValue("PaletteCuteSDR",ui->actionCuteSDR->isChecked()); settings.setValue("PaletteLinrad",ui->actionLinrad->isChecked()); settings.setValue("PaletteAFMHot",ui->actionAFMHot->isChecked()); settings.setValue("PaletteBlue",ui->actionBlue->isChecked()); settings.setValue("Mode",m_mode); + settings.setValue("ModeTx",m_modeTx); settings.setValue("SaveNone",ui->actionNone->isChecked()); - settings.setValue("SaveSynced",ui->actionSave_synced->isChecked()); settings.setValue("SaveDecoded",ui->actionSave_decoded->isChecked()); settings.setValue("SaveAll",ui->actionSave_all->isChecked()); settings.setValue("NDepth",m_ndepth); - settings.setValue("KB8RQ",m_kb8rq); settings.setValue("MonitorOFF",m_monitorStartOFF); settings.setValue("DialFreq",m_dialFreq); + settings.setValue("RxFreq",m_rxFreq); settings.setValue("TxFreq",m_txFreq); settings.setValue("InGain",m_inGain); settings.setValue("PSKReporter",m_pskReporter); @@ -423,6 +443,9 @@ void MainWindow::writeSettings() settings.setValue("TxPower",m_txPower); settings.setValue("LogComments",m_logComments); settings.setValue("PSKantenna",m_pskAntenna); + settings.setValue("Fmin",m_fMin); + settings.setValue("TxSplit",m_bSplit); + settings.setValue("UseXIT",m_bXIT); settings.endGroup(); } @@ -450,49 +473,63 @@ void MainWindow::readSettings() m_pttMethodIndex=settings.value("PTTmethod",1).toInt(); m_pttPort=settings.value("PTTport",0).toInt(); m_saveDir=settings.value("SaveDir",m_appDir + "/save").toString(); - m_nDevIn = settings.value("SoundInIndex", 0).toInt(); - m_paInDevice = settings.value("paInDevice", paNoDevice).toInt(); - if (m_paInDevice == paNoDevice) { // no saved input device? + + char soundName[128]; + QString savedName = settings.value( "SoundInName", "default").toString(); + for (m_paInDevice = Pa_GetDeviceCount() - 1; m_paInDevice >= 0; m_paInDevice--) { + snprintf( soundName, sizeof( soundName), "%s:%s", + Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paInDevice)->hostApi)->name, + Pa_GetDeviceInfo( m_paInDevice)->name); + if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paInDevice)->maxInputChannels > 0)) + break; + } + if (m_paInDevice < 0) { // no match for device name? m_paInDevice = Pa_GetDefaultInputDevice(); - if (m_paInDevice == paNoDevice) { // no default input device? + if (m_paInDevice == paNoDevice) // no default input device? m_paInDevice = 0; - } } - m_nDevOut = settings.value("SoundOutIndex", 0).toInt(); - m_paOutDevice = settings.value("paOutDevice", paNoDevice).toInt(); - if (m_paOutDevice == paNoDevice) { // no saved output device? + + savedName = settings.value("SoundOutName", "default").toString(); + for (m_paOutDevice = Pa_GetDeviceCount() - 1; m_paOutDevice >= 0; m_paOutDevice--) { + snprintf( soundName, sizeof( soundName), "%s:%s", + Pa_GetHostApiInfo( Pa_GetDeviceInfo( m_paOutDevice)->hostApi)->name, + Pa_GetDeviceInfo( m_paOutDevice)->name); + if ((savedName == soundName) && (Pa_GetDeviceInfo(m_paOutDevice)->maxOutputChannels > 0)) + break; + } + if (m_paOutDevice < 0) { // no match for device name? m_paOutDevice = Pa_GetDefaultOutputDevice(); - if (m_paOutDevice == paNoDevice) { // no default output device? + if (m_paOutDevice == paNoDevice) // no default output device? m_paOutDevice = 0; - } } + ui->actionCuteSDR->setChecked(settings.value( - "PaletteCuteSDR",true).toBool()); + "PaletteCuteSDR",false).toBool()); ui->actionLinrad->setChecked(settings.value( - "PaletteLinrad",false).toBool()); + "PaletteLinrad",true).toBool()); ui->actionAFMHot->setChecked(settings.value( "PaletteAFMHot",false).toBool()); ui->actionBlue->setChecked(settings.value( "PaletteBlue",false).toBool()); - m_mode=settings.value("Mode","JT9-1").toString(); + m_mode=settings.value("Mode","JT9").toString(); + m_modeTx=settings.value("ModeTx","JT9").toString(); + if(m_mode=="JT9") ui->pbTxMode->setText("Tx JT9 @"); + if(m_mode=="JT65") ui->pbTxMode->setText("Tx JT65 #"); ui->actionNone->setChecked(settings.value("SaveNone",true).toBool()); - ui->actionSave_synced->setChecked(settings.value( - "SaveSynced",false).toBool()); ui->actionSave_decoded->setChecked(settings.value( "SaveDecoded",false).toBool()); ui->actionSave_all->setChecked(settings.value("SaveAll",false).toBool()); m_dialFreq=settings.value("DialFreq",14.078).toDouble(); + m_rxFreq=settings.value("RxFreq",1500).toInt(); + ui->RxFreqSpinBox->setValue(m_rxFreq); m_txFreq=settings.value("TxFreq",1500).toInt(); ui->TxFreqSpinBox->setValue(m_txFreq); soundOutThread.setTxFreq(m_txFreq); - m_saveSynced=ui->actionSave_synced->isChecked(); m_saveDecoded=ui->actionSave_decoded->isChecked(); m_saveAll=ui->actionSave_all->isChecked(); - m_ndepth=settings.value("NDepth",2).toInt(); + m_ndepth=settings.value("NDepth",3).toInt(); m_inGain=settings.value("InGain",0).toInt(); ui->inGain->setValue(m_inGain); - m_kb8rq=settings.value("KB8RQ",false).toBool(); - ui->actionF4_sets_Tx6->setChecked(m_kb8rq); m_monitorStartOFF=settings.value("MonitorOFF",false).toBool(); ui->actionMonitor_OFF_at_startup->setChecked(m_monitorStartOFF); m_pskReporter=settings.value("PSKReporter",false).toBool(); @@ -547,12 +584,15 @@ void MainWindow::readSettings() m_logQSOgeom=settings.value("LogQSOgeom",QRect(500,400,424,283)).toRect(); outBufSize=settings.value("OutBufSize",4096).toInt(); m_lockTxFreq=settings.value("LockTxFreq",false).toBool(); - ui->actionLockTxFreq->setChecked(m_lockTxFreq); + ui->cbTxLock->setChecked(m_lockTxFreq); m_saveTxPower=settings.value("SaveTxPower",false).toBool(); m_saveComments=settings.value("SaveComments",false).toBool(); m_txPower=settings.value("TxPower","").toString(); m_logComments=settings.value("LogComments","").toString(); m_pskAntenna=settings.value("PSKantenna","").toString(); + m_fMin=settings.value("fMin",2500).toInt(); + m_bSplit=settings.value("TxSplit",false).toBool(); + m_bXIT=settings.value("UseXit",false).toBool(); settings.endGroup(); if(!ui->actionLinrad->isChecked() && !ui->actionCuteSDR->isChecked() && @@ -570,13 +610,14 @@ void MainWindow::readSettings() //-------------------------------------------------------------- dataSink() void MainWindow::dataSink(int k) { - static float s[NSMAX],red[NSMAX]; + static float s[NSMAX]; static int ihsym=0; static int nzap=0; static int trmin; static int npts8; static float px=0.0; static float df3; + static float slope; if(m_diskData) { jt9com_.ndiskdat=1; @@ -586,7 +627,9 @@ void MainWindow::dataSink(int k) // Get power, spectrum, and ihsym trmin=m_TRperiod/60; - symspec_(&k,&trmin,&m_nsps,&m_inGain,&px,s,red,&df3,&ihsym,&npts8); + slope=0.0; + if(g_pWideGraph!=NULL) slope=(float)g_pWideGraph->getSlope(); + symspec_(&k,&trmin,&m_nsps,&m_inGain,&slope,&px,s,&df3,&ihsym,&npts8); if(ihsym <=0) return; QString t; m_pctZap=nzap*100.0/m_nsps; @@ -594,7 +637,7 @@ void MainWindow::dataSink(int k) lab2->setText(t); ui->xThermo->setValue((double)px); //Update thermometer if(m_monitoring || m_diskData) { - g_pWideGraph->dataSink2(s,red,df3,ihsym,m_diskData); + g_pWideGraph->dataSink2(s,df3,ihsym,m_diskData); } if(ihsym == m_hsymStop) { @@ -637,8 +680,8 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog dlg.m_pttMethodIndex=m_pttMethodIndex; dlg.m_pttPort=m_pttPort; dlg.m_saveDir=m_saveDir; - dlg.m_nDevIn=m_nDevIn; - dlg.m_nDevOut=m_nDevOut; + dlg.m_paInDevice=m_paInDevice; + dlg.m_paOutDevice=m_paOutDevice; dlg.m_pskReporter=m_pskReporter; dlg.m_After73=m_After73; dlg.m_macro=m_macro; @@ -659,14 +702,17 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog dlg.m_bDTRoff=m_bDTRoff; dlg.m_pttData=m_pttData; dlg.m_poll=m_poll; + dlg.m_bSplit=m_bSplit; + dlg.m_bXIT=m_bXIT; if(m_bRigOpen) { rig->close(); ui->readFreq->setStyleSheet(""); ui->readFreq->setEnabled(false); - if(m_rig!=9999) delete rig; + if(m_rig<9900) delete rig; m_bRigOpen=false; m_catEnabled=false; + m_CATerror=false; } dlg.initDlg(); @@ -678,9 +724,7 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog m_pttMethodIndex=dlg.m_pttMethodIndex; m_pttPort=dlg.m_pttPort; m_saveDir=dlg.m_saveDir; - m_nDevIn=dlg.m_nDevIn; m_paInDevice=dlg.m_paInDevice; - m_nDevOut=dlg.m_nDevOut; m_paOutDevice=dlg.m_paOutDevice; m_macro=dlg.m_macro; m_dFreq=dlg.m_dFreq; @@ -700,6 +744,8 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog m_bDTRoff=dlg.m_bDTRoff; m_pttData=dlg.m_pttData; m_poll=dlg.m_poll; + m_bSplit=dlg.m_bSplit; + m_bXIT=dlg.m_bXIT; #ifdef WIN32 if(dlg.m_pskReporter!=m_pskReporter) { @@ -718,12 +764,14 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog } } #endif + m_pskReporter=dlg.m_pskReporter; #ifdef UNIX - psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) ); + if(m_pskReporter) { + psk_Reporter->setLocalStation(m_myCall,m_myGrid, "WSJT-X r" + rev.mid(6,4) ); + } #endif - m_pskReporter=dlg.m_pskReporter; m_After73=dlg.m_After73; if(dlg.m_restartSoundIn) { @@ -743,6 +791,8 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog if(m_catEnabled) { rigOpen(); + } else { + ui->readFreq->setStyleSheet(""); } } @@ -799,32 +849,32 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent { case Qt::Key_1: if(e->modifiers() & Qt::AltModifier) { - ui->txrb1->setChecked(true); + on_txb1_clicked(); break; } case Qt::Key_2: if(e->modifiers() & Qt::AltModifier) { - ui->txrb2->setChecked(true); + on_txb2_clicked(); break; } case Qt::Key_3: if(e->modifiers() & Qt::AltModifier) { - ui->txrb3->setChecked(true); + on_txb3_clicked(); break; } case Qt::Key_4: if(e->modifiers() & Qt::AltModifier) { - ui->txrb4->setChecked(true); + on_txb4_clicked(); break; } case Qt::Key_5: if(e->modifiers() & Qt::AltModifier) { - ui->txrb5->setChecked(true); + on_txb5_clicked(); break; } case Qt::Key_6: if(e->modifiers() & Qt::AltModifier) { - ui->txrb6->setChecked(true); + on_txb6_clicked(); break; } case Qt::Key_D: @@ -839,10 +889,6 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent case Qt::Key_F4: ui->dxCallEntry->setText(""); ui->dxGridEntry->setText(""); - if(m_kb8rq) { - m_ntx=6; - ui->txrb6->setChecked(true); - } case Qt::Key_F6: if(e->modifiers() & Qt::ShiftModifier) { on_actionDecode_remaining_files_in_directory_triggered(); @@ -898,10 +944,10 @@ void MainWindow::bumpFqso(int n) //bumpFqso() int i; bool ctrl = (n>=100); n=n%100; - i=g_pWideGraph->QSOfreq(); + i=g_pWideGraph->rxFreq(); if(n==11) i--; if(n==12) i++; - g_pWideGraph->setQSOfreq(i); + g_pWideGraph->setRxFreq(i); if(ctrl) { ui->TxFreqSpinBox->setValue(i); g_pWideGraph->setTxFreq(i); @@ -970,21 +1016,15 @@ void MainWindow::createStatusBar() //createStatusBar lab3 = new QLabel(""); lab3->setAlignment(Qt::AlignHCenter); - lab3->setMinimumSize(QSize(90,18)); + lab3->setMinimumSize(QSize(80,18)); lab3->setFrameStyle(QFrame::Panel | QFrame::Sunken); statusBar()->addWidget(lab3); lab4 = new QLabel(""); lab4->setAlignment(Qt::AlignHCenter); - lab4->setMinimumSize(QSize(50,18)); + lab4->setMinimumSize(QSize(150,18)); lab4->setFrameStyle(QFrame::Panel | QFrame::Sunken); statusBar()->addWidget(lab4); - - lab5 = new QLabel(""); - lab5->setAlignment(Qt::AlignHCenter); - lab5->setMinimumSize(QSize(150,18)); - lab5->setFrameStyle(QFrame::Panel | QFrame::Sunken); - statusBar()->addWidget(lab5); } void MainWindow::on_actionExit_triggered() //Exit() @@ -1029,7 +1069,7 @@ void MainWindow::msgBox(QString t) //msgBox void MainWindow::on_actionOnline_Users_Guide_triggered() //Display manual { QDesktopServices::openUrl(QUrl( - "http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide.pdf", + "http://www.physics.princeton.edu/pulsar/K1JT/WSJT-X_Users_Guide_v1.1.pdf", QUrl::TolerantMode)); } @@ -1046,6 +1086,8 @@ void MainWindow::on_actionWide_Waterfall_triggered() //Display Waterfalls SLOT(freezeDecode(int))); connect(g_pWideGraph, SIGNAL(f11f12(int)),this, SLOT(bumpFqso(int))); + connect(g_pWideGraph, SIGNAL(setXIT2(int)),this, + SLOT(setXIT(int))); // connect(g_pWideGraph, SIGNAL(dialFreqChanged(double)),this, // SLOT(dialFreqChanged2(double))); } @@ -1146,30 +1188,15 @@ void MainWindow::on_actionDelete_all_wav_files_in_SaveDir_triggered() } } -void MainWindow::on_actionF4_sets_Tx6_triggered() //F4 sets Tx6 -{ - m_kb8rq = !m_kb8rq; -} - void MainWindow::on_actionNone_triggered() //Save None { - m_saveSynced=false; m_saveDecoded=false; m_saveAll=false; ui->actionNone->setChecked(true); } -void MainWindow::on_actionSave_synced_triggered() -{ - m_saveSynced=true; - m_saveDecoded=false; - m_saveAll=false; - ui->actionSave_synced->setChecked(true); -} - void MainWindow::on_actionSave_decoded_triggered() { - m_saveSynced=false; m_saveDecoded=true; m_saveAll=false; ui->actionSave_decoded->setChecked(true); @@ -1177,7 +1204,6 @@ void MainWindow::on_actionSave_decoded_triggered() void MainWindow::on_actionSave_all_triggered() //Save All { - m_saveSynced=false; m_saveDecoded=false; m_saveAll=true; ui->actionSave_all->setChecked(true); @@ -1248,7 +1274,7 @@ void MainWindow::on_DecodeButton_clicked() //Decode request void MainWindow::freezeDecode(int n) //freezeDecode() { bool ctrl = (n>=100); - int i=g_pWideGraph->QSOfreq(); + int i=g_pWideGraph->rxFreq(); if(ctrl) { ui->TxFreqSpinBox->setValue(i); g_pWideGraph->setTxFreq(i); @@ -1258,6 +1284,7 @@ void MainWindow::freezeDecode(int n) //freezeDecode() void MainWindow::decode() //decode() { + if(!m_dataAvailable) return; ui->DecodeButton->setStyleSheet(m_pbdecoding_style1); if(jt9com_.nagain==0 && (!m_diskData)) { qint64 ms = QDateTime::currentMSecsSinceEpoch() % 86400000; @@ -1268,21 +1295,26 @@ void MainWindow::decode() //decode() jt9com_.nutc=100*ihr + imin; } - jt9com_.nfqso=g_pWideGraph->QSOfreq(); + jt9com_.nfqso=g_pWideGraph->rxFreq(); jt9com_.ndepth=m_ndepth; jt9com_.ndiskdat=0; if(m_diskData) jt9com_.ndiskdat=1; - jt9com_.nfa=g_pWideGraph->getFmin(); - jt9com_.nfb=g_pWideGraph->getFmax(); - - jt9com_.ntol=3; + int nfa=g_pWideGraph->getFmin(); + int nfb=g_pWideGraph->getFmax(); + if(m_mode=="JT9") nfa=200; //decode from 0 to fmax + if(m_mode=="JT65") nfa=nfb; //decode from 0 to fmax + jt9com_.nfa=nfa; + jt9com_.nfb=nfb; + jt9com_.ntol=20; if(jt9com_.nutc < m_nutc0) m_RxLog |= 1; //Date and Time to all.txt m_nutc0=jt9com_.nutc; - jt9com_.nrxlog=m_RxLog; - jt9com_.nfsample=12000; + jt9com_.ntxmode=9; + if(m_modeTx=="JT65") jt9com_.ntxmode=65; + jt9com_.nmode=9; + if(m_mode=="JT65") jt9com_.nmode=65; + if(m_mode=="JT9+JT65") jt9com_.nmode=9+65; jt9com_.ntrperiod=m_TRperiod; m_nsave=0; - if(m_saveSynced) m_nsave=1; if(m_saveDecoded) m_nsave=2; jt9com_.nsave=m_nsave; strncpy(jt9com_.datetime, m_dateTime.toLatin1(), 20); @@ -1294,7 +1326,7 @@ void MainWindow::decode() //decode() char *from = (char*) jt9com_.ss; int size=sizeof(jt9com_); if(jt9com_.newdat==0) { - int noffset = 4*184*NSMAX + 4*NSMAX + 4*2*NTMAX*1500 + 2*NTMAX*12000; + int noffset = 4*184*NSMAX + 4*NSMAX + 2*NTMAX*12000; to += noffset; from += noffset; size -= noffset; @@ -1325,10 +1357,8 @@ void MainWindow::readFromStdout() //readFromStdout while(proc_jt9.canReadLine()) { QByteArray t=proc_jt9.readLine(); if(t.indexOf("") >= 0) { - m_bsynced = (t.mid(19,1).toInt()==1); m_bdecoded = (t.mid(23,1).toInt()==1); - bool keepFile=m_saveAll or (m_saveSynced and m_bsynced) or - (m_saveDecoded and m_bdecoded); + bool keepFile=m_saveAll or (m_saveDecoded and m_bdecoded); if(!keepFile and !m_diskData) killFileTimer->start(45*1000); //Kill in 45 s jt9com_.nagain=0; jt9com_.ndiskdat=0; @@ -1372,12 +1402,11 @@ void MainWindow::readFromStdout() //readFromStdout QString bg="white"; if(t.indexOf(" CQ ")>0) bg="#66ff66"; //green if(m_myCall!="" and t.indexOf(" "+m_myCall+" ")>0) bg="#ff6666"; //red - bool bQSO=abs(t.mid(22,4).toInt() - g_pWideGraph->QSOfreq()) < 10; - QString t1=t.mid(0,5) + t.mid(10,4) + t.mid(15,5) + t.mid(22,4) + - t.mid(32); - t1=t1.replace("\n","").mid(0,t1.length()-4); + bool bQSO=abs(t.mid(14,4).toInt() - g_pWideGraph->rxFreq()) < 10; + QString t1=t.replace("\n","").mid(0,t.length()-4); QString s = "
" + t1 + "
"; + bool b65=t1.indexOf("#")==19; if(bQSO) { cursor = ui->decodedTextBrowser2->textCursor(); cursor.movePosition(QTextCursor::End); @@ -1386,6 +1415,8 @@ void MainWindow::readFromStdout() //readFromStdout cursor.insertHtml(s); ui->decodedTextBrowser2->setTextCursor(cursor); m_QSOmsg=t1; + if(b65 and m_modeTx!="JT65") on_pbTxMode_clicked(); + if(!b65 and m_modeTx=="JT65") on_pbTxMode_clicked(); } if(jt9com_.nagain==0) { @@ -1401,7 +1432,7 @@ void MainWindow::readFromStdout() //readFromStdout ui->decodedTextBrowser->setTextCursor(cursor); } - QString msg=t.mid(34); + QString msg=t.mid(21); int i1=msg.indexOf("\r"); if(i1>0) msg=msg.mid(0,i1-1) + " "; bool b=stdmsg_(msg.mid(0,22).toLatin1().constData(),22); @@ -1425,30 +1456,30 @@ void MainWindow::readFromStdout() //readFromStdout int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; bool okToPost=(nsec>50); + QString msgmode="JT9"; + if(b65) msgmode="JT65"; + i1=msg.indexOf(" "); + QString c2=msg.mid(i1+1); + int i2=c2.indexOf(" "); + QString g2=c2.mid(i2+1,4); + c2=c2.mid(0,i2); + QString remote="call," + c2 + ","; + if(gridOK(g2)) remote += "gridsquare," + g2 + ","; + int nHz=t.mid(14,4).toInt(); + uint nfreq=1000000.0*m_dialFreq + nHz + 0.5; + remote += "freq," + QString::number(nfreq); + int nsnr=t.mid(5,3).toInt(); + remote += ",mode," + msgmode + ",snr," + QString::number(nsnr) + ",,"; + wchar_t tremote[256]; + remote.toWCharArray(tremote); #ifdef WIN32 if(m_pskReporterInit and b and !m_diskData and okToPost) { - int i1=msg.indexOf(" "); - QString c2=msg.mid(i1+1); - int i2=c2.indexOf(" "); - QString g2=c2.mid(i2+1,4); - c2=c2.mid(0,i2); - QString remote="call," + c2 + ","; - if(gridOK(g2)) remote += "gridsquare," + g2 + ","; - int nHz=t.mid(22,4).toInt(); - uint nfreq=1000000.0*m_dialFreq + nHz + 0.5; - remote += "freq," + QString::number(nfreq); - int nsnr=t.mid(10,3).toInt(); - remote += ",mode,JT9,snr," + QString::number(nsnr) + ",,"; - - wchar_t tremote[256]; - remote.toWCharArray(tremote); - - QString local="station_callsign," + m_myCall + "," + - "my_gridsquare," + m_myGrid + ","; - if(m_pskAntenna!="") local += "my_antenna," + m_pskAntenna + ","; - local += "programid,WSJT-X,programversion," + rev.mid(6,4) + ",,"; + QString local="station_callsign#" + m_myCall + "#" + + "my_gridsquare#" + m_myGrid + "#"; + if(m_pskAntenna!="") local += "my_antenna#" + m_pskAntenna + "#"; + local += "programid#WSJT-X#programversion#" + rev.mid(6,4) + "##"; wchar_t tlocal[256]; local.toWCharArray(tlocal); @@ -1456,28 +1487,20 @@ void MainWindow::readFromStdout() //readFromStdout rc=ReporterSeenCallsign(tremote,tlocal,flags); if(rc!=0) { ReporterGetInformation(buffer,256); - qDebug() << "C:" << rc << QString::fromStdWString(buffer); } rc=ReporterTickle(); if(rc!=0) { rc=ReporterGetInformation(buffer,256); - qDebug() << "D:" << QString::fromStdWString(buffer); } } #else - if(b and !m_diskData and okToPost) { - int i1=msg.indexOf(" "); - QString c2=msg.mid(i1+1); - int i2=c2.indexOf(" "); - QString g2=c2.mid(i2+1,4); - c2=c2.mid(0,i2); - int nHz=t.mid(22,4).toInt(); - QString freq = QString::number((int)(1000000.0*m_dialFreq + - nHz + 0.5)); - QString snr= QString::number(t.mid(10,3).toInt()); - if(gridOK(g2)) - psk_Reporter->addRemoteStation(c2,g2,freq,"JT9",snr, + if(m_pskReporter and b and !m_diskData and okToPost) { + QString freq = QString::number(nfreq); + QString snr= QString::number(nsnr); + if(gridOK(g2)) { + psk_Reporter->addRemoteStation(c2,g2,freq,msgmode,snr, QString::number(QDateTime::currentDateTime().toTime_t())); + } } #endif } @@ -1520,16 +1543,17 @@ void MainWindow::guiUpdate() { static int iptt0=0; static bool btxok0=false; - static int nc0=1; static char message[29]; static char msgsent[29]; static int nsendingsh=0; - int khsym=0; + static int giptt00=-1; + static int gcomport00=-1; int ret=0; QString rt; double tx1=0.0; double tx2=1.0 + 85.0*m_nsps/12000.0 + icw[0]*2560.0/48000.0; + if(m_modeTx=="JT65") tx2=1.0 + 126*4096/11025.0 + icw[0]*2560.0/48000.0; if(!m_txFirst) { tx1 += m_TRperiod; @@ -1548,12 +1572,12 @@ void MainWindow::guiUpdate() } float fTR=float((nsec%m_TRperiod))/m_TRperiod; - if(m_iptt==0 and ((bTxTime and !btxMute and fTR<0.4) or m_tune )) { + if(g_iptt==0 and ((bTxTime and !btxMute and fTR<0.4) or m_tune )) { icw[0]=m_ncw; //Raise PTT if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) { - m_iptt=1; + g_iptt=1; if(m_pttData) ret=rig->setPTT(RIG_PTT_ON_DATA, RIG_VFO_CURR); if(!m_pttData) ret=rig->setPTT(RIG_PTT_ON_MIC, RIG_VFO_CURR); if(ret!=RIG_OK) { @@ -1562,11 +1586,14 @@ void MainWindow::guiUpdate() } } + if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { //DTR or RTS - ptt(m_pttPort,1,&m_iptt,&m_COMportOpen); +// qDebug() << "guiUpdate, line 1585:" << m_pttPort << 1 << g_iptt << g_COMportOpen; + ptt(m_pttPort,1,&g_iptt,&g_COMportOpen); +// qDebug() << "guiUpdate, line 1588:" << m_pttPort << 1 << g_iptt << g_COMportOpen; } if(m_pttMethodIndex==3) { //VOX - m_iptt=1; + g_iptt=1; } ptt1Timer->start(200); //Sequencer delay } @@ -1576,7 +1603,7 @@ void MainWindow::guiUpdate() } // Calculate Tx tones when needed - if((m_iptt==1 && iptt0==0) || m_restart) { + if((g_iptt==1 && iptt0==0) || m_restart) { QByteArray ba; if(m_ntx == 1) ba=ui->tx1->text().toLocal8Bit(); if(m_ntx == 2) ba=ui->tx2->text().toLocal8Bit(); @@ -1591,11 +1618,12 @@ void MainWindow::guiUpdate() // ba2msg(ba,msgsent); int len1=22; int ichk=0,itext=0; - genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1); + if(m_modeTx=="JT9") genjt9_(message,&ichk,msgsent,itone,&itext,len1,len1); + if(m_modeTx=="JT65") gen65_(message,&ichk,msgsent,itone,&itext,len1,len1); msgsent[22]=0; QString t=QString::fromLatin1(msgsent); if(m_tune) t="TUNE"; - lab5->setText("Last Tx: " + t); + lab4->setText("Last Tx: " + t); if(m_restart) { QFile f("ALL.TXT"); f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); @@ -1649,7 +1677,8 @@ void MainWindow::guiUpdate() // If PTT was just raised, start a countdown for raising TxOK: - if(m_iptt == 1 && iptt0 == 0) { +// NB: could be better implemented with a timer + if(g_iptt == 1 && iptt0 == 0) { nc1=-9; // TxDelay = 0.8 s } if(nc1 <= 0) { @@ -1669,6 +1698,7 @@ void MainWindow::guiUpdate() soundInThread.setMonitoring(false); btxok=true; m_transmitting=true; + ui->pbTxMode->setEnabled(false); if(!m_tune) { QFile f("ALL.TXT"); f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); @@ -1681,36 +1711,15 @@ void MainWindow::guiUpdate() if(m_tx2QSO and !m_tune) displayTxMsg(t); } - if(!btxok && btxok0 && m_iptt==1) stopTx(); + if(!btxok && btxok0 && g_iptt==1) stopTx(); +/* // If btxok was just lowered, start a countdown for lowering PTT - if(!btxok && btxok0 && m_iptt==1) nc0=-11; //RxDelay = 1.0 s + if(!btxok && btxok0 && g_iptt==1) nc0=-11; //RxDelay = 1.0 s if(nc0 <= 0) { nc0++; } - - if(nc0 == 0) { - //Lower PTT - if(m_catEnabled and m_bRigOpen and m_pttMethodIndex==0) { - m_iptt=0; - ret=rig->setPTT(RIG_PTT_OFF, RIG_VFO_CURR); //CAT control for PTT=0 - if(ret!=RIG_OK) { - rt.sprintf("CAT control PTT failed: %d",ret); - msgBox(rt); - } - } - if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { //DTR-RTS - ptt(m_pttPort,0,&m_iptt,&m_COMportOpen); - } - if(m_pttMethodIndex==3) { //VOX - m_iptt=0; - } - } - - if(m_iptt == 0 && !btxok) { - // sending="" - // nsendingsh=0 - } +*/ if(m_monitoring) { ui->monitorButton->setStyleSheet(m_pbmonitor_style); @@ -1718,8 +1727,6 @@ void MainWindow::guiUpdate() ui->monitorButton->setStyleSheet(""); } - lab3->setText("QSO Freq: " + QString::number(g_pWideGraph->QSOfreq())); - if(m_startAnother) { m_startAnother=false; on_actionOpen_next_in_directory_triggered(); @@ -1765,24 +1772,31 @@ void MainWindow::guiUpdate() if(m_catEnabled and m_poll>0 and (nsec%m_poll)==0) { if(m_dontReadFreq) { m_dontReadFreq=false; - } else { + } else if(!m_transmitting) { double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0; if(fMHz<0.0) { rt.sprintf("Rig control error %d\nFailed to read frequency.", int(1000000.0*fMHz)); msgBox(rt); m_catEnabled=false; + ui->readFreq->setStyleSheet("QPushButton{background-color: red; \ + border-width: 0px; border-radius: 5px;}"); } int ndiff=1000000.0*(fMHz-m_dialFreq); if(ndiff!=0) dialFreqChanged2(fMHz); } } - m_hsym0=khsym; m_sec0=nsec; } - iptt0=m_iptt; + if(g_iptt!=giptt00 or g_COMportOpen!=gcomport00) { +// qDebug() << "guiUpdate line 1788:" << g_iptt << g_COMportOpen; + giptt00=g_iptt; + gcomport00=g_COMportOpen; + } + + iptt0=g_iptt; btxok0=btxok; } //End of GUIupdate @@ -1791,7 +1805,12 @@ void MainWindow::displayTxMsg(QString t) QString bg="yellow"; QTextBlockFormat bf; QTextCursor cursor; - t=QDateTime::currentDateTimeUtc().toString("hhmmss Tx: ") + t; + QString t1=" @ "; + if(m_modeTx=="JT65") t1=" # "; + QString t2; + t2.sprintf("%4d",m_txFreq); + t=QDateTime::currentDateTimeUtc().toString("hhmm") + \ + " Tx " + t2 + t1 + t; QString s = "
" + t + "
"; cursor = ui->decodedTextBrowser2->textCursor(); @@ -1809,12 +1828,14 @@ void MainWindow::startTx2() double snr=t.mid(1,5).toDouble(); if(snr>0.0 or snr < -50.0) snr=99.0; soundOutThread.setTxSNR(snr); + soundOutThread.m_modeTx=m_modeTx; soundOutThread.start(QThread::HighestPriority); ui->xThermo->setValue(0.0); //Set Thermo to zero m_monitoring=false; soundInThread.setMonitoring(false); btxok=true; m_transmitting=true; + ui->pbTxMode->setEnabled(false); } } @@ -1825,7 +1846,9 @@ void MainWindow::stopTx() soundOutThread.wait(3000); } m_transmitting=false; - m_iptt=0; + ui->pbTxMode->setEnabled(true); + g_iptt=0; +// qDebug() << "stopTx, line 1845:" << g_iptt << g_COMportOpen; lab1->setStyleSheet(""); lab1->setText(""); ptt0Timer->start(200); //Sequencer delay @@ -1847,7 +1870,8 @@ void MainWindow::stopTx2() } } if(m_pttMethodIndex==1 or m_pttMethodIndex==2) { - ptt(m_pttPort,0,&m_iptt,&m_COMportOpen); +// qDebug() << "stopTx2, line 1867):" << g_iptt << g_COMportOpen; + ptt(m_pttPort,0,&g_iptt,&g_COMportOpen); } if(m_73TxDisable and m_sent73) on_stopTxButton_clicked(); @@ -1930,6 +1954,7 @@ void MainWindow::doubleClickOnCall2(bool shift, bool ctrl) doubleClickOnCall(shift,ctrl); m_decodedText2=false; } + void MainWindow::doubleClickOnCall(bool shift, bool ctrl) { QTextCursor cursor; @@ -1972,19 +1997,32 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) m_QSOmsg=t2; } - int nfreq=int(t4.at(3).toFloat()); - g_pWideGraph->setQSOfreq(nfreq); //Set Rx freq - QString firstcall=t4.at(4); + int nfreq=t4.at(3).toInt(); + if(t4.at(1)=="Tx") nfreq=t4.at(2).toInt(); + g_pWideGraph->setRxFreq(nfreq); //Set Rx freq + if(t4.at(1)=="Tx") return; + + if(t4.at(4)=="@") { + m_modeTx="JT9"; + ui->pbTxMode->setText("Tx JT9 @"); + g_pWideGraph->setModeTx(m_modeTx); + } + if(t4.at(4)=="#") { + m_modeTx="JT65"; + ui->pbTxMode->setText("Tx JT65 #"); + g_pWideGraph->setModeTx(m_modeTx); + } + QString firstcall=t4.at(5); // Don't change Tx freq if a station is calling me, unless m_lockTxFreq // is true or CTRL is held down or if((firstcall!=m_myCall) or m_lockTxFreq or ctrl) { ui->TxFreqSpinBox->setValue(nfreq); } - QString hiscall=t4.at(5); + QString hiscall=t4.at(6); QString hisgrid=""; - if(t4.length()>=7) hisgrid=t4.at(6); + if(t4.length()>=8) hisgrid=t4.at(7); + if(hiscall!=ui->dxCallEntry->text()) ui->dxGridEntry->setText(""); ui->dxCallEntry->setText(hiscall); - ui->dxGridEntry->setText(""); if(gridOK(hisgrid)) ui->dxGridEntry->setText(hisgrid); if(ui->dxGridEntry->text()=="") lookup(); m_hisGrid=ui->dxGridEntry->text(); @@ -2005,8 +2043,8 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) ui->rptSpinBox->setValue(rpt.toInt()); genStdMsgs(rpt); if(t2.indexOf(m_myCall)>=0) { - if(t4.length()>=7 and !gridOK(t4.at(6))) { - QString r=t4.at(6); + if(t4.length()>=7 and !gridOK(t4.at(7))) { + QString r=t4.at(7); if(r.mid(0,3)=="RRR") { m_ntx=5; ui->txrb5->setChecked(true); @@ -2362,7 +2400,7 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button logDlg->m_saveComments=m_saveComments; logDlg->m_txPower=m_txPower; logDlg->m_comments=m_logComments; - logDlg->initLogQSO(m_hisCall,m_hisGrid,m_mode,m_rptSent,m_rptRcvd, + logDlg->initLogQSO(m_hisCall,m_hisGrid,m_modeTx,m_rptSent,m_rptRcvd, m_dateTimeQSO,m_dialFreq+m_txFreq/1.0e6, m_myCall,m_myGrid,m_noSuffix,m_toRTTY,m_dBtoComments); connect(logDlg, SIGNAL(acceptQSO(bool)),this,SLOT(acceptQSO2(bool))); @@ -2393,101 +2431,76 @@ void MainWindow::acceptQSO2(bool accepted) void MainWindow::on_actionJT9_1_triggered() { - m_mode="JT9-1"; + m_mode="JT9"; + if(m_modeTx!="JT9") on_pbTxMode_clicked(); statusChanged(); m_TRperiod=60; m_nsps=6912; m_hsymStop=173; soundInThread.setPeriod(m_TRperiod,m_nsps); soundOutThread.setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - lab4->setStyleSheet("QLabel{background-color: #ff6ec7}"); - lab4->setText(m_mode); + lab3->setStyleSheet("QLabel{background-color: #ff6ec7}"); + lab3->setText(m_mode); ui->actionJT9_1->setChecked(true); - //m_fMax=2000; - //ui->fMaxSpinBox->setValue(m_fMax); - g_pWideGraph->setfMax(2000); + g_pWideGraph->setPeriod(m_TRperiod,m_nsps); + g_pWideGraph->setMode(m_mode); + g_pWideGraph->setModeTx(m_modeTx); + ui->pbTxMode->setEnabled(false); } -void MainWindow::on_actionJT9_2_triggered() +void MainWindow::on_actionJT65_triggered() { - m_mode="JT9-2"; + m_mode="JT65"; + if(m_modeTx!="JT65") on_pbTxMode_clicked(); statusChanged(); - m_TRperiod=120; - m_nsps=15360; - m_hsymStop=178; + m_TRperiod=60; + m_nsps=6912; //For symspec only + m_hsymStop=173; soundInThread.setPeriod(m_TRperiod,m_nsps); soundOutThread.setPeriod(m_TRperiod,m_nsps); + lab3->setStyleSheet("QLabel{background-color: #ffff00}"); + lab3->setText(m_mode); + ui->actionJT65->setChecked(true); g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - lab4->setStyleSheet("QLabel{background-color: #ffff00}"); - lab4->setText(m_mode); - ui->actionJT9_2->setChecked(true); - //m_fMax=2000; - //ui->fMaxSpinBox->setValue(m_fMax); - g_pWideGraph->setfMax(2000); + g_pWideGraph->setMode(m_mode); + g_pWideGraph->setModeTx(m_modeTx); + ui->pbTxMode->setEnabled(false); } -void MainWindow::on_actionJT9_5_triggered() +void MainWindow::on_actionJT9_JT65_triggered() { - m_mode="JT9-5"; + m_mode="JT9+JT65"; +// if(m_modeTx!="JT9") on_pbTxMode_clicked(); statusChanged(); - m_TRperiod=300; - m_nsps=40960; - m_hsymStop=172; + m_TRperiod=60; + m_nsps=6912; + m_hsymStop=173; soundInThread.setPeriod(m_TRperiod,m_nsps); soundOutThread.setPeriod(m_TRperiod,m_nsps); + lab3->setStyleSheet("QLabel{background-color: #ffa500}"); + lab3->setText(m_mode); + ui->actionJT9_JT65->setChecked(true); g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - lab4->setStyleSheet("QLabel{background-color: #ffa500}"); - lab4->setText(m_mode); - ui->actionJT9_5->setChecked(true); - //m_fMax=1300; - //ui->fMaxSpinBox->setValue(m_fMax); - g_pWideGraph->setfMax(1300); -} - -void MainWindow::on_actionJT9_10_triggered() -{ - m_mode="JT9-10"; - statusChanged(); - m_TRperiod=600; - m_nsps=82944; - m_hsymStop=171; - soundInThread.setPeriod(m_TRperiod,m_nsps); - soundOutThread.setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - lab4->setStyleSheet("QLabel{background-color: #7fff00}"); - lab4->setText(m_mode); - ui->actionJT9_10->setChecked(true); - //m_fMax=1150; - //ui->fMaxSpinBox->setValue(m_fMax); - g_pWideGraph->setfMax(1150); -} - -void MainWindow::on_actionJT9_30_triggered() -{ - m_mode="JT9-30"; - statusChanged(); - m_TRperiod=1800; - m_nsps=252000; - m_hsymStop=167; - soundInThread.setPeriod(m_TRperiod,m_nsps); - soundOutThread.setPeriod(m_TRperiod,m_nsps); - g_pWideGraph->setPeriod(m_TRperiod,m_nsps); - lab4->setStyleSheet("QLabel{background-color: #97ffff}"); - lab4->setText(m_mode); - ui->actionJT9_30->setChecked(true); - //m_fMax=1050; - //ui->fMaxSpinBox->setValue(m_fMax); - g_pWideGraph->setfMax(1050); + g_pWideGraph->setMode(m_mode); + g_pWideGraph->setModeTx(m_modeTx); + ui->pbTxMode->setEnabled(true); } void MainWindow::on_TxFreqSpinBox_valueChanged(int n) { m_txFreq=n; if(g_pWideGraph!=NULL) g_pWideGraph->setTxFreq(n); + if(m_lockTxFreq) ui->RxFreqSpinBox->setValue(n); soundOutThread.setTxFreq(n); } +void MainWindow::on_RxFreqSpinBox_valueChanged(int n) +{ + m_rxFreq=n; + if(g_pWideGraph!=NULL) g_pWideGraph->setRxFreq(n); + if(m_lockTxFreq) ui->TxFreqSpinBox->setValue(n); +} + void MainWindow::on_actionQuickDecode_triggered() { m_ndepth=1; @@ -2638,6 +2651,9 @@ void MainWindow::on_bandComboBox_activated(int index) if(m_bRigOpen) { m_dontReadFreq=true; ret=rig->setFreq(MHz(m_dialFreq)); +// ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_B); + bumpFqso(11); + bumpFqso(12); if(ret!=RIG_OK) { rt.sprintf("Set rig frequency failed: %d",ret); msgBox(rt); @@ -2783,11 +2799,6 @@ void MainWindow::on_actionRunaway_Tx_watchdog_triggered(bool checked) m_runaway=checked; } -void MainWindow::on_actionTx2QSO_triggered(bool checked) -{ - m_tx2QSO=checked; -} - void MainWindow::on_tuneButton_clicked() { if(m_tune) { @@ -2820,12 +2831,16 @@ void MainWindow::rigOpen() int ret; rig = new Rig(); - if(m_rig != 9999) { + if(m_rig<9900) { if (!rig->init(m_rig)) { msgBox("Rig init failure"); return; } - rig->setConf("rig_pathname", m_catPort.toLatin1().data()); + QString sCATport=m_catPort; +#ifdef WIN32 + sCATport="\\\\.\\" + m_catPort; //Allow COM ports above 9 +#endif + rig->setConf("rig_pathname", sCATport.toLatin1().data()); char buf[80]; sprintf(buf,"%d",m_serialRate); rig->setConf("serial_speed",buf); @@ -2844,23 +2859,28 @@ void MainWindow::rigOpen() if(ret==RIG_OK) { m_bRigOpen=true; if(m_poll==0) ui->readFreq->setEnabled(true); + m_CATerror=false; } else { t="Open rig failed"; msgBox(t); m_catEnabled=false; m_bRigOpen=false; + m_CATerror=true; } +// qDebug() << "A" << m_bRigOpen << m_poll << m_CATerror; if(m_bRigOpen) { if(m_poll>0) { - ui->readFreq->setStyleSheet("QPushButton{background-color: red; \ + ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00; \ border-width: 0px; border-radius: 5px;}"); } else { ui->readFreq->setStyleSheet("QPushButton{background-color: orange; \ - border-width: 0px; border-radius: 5px;}"); + border-width: 0px; border-radius: 5px;}"); } - } else { - ui->readFreq->setStyleSheet(""); +} else { +if(m_CATerror) ui->readFreq->setStyleSheet("QPushButton{background-color: red; \ + border-width: 0px; border-radius: 5px;}"); +if(!m_CATerror) ui->readFreq->setStyleSheet(""); } } @@ -2871,18 +2891,19 @@ void MainWindow::on_actionAllow_multiple_instances_triggered(bool checked) void MainWindow::on_pbR2T_clicked() { - int n=g_pWideGraph->QSOfreq(); + int n=g_pWideGraph->rxFreq(); ui->TxFreqSpinBox->setValue(n); } void MainWindow::on_pbT2R_clicked() { - g_pWideGraph->setQSOfreq(m_txFreq); + g_pWideGraph->setRxFreq(m_txFreq); } void MainWindow::on_readFreq_clicked() { + if(m_transmitting) return; m_dontReadFreq=false; double fMHz=rig->getFreq(RIG_VFO_CURR)/1000000.0; if(fMHz<0.0) { @@ -2897,9 +2918,54 @@ void MainWindow::on_readFreq_clicked() if(ndiff!=0) dialFreqChanged2(fMHz); } +void MainWindow::on_pbTxMode_clicked() +{ + if(m_modeTx=="JT9") { + m_modeTx="JT65"; + ui->pbTxMode->setText("Tx JT65 #"); + } else { + m_modeTx="JT9"; + ui->pbTxMode->setText("Tx JT9 @"); + } + g_pWideGraph->setModeTx(m_modeTx); +} -void MainWindow::on_actionLockTxFreq_triggered(bool checked) +void MainWindow::setXIT(int n) +{ + int ret; + int xit=0; + if(m_bRigOpen) { + xit=-1000; + if(n>1000) xit=0; + if(n>2000) xit=1000; + if(n>3000) xit=2000; + if(n>4000) xit=3000; + if(m_bXIT) { + ret=rig->setXit((shortfreq_t)xit,RIG_VFO_TX); +// ret=rig->setSplitFreq(MHz(m_dialFreq),RIG_VFO_A); + + } + if(m_bSplit) ret=rig->setSplitFreq(MHz(m_dialFreq)+xit,RIG_VFO_B); + } + soundOutThread.setXIT(xit); +} + +void MainWindow::setFreq4(int rxFreq, int txFreq) +{ + m_rxFreq=rxFreq; + m_txFreq=txFreq; + ui->RxFreqSpinBox->setValue(m_rxFreq); + ui->TxFreqSpinBox->setValue(m_txFreq); +} + +void MainWindow::on_cbTxLock_clicked(bool checked) { m_lockTxFreq=checked; - g_pWideGraph->m_lockTxFreq=checked; + g_pWideGraph->setLockTxFreq(m_lockTxFreq); + if(m_lockTxFreq) on_pbR2T_clicked(); +} + +void MainWindow::on_actionTx2QSO_triggered(bool checked) +{ + m_tx2QSO=checked; } diff --git a/mainwindow.h b/mainwindow.h index 792230ace..1df7be5e5 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -43,6 +43,8 @@ public slots: void readFromStdout(); void readFromStderr(); void jt9_error(); + void setXIT(int n); + void setFreq4(int rxFreq, int txFreq); protected: virtual void keyPressEvent( QKeyEvent *e ); @@ -72,7 +74,6 @@ private slots: void on_actionOpen_next_in_directory_triggered(); void on_actionDecode_remaining_files_in_directory_triggered(); void on_actionDelete_all_wav_files_in_SaveDir_triggered(); - void on_actionF4_sets_Tx6_triggered(); void on_actionNone_triggered(); void on_actionSave_all_triggered(); void on_actionKeyboard_shortcuts_triggered(); @@ -97,13 +98,10 @@ private slots: void on_logQSOButton_clicked(); void on_actionAFMHot_triggered(); void on_actionBlue_triggered(); - void on_actionJT9_2_triggered(); void on_actionJT9_1_triggered(); - void on_actionJT9_5_triggered(); - void on_actionJT9_30_triggered(); - void on_actionJT9_10_triggered(); + void on_actionJT65_triggered(); + void on_actionJT9_JT65_triggered(); void on_TxFreqSpinBox_valueChanged(int arg1); - void on_actionSave_synced_triggered(); void on_actionSave_decoded_triggered(); void on_actionQuickDecode_triggered(); void on_actionMediumDecode_triggered(); @@ -147,7 +145,6 @@ private slots: void on_rptSpinBox_valueChanged(int n); void on_action_73TxDisable_triggered(bool checked); void on_actionRunaway_Tx_watchdog_triggered(bool checked); - void on_actionTx2QSO_triggered(bool checked); void killFile(); void on_tuneButton_clicked(); void on_actionAllow_multiple_instances_triggered(bool checked); @@ -155,10 +152,11 @@ private slots: void on_pbT2R_clicked(); void acceptQSO2(bool accepted); void on_bandComboBox_activated(int index); - void on_readFreq_clicked(); - - void on_actionLockTxFreq_triggered(bool checked); + void on_pbTxMode_clicked(); + void on_RxFreqSpinBox_valueChanged(int n); + void on_cbTxLock_clicked(bool checked); + void on_actionTx2QSO_triggered(bool checked); private: Ui::MainWindow *ui; @@ -168,15 +166,13 @@ private: qint64 m_msErase; qint64 m_secBandChanged; - qint32 m_nDevIn; - qint32 m_nDevOut; qint32 m_idInt; qint32 m_waterfallAvg; qint32 m_pttMethodIndex; - qint32 m_QSOfreq0; qint32 m_ntx; qint32 m_pttPort; qint32 m_timeout; + qint32 m_rxFreq; qint32 m_txFreq; qint32 m_setftx; qint32 m_ndepth; @@ -184,7 +180,7 @@ private: qint32 m_RxLog; qint32 m_nutc0; qint32 m_nrx; - qint32 m_hsym0; + qint32 m_hsym; qint32 m_paInDevice; qint32 m_paOutDevice; qint32 m_TRperiod; @@ -205,12 +201,12 @@ private: qint32 m_handshakeIndex; qint32 m_ncw; qint32 m_secID; - qint32 m_COMportOpen; - qint32 m_iptt; qint32 m_band; qint32 m_repeatMsg; qint32 m_watchdogLimit; qint32 m_poll; + qint32 m_fMin; + qint32 m_fMax; bool m_monitoring; bool m_transmitting; @@ -221,15 +217,12 @@ private: bool m_auto; bool m_restart; bool m_startAnother; - bool m_saveSynced; bool m_saveDecoded; bool m_saveAll; bool m_widebandDecode; - bool m_kb8rq; bool m_call3Modified; bool m_dataAvailable; bool m_killAll; - bool m_bsynced; bool m_bdecoded; bool m_monitorStartOFF; bool m_pskReporter; @@ -250,7 +243,6 @@ private: bool m_73TxDisable; bool m_sent73; bool m_runaway; - bool m_tx2QSO; bool m_tune; bool m_bRigOpen; bool m_bMultipleOK; @@ -260,6 +252,10 @@ private: bool m_lockTxFreq; bool m_saveTxPower; bool m_saveComments; + bool m_tx2QSO; + bool m_CATerror; + bool m_bSplit; + bool m_bXIT; char m_decoded[80]; @@ -308,6 +304,7 @@ private: QString m_palette; QString m_dateTime; QString m_mode; + QString m_modeTx; QString m_fname; QString m_rpt; QString m_rptSent; @@ -366,13 +363,15 @@ extern int ptt(int nport, int ntx, int* iptt, int* nopen); extern "C" { //----------------------------------------------------- C and Fortran routines -void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, - float* px, float s[], float red[], - float* df3, int* nhsym, int* npts8); +void symspec_(int* k, int* ntrperiod, int* nsps, int* ingain, float* slope, + float* px, float s[], float* df3, int* nhsym, int* npts8); void genjt9_(char* msg, int* ichk, char* msgsent, int itone[], int* itext, int len1, int len2); +void gen65_(char* msg, int* ichk, char* msgsent, int itone[], + int* itext, int len1, int len2); + bool stdmsg_(const char* msg, int len); void azdist_(char* MyGrid, char* HisGrid, double* utch, int* nAz, int* nEl, diff --git a/mainwindow.ui b/mainwindow.ui index 010e2661f..f3509ec69 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 711 - 475 + 760 + 552 @@ -18,7 +18,7 @@ - 711 + 760 475 @@ -35,887 +35,1372 @@ - + - - - QLayout::SetDefaultConstraint + + + 3 - - - - 3 + + 1 + + + + + + 0 + 0 + - - 1 + + + 200 + 100 + - - - - - 0 - 0 - - - - - 200 - 100 - - - - - 500 - 1000 - - - - - Courier New - 10 - - - - QFrame::Panel - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + 500 + 1000 + + + + + Courier New + 10 + + + + QFrame::Panel + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Courier New'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - false - - - false - - - - - - - - 300 - 20 - - - - - 500 - 20 - - - - - - - - - 252 - 252 - 252 - - - - - - - 170 - 170 - 170 - - - - - - - - - 252 - 252 - 252 - - - - - - - 170 - 170 - 170 - - - - - - - - - 170 - 170 - 170 - - - - - - - 170 - 170 - 170 - - - - - - - - true - - - UTC dB DT Freq Dr - - - 5 - - - - - - - - 300 - 20 - - - - - 500 - 20 - - - - - - - - - 252 - 252 - 252 - - - - - - - 170 - 170 - 170 - - - - - - - - - 252 - 252 - 252 - - - - - - - 170 - 170 - 170 - - - - - - - - - 170 - 170 - 170 - - - - - - - 170 - 170 - 170 - - - - - - - - true - - - UTC dB DT Freq Dr - - - 5 - - - - - - - - 0 - 0 - - - - - 200 - 100 - - - - - 500 - 1000 - - - - - Courier New - 10 - - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - - - - - - 500 - 16777215 - - - - - 10 - 50 - false - - - - QSO Frequency - - - Qt::AlignCenter - - - - - - - - 500 - 16777215 - - - - - 10 - 50 - false - - - - Band Activity - - - Qt::AlignCenter - - - - - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - QFrame::Plain - - - Qt::Horizontal - - - - - - - - - - - - 50 - 0 - - - - Enter this QSO in ADIF log - - - Log &QSO - - - - - - - - 50 - 0 - - - - Stop monitoring - - - &Stop - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - - 16777215 - 16777215 - - - - Start monitoring - - - &Monitor - - - - - - - - 50 - 0 - - - - Decode most recent Rx period at QSO Frequency (use shift for all freqs) - - - &Decode - - - - - - - - 50 - 0 - - - - Erase QSO Frequency window. Double-click for both windows - - - &Erase - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - Toggle Tx Enable On/Off - - - E&nable Tx - - - - - - - - 0 - 0 - - - - - 50 - 0 - - - - Set Tx Enable OFF - - - &Halt Tx - - - - - - - Assert PTT and emit a pure tone - - - &Tune - - - - - - - - - QLayout::SetMinimumSize +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> - - - - - 0 - 0 - - - - - 283 - 222 - - - - QFrame::StyledPanel - - - QFrame::Plain - - - 0 - - - + + false + + + false + + + + + + + + 300 + 20 + + + + + 500 + 20 + + + + + + + + + 252 + 252 + 252 + + + + + + + 170 + 170 + 170 + + + + + + + + + 252 + 252 + 252 + + + + + + + 170 + 170 + 170 + + + + + + + + + 170 + 170 + 170 + + + + + + + 170 + 170 + 170 + + + + + + + + true + + + UTC dB DT Freq Dr + + + 5 + + + + + + + + 300 + 20 + + + + + 500 + 20 + + + + + + + + + 252 + 252 + 252 + + + + + + + 170 + 170 + 170 + + + + + + + + + 252 + 252 + 252 + + + + + + + 170 + 170 + 170 + + + + + + + + + 170 + 170 + 170 + + + + + + + 170 + 170 + 170 + + + + + + + + true + + + UTC dB DT Freq Dr + + + 5 + + + + + + + + 0 + 0 + + + + + 200 + 100 + + + + + 500 + 1000 + + + + + Courier New + 10 + + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + + + + + + 500 + 16777215 + + + + + 10 + 50 + false + + + + Rx Frequency + + + Qt::AlignCenter + + + + + + + + 500 + 16777215 + + + + + 10 + 50 + false + + + + Band Activity + + + Qt::AlignCenter + + + + + + + QFrame::Plain + + + Qt::Horizontal + + + + + + + QFrame::Plain + + + Qt::Horizontal + + + + +
+ + + + + + + 50 + 0 + + + + Enter this QSO in ADIF log + + + Log &QSO + + + + + + + + 50 + 0 + + + + Stop monitoring + + + &Stop + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 16777215 + 16777215 + + + + Start monitoring + + + &Monitor + + + + + + + + 50 + 0 + + + + Erase QSO Frequency window. Double-click for both windows + + + &Erase + + + + + + + + 50 + 0 + + + + Decode most recent Rx period at QSO Frequency (use shift for all freqs) + + + &Decode + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Toggle Tx Enable On/Off + + + E&nable Tx + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Set Tx Enable OFF + + + &Halt Tx + + + + + + + Assert PTT and emit a pure tone + + + &Tune + + + + + + + + + + + Select operating band + + + 7 + + + + 2200 m + + + + + 630 m + + + + + 160 m + + + + + 80 m + + + + + 60 m + + + + + 40 m + + + + + 30 m + + + + + 20 m + + + + + 17 m + + + + + 15 m + + + + + 12 m + + + + + 10 m + + + + + 6 m + + + + + 4 m + + + + + 2 m + + + + + Other + + + + + + + + + 15 + 15 + + + + If orange, click to read dial frequency once + + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 158 + 16777215 + + + + + 16 + 50 + false + + + + USB dial frequency + + + 14.078 + + + Qt::AlignCenter + + + + + + + + 105 + 23 + + + + + 105 + 16777215 + + + + Check to Tx in even minutes, uncheck for odd minutes + + + Tx even + + + + + + + + 0 + 0 + + + + + 283 + 222 + + + + QFrame::StyledPanel + + + QFrame::Plain + + + 0 + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 200 + + + + QTabWidget::West + + + QTabWidget::Triangular + + 0 - - 0 - - - - - - 0 - 0 - + + + 1 + + + + 6 - - - 0 - 200 - + + 4 - - QTabWidget::West + + 1 - - QTabWidget::Triangular - - + 0 - - - 1 - - + + 0 + + + + + 6 + + + 5 + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Qt::LeftToRight + + + Tx 1 + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + buttonGroup + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + true + + + buttonGroup + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + buttonGroup + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + + Droid Sans + 50 + false + + + + + + + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Tx 3 + + + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Tx 4 + + + + + + + Queue up the next Tx message + + + Next + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + Right-click to select a macro message + + + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Tx 5 + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + buttonGroup + + + + + + + Switch to this Tx message NOW + + + Now + + + Qt::AlignCenter + + + + + + + + 200 + 0 + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Generate standard messages for minimal QSO + + + Generate Std Msgs + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Tx 6 + + + + + + + + 40 + 16777215 + + + + Switch to this Tx message NOW + + + Tx 2 + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + buttonGroup + + + + + + + + 16 + 0 + + + + + 0 + 20 + + + + + 20 + 16777215 + + + + Send this message in next Tx interval + + + + + + buttonGroup + + + + + + + + 200 + 0 + + + + + 150 + 24 + + + + + 150 + 16777215 + + + + + + + + + + + 2 + + + + 0 + + + 0 + + + 6 - 4 - - - 1 + 2 - 0 - - - 0 + 2 - - - 6 + + + 2 - - 5 - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Qt::LeftToRight - - - Tx 1 - - - - - - - - 16 - 0 - - + + 0 - 20 + 30 - 20 - 16777215 + 16777215 + 30 - - Send this message in next Tx interval - - - - - buttonGroup - - - - - - - - 16 - 0 - - - - - 0 - 20 - - - - - 20 - 16777215 - - - - Send this message in next Tx interval - - - - - - true - - - buttonGroup - - - - - - - - 16 - 0 - - - - - 0 - 20 - - - - - 20 - 16777215 - - - - Send this message in next Tx interval - - - - - - buttonGroup - - - - - - - - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - - - - - Droid Sans - 50 - false - - - - - - - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Tx 3 - - - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Tx 4 - - - - - - - Queue up the next Tx message - - - Next - - - - - - - - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - - - - - - - - - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - - - - Right-click to select a macro message - - - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Tx 5 - - - - - - - - 16 - 0 - - - - - 0 - 20 - - - - - 20 - 16777215 - - - - Send this message in next Tx interval - - - - - - buttonGroup - - - - - - - Switch to this Tx message NOW - - - Now + Calling CQ Qt::AlignCenter - - + + + + Generate a CQ message + + + CQ + + + + + + + Generate message with RRR + + + RRR + + + + + + + Generate message with report + + + dB + + + + + + + + 0 + 30 + + + + + 16777215 + 30 + + + + Answering CQ + + + Qt::AlignCenter + + + + + + + Generate message for replying to a CQ + + + Grid + + + + + + + Generate message with R+report + + + R+dB + + + + + + + Generate message with 73 + + + 73 + + + + + + + + + - 200 + 0 0 @@ -925,766 +1410,773 @@ p, li { white-space: pre-wrap; } 0 - - - 150 - 16777215 - - - - Generate standard messages for minimal QSO - - - Generate Std Msgs + + true - - + + - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - - - - - - - - - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - - - - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Tx 6 - - - - - - - - 40 - 16777215 - - - - Switch to this Tx message NOW - - - Tx 2 - - - - - - - - 16 + 0 0 0 - 20 - - - - - 20 - 16777215 + 26 - Send this message in next Tx interval + Send this standard (generated) message - + Gen msg - - buttonGroup - - - - - - - - 16 - 0 - - - - - 0 - 20 - - - - - 20 - 16777215 - - - - Send this message in next Tx interval - - - - - - buttonGroup - - - - - - - - 200 - 0 - - - - - 150 - 24 - - - - - 150 - 16777215 - + + true - - - - - 2 - - - - 0 - - - 0 - - - - 6 - - - 2 - - - 2 - + - - - 2 + + + + 0 + 0 + - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - Calling CQ - - - Qt::AlignCenter - - - - - - - Generate a CQ message - - - CQ - - - - - - - Generate message with RRR - - - RRR - - - - - - - Generate message with report - - - dB - - - - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - Answering CQ - - - Qt::AlignCenter - - - - - - - Generate message for replying to a CQ - - - Grid - - - - - - - Generate message with R+report - - - R+dB - - - - - - - Generate message with 73 - - - 73 - - - - + + + 150 + 0 + + + - - - - - - 0 - 0 - - - - - 150 - 0 - - - - true - - - - - - - - 0 - 0 - - - - - 0 - 26 - - - - Send this standard (generated) message - - - Gen msg - - - true - - - - - - - - - - - - 0 - 0 - - - - - 150 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 26 - - - - Send this free-text message (max 13 characters) - - - Free msg - - - - + + + + 0 + 0 + + + + + 0 + 26 + + + + Send this free-text message (max 13 characters) + + + Free msg + + - - - - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - - 16777215 - 16777215 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 159 - 175 - 213 - - - - - - - 159 - 175 - 213 - - - - - - - - true - - - DX Grid - - - Qt::AlignCenter - - - 2 - - - - - - - Select operating band - - - 7 - - - - 2200 m - - - - - 630 m - - - - - 160 m - - - - - 80 m - - - - - 60 m - - - - - 40 m - - - - - 30 m - - - - - 20 m - - - - - 17 m - - - - - 15 m - - - - - 12 m - - - - - 10 m - - - - - 6 m - - - - - 4 m - - - - - 2 m - - - - - Other - - - - - - - - 5 - - - - - - 0 - 0 - - - - - 40 - 16777215 - - - - Report - + + - - - - - - 0 - 0 - - - - - 55 - 0 - - - - - 55 - 16777215 - - - - Signal report (dB0 - - - -50 - - - 49 - - - -15 - - - - - - - + + + + + + + + + + 0 + 0 + + + + + 0 + 180 + + + + + 15 + 16777215 + + + + 60 + + + 0 + + + false + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 0 + 180 + + + + + 20 + 180 + + + + Digital gain for audio input + + + -50 + + + 50 + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 159 + 175 + 213 + + + + + + + 159 + 175 + 213 + + + + + + + + true + + + DX Call + + + Qt::AlignCenter + + + 2 + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + 16777215 + 16777215 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 159 + 175 + 213 + + + + + + + 159 + 175 + 213 + + + + + + + + true + + + DX Grid + + + Qt::AlignCenter + + + 2 + + + + + + + false + + + Tx JT9 + + + + + + + + 0 + 0 + + + + + 70 + 27 + + + + + 74 + 16777215 + + + + Callsign of station to be worked + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 70 + 27 + + + + + 74 + 16777215 + + + + Locator of station to be worked + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 113 + 0 + + + + + 105 + 16777215 + + + + Audio Tx frequency + + + Hz + + + Tx + + + 200 + + + 5000 + + + 1500 + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + 16777215 + 23 + + + + true + + + Az + + + Qt::AlignCenter + + + 4 + + + + + + + + 0 + 0 + + + + + 0 + 23 + + + + + 16777215 + 23 + + + + Dist + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 33 + 20 + + + + + + + + + 0 + 0 + + + + + 113 + 20 + + + + Hz + + + Rx + + + 200 + + + 5000 + + + 1500 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 13 + 20 + + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + dB + + + + + + + + 0 + 0 + + + + + 74 + 16777215 + + + + Search for callsign in database + + + &Lookup + + + + + + + + 0 + 0 + + + + + 74 + 16777215 + + + + Add callsign and locator to database + + + Add + + + + + + + 5 + + + QLayout::SetFixedSize + + + - + 0 0 - - - 0 - 30 - - - 158 - 16777215 - - - - - 16 - 50 - false - - - - USB dial frequency - - - 14.078 - - - Qt::AlignCenter - - - - - - - - 105 - 23 - - - - - 105 + 48 16777215 - Check to Tx in even minutes, uncheck for odd minutes + Set Tx frequency to Rx Frequency - Tx even + Tx=Rx - - + + - + 0 0 - - - 0 - 180 - - - 42 - 180 + 48 + 16777215 - dB above one bit in A/D samples + Set Rx frequency to Tx Frequency - - 1 - - - 60.000000000000000 - - - 0.000000000000000 - - - 8 - - - 0.000000000000000 + + Rx=Tx - - + + + + + + + 0 + 0 + + + + + 130 + 60 + + + + + 158 + 60 + + + + + 16 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 2 + + + 0 + + + 01:23:45 + + + Qt::AlignCenter + + + + + + + Lock Tx=Rx + + + + + + + 5 + + + + + + 0 + 0 + + + + Report + + + + + 0 @@ -1693,509 +2185,27 @@ p, li { white-space: pre-wrap; } - 0 - 180 - - - - - 16777215 - 180 - - - - Digital gain for audio input - - - -50 - - - 50 - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - 105 + 55 0 - 105 + 55 16777215 - Audio Tx frequency - - - Hz - - - Tx + + Signal report (dB0 - 500 + -50 - 20000 + 49 - 1500 - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - 5 - - - QLayout::SetFixedSize - - - - - - 0 - 0 - - - - - 48 - 16777215 - - - - Set Tx frequency to Rx Frequency - - - Tx=Rx - - - - - - - - 0 - 0 - - - - - 48 - 16777215 - - - - Set Rx frequency to Tx Frequency - - - Rx=Tx - - - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - dB - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - - 16777215 - 23 - - - - true - - - Az - - - Qt::AlignCenter - - - 4 - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - - 16777215 - 23 - - - - Dist - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 74 - 16777215 - - - - Search for callsign in database - - - &Lookup - - - - - - - - 0 - 0 - - - - - 74 - 16777215 - - - - Add callsign and locator to database - - - Add - - - - - - - - 0 - 0 - - - - - 130 - 60 - - - - - 158 - 60 - - - - - 16 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - 2 - - - 0 - - - 01:23:45 - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 0 - 23 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 159 - 175 - 213 - - - - - - - 159 - 175 - 213 - - - - - - - - true - - - DX Call - - - Qt::AlignCenter - - - 2 - - - - - - - - 0 - 0 - - - - - 70 - 27 - - - - - 74 - 16777215 - - - - Locator of station to be worked - - - - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - - 70 - 27 - - - - - 74 - 16777215 - - - - Callsign of station to be worked - - - - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 2 - 20 - - - - - - - - - 15 - 15 - - - - If orange, click to read dial frequency once - - - + -15 @@ -2210,7 +2220,7 @@ p, li { white-space: pre-wrap; } 0 0 - 711 + 760 21 @@ -2241,8 +2251,6 @@ p, li { white-space: pre-wrap; } - - @@ -2253,7 +2261,6 @@ p, li { white-space: pre-wrap; } - @@ -2287,7 +2294,6 @@ p, li { white-space: pre-wrap; } Save - @@ -2305,7 +2311,8 @@ p, li { white-space: pre-wrap; } Mode - + + @@ -2399,7 +2406,7 @@ p, li { white-space: pre-wrap; } true - false + true Linrad @@ -2410,7 +2417,7 @@ p, li { white-space: pre-wrap; } true - true + false CuteSDR @@ -2620,8 +2627,11 @@ p, li { white-space: pre-wrap; } true + + true + - JT9-1 + JT9 @@ -2740,7 +2750,7 @@ p, li { white-space: pre-wrap; } true - Convert JT9-x to RTTY for logging + Convert mode to RTTY for logging @@ -2812,14 +2822,6 @@ p, li { white-space: pre-wrap; } Runaway Tx watchdog - - - true - - - Tx messages echoed to QSO window - - true @@ -2828,11 +2830,6 @@ p, li { white-space: pre-wrap; } Allow multiple instances - - - Tx frequency always follows Rx frequency - - true @@ -2841,14 +2838,33 @@ p, li { white-space: pre-wrap; } Tx freq locked to Rx freq + + + true + + + JT65 + + + + + true + + + JT9+JT65 + + + + + true + + + Tx messages to Rx Frequency window + + - - QwtThermo - QWidget -
qwt_thermo.h
-
DisplayText QTextBrowser @@ -2859,8 +2875,8 @@ p, li { white-space: pre-wrap; } logQSOButton stopButton monitorButton - DecodeButton EraseButton + DecodeButton autoButton stopTxButton tuneButton @@ -2869,8 +2885,6 @@ p, li { white-space: pre-wrap; } inGain dxCallEntry dxGridEntry - lookupButton - addButton txFirstCheckBox TxFreqSpinBox pbR2T @@ -2898,16 +2912,16 @@ p, li { white-space: pre-wrap; } txb6 decodedTextBrowser decodedTextBrowser2 - pbCallCQ - rbFreeText genMsg - rbGenMsg + pbAnswerCaller + rbFreeText + pbSendRRR + freeTextMsg pbAnswerCQ pbSendReport pbSend73 - pbSendRRR - pbAnswerCaller - freeTextMsg + rbGenMsg + pbCallCQ diff --git a/plotter.cpp b/plotter.cpp index 7168096a0..39f12eb75 100644 --- a/plotter.cpp +++ b/plotter.cpp @@ -15,8 +15,8 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_NoSystemBackground, true); - m_StartFreq = 1000; - m_nSpan=1000; //Units: Hz + m_StartFreq = 0; + m_nSpan=2; //used for FFT bins/pixel m_fSpan=(float)m_nSpan; m_hdivs = HORZ_DIVS; m_FreqUnits = 1; @@ -27,7 +27,7 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor m_ScalePixmap = QPixmap(0,0); m_OverlayPixmap = QPixmap(0,0); m_Size = QSize(0,0); - m_fQSO = 1020; + m_rxFreq = 1020; m_line = 0; m_fSample = 12000; m_nsps=6912; @@ -83,7 +83,7 @@ void CPlotter::paintEvent(QPaintEvent *) // paintEvent() m_paintEventBusy=false; } -void CPlotter::draw(float swide[], float red[], int i0) //draw() +void CPlotter::draw(float swide[], int i0) //draw() { int j,y2; float y; @@ -98,18 +98,18 @@ void CPlotter::draw(float swide[], float red[], int i0) //draw() QPainter painter2D(&m_2DPixmap); painter2D.setPen(Qt::green); - if(m_bJT9Sync) painter2D.setPen(Qt::red); QPoint LineBuf[MAX_SCREENSIZE]; j=0; - int iz=XfromFreq(2000.0); -// for(int i=0; iiz) swide[i]=0; y=0.0; if(swide[i]>0.0) y = 10.0*log10(swide[i]); - int y1 = 5.0*gain*y + 10*m_plotZero; + int y1 = 5.0*gain*y + 10*(m_plotZero-4); if (y1<0) y1=0; if (y1>254) y1=254; if (swide[i]>1.e29) y1=255; @@ -125,7 +125,7 @@ void CPlotter::draw(float swide[], float red[], int i0) //draw() } y2=gain*6.0*log10(sum/m_binsPerPixel) - 10.0; } - if(m_bJT9Sync) y2=3.0*gain*red[i] - 15; + y2 += m_plotZero; if(i==iz-1) painter2D.drawPolyline(LineBuf,j); LineBuf[j].setX(i); LineBuf[j].setY(m_h-(y2+0.8*m_h)); @@ -163,7 +163,7 @@ void CPlotter::DrawOverlay() //DrawOverlay() if(m_OverlayPixmap.isNull()) return; if(m_WaterfallPixmap.isNull()) return; int w = m_WaterfallPixmap.width(); - int x,y,x1,x2,dx; + int x,y,x1,x2; // int nHzDiv[11]={0,50,100,200,200,200,500,500,500,500,500}; float pixperdiv; @@ -180,12 +180,15 @@ void CPlotter::DrawOverlay() //DrawOverlay() double df = m_binsPerPixel*m_fftBinWidth; pixperdiv = m_freqPerDiv/df; y = m_h2 - m_h2/VERT_DIVS; + m_hdivs = w*df/m_freqPerDiv + 0.9999; for( int i=1; i= 0 and x<=m_w) { + painter.setPen(QPen(Qt::white, 1,Qt::DotLine)); + painter.drawLine(x, 0, x , y); + painter.drawLine(x, m_h2-5, x , m_h2); + } } pixperdiv = (float)m_h2 / (float)VERT_DIVS; @@ -258,40 +261,30 @@ void CPlotter::DrawOverlay() //DrawOverlay() } } - x1=XfromFreq(m_fMin); - int bw=9.0*12000.0/m_nsps; - dx=XfromFreq(m_fMin+bw) - x1; + float bw=9.0*12000.0/m_nsps; + if(m_modeTx=="JT65") bw=66.0*11025.0/4096.0; QPen pen0(Qt::green, 3); //Mark Rx Freq with green painter0.setPen(pen0); - x1=XfromFreq(m_fQSO); - x2=x1+dx; + x1=XfromFreq(m_rxFreq); + x2=XfromFreq(m_rxFreq+bw); painter0.drawLine(x1,24,x1,30); painter0.drawLine(x1,28,x2,28); painter0.drawLine(x2,24,x2,30); - QPen pen2(Qt::blue, 3); //Mark the decoding range - painter0.setPen(pen2); - x1=XfromFreq(m_fMin); - if(x1<2) x1=2; - x2=x1+30; -// pen2.setWidth(6); - painter0.drawLine(x1,18,x1,28); - painter0.drawLine(x1,23,x2,23); - painter0.drawLine(x2,23,x2-5,18); - painter0.drawLine(x2,23,x2-5,28); - x2=XfromFreq(m_fMax); - x1=x2-30; -// pen2.setWidth(6); - painter0.drawLine(x2,18,x2,28); - painter0.drawLine(x1,23,x2,23); - painter0.drawLine(x1,23,x1+5,18); - painter0.drawLine(x1,23,x1+5,28); + if(m_mode=="JT9+JT65") { + QPen pen2(Qt::blue, 3); //Mark the JT65 | JT9 divider + painter0.setPen(pen2); + x1=XfromFreq(m_fMin); + if(x1<2) x1=2; + x2=x1+30; + painter0.drawLine(x1,8,x1,28); + } QPen pen1(Qt::red, 3); //Mark Tx freq with red painter0.setPen(pen1); x1=XfromFreq(m_txFreq); - x2=x1+dx; + x2=XfromFreq(m_txFreq+bw); painter0.drawLine(x1,17,x1,21); painter0.drawLine(x1,17,x2,17); painter0.drawLine(x2,17,x2,21); @@ -310,7 +303,7 @@ void CPlotter::MakeFrequencyStrs() //MakeFrequencyStrs int CPlotter::XfromFreq(float f) //XfromFreq() { // float w = m_WaterfallPixmap.width(); - int x = (int) m_w * (f - m_StartFreq)/m_fSpan; + int x = int(m_w * (f - m_StartFreq)/m_fSpan + 0.5); if(x<0 ) return 0; if(x>m_w) return m_w; return x; @@ -318,7 +311,8 @@ int CPlotter::XfromFreq(float f) //XfromFreq() float CPlotter::FreqfromX(int x) //FreqfromX() { - return float(1000.0 + x*m_binsPerPixel*m_fftBinWidth); +// return float(1000.0 + x*m_binsPerPixel*m_fftBinWidth); + return float(x*m_binsPerPixel*m_fftBinWidth); } void CPlotter::SetRunningState(bool running) //SetRunningState() @@ -362,10 +356,9 @@ int CPlotter::plotWidth(){return m_WaterfallPixmap.width();} void CPlotter::UpdateOverlay() {DrawOverlay();} void CPlotter::setDataFromDisk(bool b) {m_dataFromDisk=b;} -void CPlotter::setRxRange(int fMin, int fMax) +void CPlotter::setRxRange(int fMin) { m_fMin=fMin; - m_fMax=fMax; } void CPlotter::setBinsPerPixel(int n) // set nbpp @@ -380,43 +373,39 @@ int CPlotter::binsPerPixel() // get nbpp return m_binsPerPixel; } -void CPlotter::setFQSO(int x, bool bf) //setFQSO() +void CPlotter::setRxFreq(int x, bool bf) //setRxFreq() { if(bf) { - m_fQSO=x; // x is freq in Hz - m_xClick=XfromFreq(m_fQSO); + m_rxFreq=x; // x is freq in Hz + m_xClick=XfromFreq(m_rxFreq); } else { if(x<0) x=0; // x is pixel number if(x>m_Size.width()) x=m_Size.width(); - m_fQSO = int(FreqfromX(x)+0.5); + m_rxFreq=int(FreqfromX(x)+0.5); m_xClick=x; } + emit setFreq1(m_rxFreq,m_txFreq); DrawOverlay(); update(); } -void CPlotter::setFcal(int n) //setFcal() -{ - m_fCal=n; -} - -int CPlotter::fQSO() {return m_fQSO;} //get fQSO +int CPlotter::rxFreq() {return m_rxFreq;} //get rxFreq void CPlotter::mousePressEvent(QMouseEvent *event) //mousePressEvent { int x=event->x(); - setFQSO(x,false); // Wideband waterfall + setRxFreq(x,false); // Wideband waterfall bool ctrl = (event->modifiers() & Qt::ControlModifier); int n=1; if(ctrl) n+=100; emit freezeDecode1(n); - if(ctrl) setTxFreq(m_fQSO); + if(ctrl or m_lockTxFreq) setTxFreq(m_rxFreq); } void CPlotter::mouseDoubleClickEvent(QMouseEvent *event) //mouse2click { // int x=event->x(); -// setFQSO(x,false); +// setRxFreq(x,false); bool ctrl = (event->modifiers() & Qt::ControlModifier); int n=2; if(ctrl) n+=100; @@ -536,6 +525,22 @@ void CPlotter::setNsps(int ntrperiod, int nsps) void CPlotter::setTxFreq(int n) //setTol() { m_txFreq=n; + emit setFreq1(m_rxFreq,m_txFreq); DrawOverlay(); update(); } + +void CPlotter::setMode(QString mode) +{ + m_mode=mode; +} + +void CPlotter::setModeTx(QString modeTx) +{ + m_modeTx=modeTx; +} + +int CPlotter::getFmax() +{ + return m_fMax; +} diff --git a/plotter.h b/plotter.h index 077853ea8..aa4470230 100644 --- a/plotter.h +++ b/plotter.h @@ -30,19 +30,20 @@ public: QSize minimumSizeHint() const; QSize sizeHint() const; QColor m_ColorTbl[256]; + bool m_bCurrent; bool m_bCumulative; - bool m_bJT9Sync; - int m_plotZero; - int m_plotGain; + bool m_lockTxFreq; + float m_fSpan; + + qint32 m_plotZero; + qint32 m_plotGain; qint32 m_nSpan; qint32 m_binsPerPixel; - qint32 m_fQSO; - qint32 m_fCal; qint32 m_w; - void draw(float sw[], float red[], int i0); //Update the waterfall + void draw(float sw[], int i0); //Update the waterfall void SetRunningState(bool running); void setPlotZero(int plotZero); int getPlotZero(); @@ -54,22 +55,25 @@ public: void setNSpan(int n); void UpdateOverlay(); void setDataFromDisk(bool b); - void setRxRange(int fMin, int fMax); + void setRxRange(int fMin); void setBinsPerPixel(int n); int binsPerPixel(); - void setFQSO(int n, bool bf); - void setFcal(int n); + void setRxFreq(int n, bool bf); void DrawOverlay(); - int fQSO(); + int rxFreq(); void setPalette(QString palette); void setFsample(int n); void setNsps(int ntrperiod, int nsps); void setTxFreq(int n); + void setMode(QString mode); + void setModeTx(QString modeTx); double fGreen(); void SetPercent2DScreen(int percent){m_Percent2DScreen=percent;} + int getFmax(); signals: void freezeDecode1(int n); + void setFreq1(int rxFreq, int txFreq); protected: //re-implemented widget event handlers @@ -92,16 +96,21 @@ private: QSize m_Size; QString m_Str; QString m_HDivText[483]; + QString m_mode; + QString m_modeTx; + bool m_Running; bool m_paintEventBusy; + bool m_dataFromDisk; + double m_fGreen; double m_fftBinWidth; + qint64 m_StartFreq; + qint32 m_dBStepSize; qint32 m_FreqUnits; qint32 m_hdivs; - bool m_dataFromDisk; - char m_sutc[6]; qint32 m_line; qint32 m_fSample; qint32 m_i0; @@ -113,10 +122,13 @@ private: qint32 m_h1; qint32 m_h2; qint32 m_TRperiod; + qint32 m_rxFreq; qint32 m_txFreq; qint32 m_fMin; qint32 m_fMax; + char m_sutc[6]; + private slots: void mousePressEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); diff --git a/psk_reporter.cpp b/psk_reporter.cpp index 9d2ec05e7..6856d174f 100644 --- a/psk_reporter.cpp +++ b/psk_reporter.cpp @@ -39,10 +39,10 @@ PSK_Reporter::PSK_Reporter(QObject *parent) : void PSK_Reporter::setLocalStation(QString call, QString gridSquare, QString programInfo) { - m_rxCall = call; - m_rxGrid = gridSquare; - m_progId = programInfo; - reportTimer->start(5*60*1000); // 5 minutes; + m_rxCall = call; + m_rxGrid = gridSquare; + m_progId = programInfo; + reportTimer->start(5*60*1000); // 5 minutes; } void PSK_Reporter::addRemoteStation(QString call, QString grid, QString freq, QString mode, QString snr, QString time ) @@ -99,15 +99,6 @@ void PSK_Reporter::sendReport() // Get IP address for pskreporter.info and send report via UDP QHostInfo info = QHostInfo::fromName("report.pskreporter.info"); m_udpSocket->writeDatagram(report,info.addresses().at(0),4739); - - /* - qDebug() << header_h; - qDebug() << m_rxInfoDescriptor_h; - qDebug() << m_txInfoDescriptor_h; - qDebug() << rxInfoData_h; - qDebug() << txInfoData_h; - qDebug() << report.toHex(); - */ } diff --git a/rigclass.cpp b/rigclass.cpp index 4e7f718ce..a4c06850a 100644 --- a/rigclass.cpp +++ b/rigclass.cpp @@ -7,7 +7,7 @@ * Hamlib C++ interface is a frontend implementing wrapper functions. */ -/* +/** * * Hamlib C++ bindings - main file * Copyright (c) 2001-2003 by Stephane Fillod @@ -36,7 +36,7 @@ #include #include "rigclass.h" #include - +#include static int hamlibpp_freq_event(RIG *rig, vfo_t vfo, freq_t freq, rig_ptr_t arg); @@ -78,9 +78,16 @@ int Rig::init(rig_model_t rig_model) } int Rig::open(int n) { -#ifdef WIN32 // Ham radio Deluxe only on Windows - m_hrd=(n==9999); - if(m_hrd) { + m_hrd=false; + m_cmndr=false; + if(n<9900) { + if(n==-99999) return -1; //Silence compiler warning + return rig_open(theRig); + } + +#ifdef WIN32 // Ham radio Deluxe or Commander (Windows only) + if(n==9999) { + m_hrd=true; bool bConnect=false; bConnect = HRDInterfaceConnect(L"localhost",7809); if(bConnect) { @@ -92,12 +99,30 @@ int Rig::open(int n) { m_hrd=false; return -1; } - } else -#endif - { - if(n==-99999) return -1; //Silence compiler warning - return rig_open(theRig); } + if(n==9998) { + socket->connectToHost(QHostAddress::LocalHost, 52002); + if(!socket->waitForConnected(1000)) { + return -1; + } + QString t; +// qint32 nkHz=14076; +// t.sprintf("CmdSetFreq%5d",nkHz); + t="CmdGetFreq"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + socket->write(buf); + socket->waitForReadyRead(1000); + QByteArray reply=socket->read(128); + if(reply.indexOf("")==0) { +// qDebug() << "Freq:" << reply; +// qDebug() << "Connected to Commander"; + m_cmndr=true; + return 0; + } + } +#endif + return -1; } int Rig::close(void) { @@ -105,6 +130,9 @@ int Rig::close(void) { if(m_hrd) { HRDInterfaceDisconnect(); return 0; + } else if(m_cmndr) { + socket->close(); + return 0; } else #endif { @@ -132,13 +160,70 @@ int Rig::setFreq(freq_t freq, vfo_t vfo) { } else { return -1; } + } else if(m_cmndr) { + QString t; + qint32 nkHz=int(0.001*freq); + t.sprintf("CmdSetFreq%5d",nkHz); + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + socket->write(buf); + socket->waitForBytesWritten(1000); + return 0; } else #endif - { + { return rig_set_freq(theRig, vfo, freq); } } +int Rig::setXit(shortfreq_t xit, vfo_t vfo) +{ + return rig_set_xit(theRig, vfo, xit); +} + +int Rig::setVFO(vfo_t vfo) +{ + return rig_set_vfo(theRig, vfo); +} + +vfo_t Rig::getVFO() +{ + vfo_t vfo; + rig_get_vfo(theRig, &vfo); + return vfo; +} + +int Rig::setSplitFreq(freq_t tx_freq, vfo_t vfo) { +#ifdef WIN32 // Ham Radio Deluxe only on Windows + if(m_hrd) { + QString t; + int nhz=(int)tx_freq; + t=m_context + "Set Frequency-Hz " + QString::number(nhz); + const wchar_t* cmnd = (const wchar_t*) t.utf16(); + const wchar_t* result=HRDInterfaceSendMessage(cmnd); + QString t2=QString::fromWCharArray (result,-1); + HRDInterfaceFreeString(result); + if(t2=="OK") { + return 0; + } else { + return -1; + } + } else if(m_cmndr) { + QString t; + qint32 nkHz=int(0.001*tx_freq); + t.sprintf("CmdSetTxFreq%5d",nkHz); + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + socket->write(buf); + socket->waitForBytesWritten(1000); + return 0; + } else +#endif + { + return rig_set_split_freq(theRig, vfo, tx_freq); + } +} + freq_t Rig::getFreq(vfo_t vfo) { freq_t freq; @@ -150,10 +235,29 @@ freq_t Rig::getFreq(vfo_t vfo) HRDInterfaceFreeString(freqString); freq=t2.toDouble(); return freq; + } else if(m_cmndr) { + QString t; + t="CmdGetFreq"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + socket->write(buf); + socket->waitForReadyRead(1000); + QByteArray reply=socket->read(128); + QString t2(reply); + if(t2.indexOf(""); + t2=t2.mid(i1+1).replace(",",""); + freq=1000.0*t2.toDouble(); + return freq; + } else { + return -1.0; + } } else #endif - { - rig_get_freq(theRig, vfo, &freq); + { + int iret=rig_get_freq(theRig, vfo, &freq); +// iret should be 0. Negative values mean rig_get_freq() failed. + if(iret<0) freq=-1.0; return freq; } } @@ -168,18 +272,6 @@ rmode_t Rig::getMode(pbwidth_t& width, vfo_t vfo) { return mode; } -int Rig::setVFO(vfo_t vfo) -{ - return rig_set_vfo(theRig, vfo); -} - -vfo_t Rig::getVFO() -{ - vfo_t vfo; - rig_get_vfo(theRig, &vfo); - return vfo; -} - int Rig::setPTT(ptt_t ptt, vfo_t vfo) { #ifdef WIN32 // Ham Radio Deluxe only on Windows @@ -201,6 +293,16 @@ int Rig::setPTT(ptt_t ptt, vfo_t vfo) } else { return -1; } + } else if(m_cmndr) { + QString t; + if(ptt==0) t="CmdRX"; + if(ptt>0) t="CmdTX"; + QByteArray ba = t.toLocal8Bit(); + const char* buf=ba.data(); + socket->write(buf); + socket->waitForBytesWritten(1000); +// qDebug() << ptt << buf; + return 0; } else #endif { diff --git a/rigclass.h b/rigclass.h index 6a170721a..9c933e715 100644 --- a/rigclass.h +++ b/rigclass.h @@ -25,15 +25,18 @@ #include #include #include +#include + +extern QTcpSocket* socket; class BACKEND_IMPEXP Rig { private: RIG* theRig; // Global ref. to the rig -#ifdef WIN32 // Ham Radio Deluxe only on Windows bool m_hrd; -#endif + bool m_cmndr; QString m_context; + protected: public: Rig(); @@ -59,7 +62,8 @@ public: rmode_t getMode(pbwidth_t&, vfo_t vfo = RIG_VFO_CURR); int setVFO(vfo_t); vfo_t getVFO(); - + int setXit(shortfreq_t xit, vfo_t vfo); + int setSplitFreq(freq_t tx_freq, vfo_t vfo = RIG_VFO_CURR); int setPTT (ptt_t ptt, vfo_t vfo = RIG_VFO_CURR); ptt_t getPTT (vfo_t vfo = RIG_VFO_CURR); diff --git a/soundin.cpp b/soundin.cpp index 3cfd9860e..332e5d371 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -2,7 +2,8 @@ #include #define FRAMES_PER_BUFFER 1024 -#define NSMAX 1365 +//#define NSMAX 1365 +#define NSMAX 6827 #define NTMAX 120 extern "C" { @@ -10,7 +11,7 @@ extern "C" { extern struct { float ss[184*NSMAX]; //This is "common/jt9com/..." in fortran float savg[NSMAX]; - float c0[2*NTMAX*1500]; +// float c0[2*NTMAX*1500]; short int d2[NTMAX*12000]; int nutc; //UTC as integer, HHMM int ndiskdat; //1 ==> data read from *.wav file @@ -26,8 +27,8 @@ extern struct { int nsave; int nagain; int ndepth; - int nrxlog; - int nfsample; + int ntxmode; + int nmode; char datetime[20]; } jt9com_; } @@ -60,7 +61,7 @@ extern "C" int a2dCallback( const void *inputBuffer, void *outputBuffer, udata->ncall++; if( (statusFlags&paInputOverflow) != 0) { - qDebug() << "Input Overflow"; + qDebug() << "Input Overflow in a2dCallback"; } if(udata->bzero) { //Start of a new Rx sequence udata->kin=0; //Reset buffer pointer diff --git a/soundout.cpp b/soundout.cpp index 1766084a4..05daf6514 100644 --- a/soundout.cpp +++ b/soundout.cpp @@ -7,7 +7,7 @@ extern "C" { } extern float gran(); //Noise generator (for tests only) -extern int itone[85]; //Tx audio tones for 85 symbols +extern int itone[126]; //Audio tones for all Tx symbols extern int icw[250]; //Dits for CW ID extern int outBufSize; extern bool btxok; @@ -17,10 +17,12 @@ extern double outputLatency; typedef struct //Parameters sent to or received from callback function { double txsnrdb; - int nsps; + double dnsps; int ntrperiod; int ntxfreq; + int xit; int ncall; + int nsym; bool txMute; bool bRestart; bool btune; @@ -45,6 +47,7 @@ extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer, static double fac; static double amp; static int ic=0,j=0; + static int isym0=-999; static short int i2; int isym,nspd; @@ -58,7 +61,7 @@ extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer, udata->bRestart=false; srand(mstr); //Initialize random seed } - isym=ic/(4*udata->nsps); //Actual fsample=48000 + isym=ic/(4.0*udata->dnsps); //Actual fsample=48000 if(udata->btune) isym=0; //If tuning, send pure tone if(udata->txsnrdb < 0.0) { snr=pow(10.0,0.05*(udata->txsnrdb-6.0)); @@ -66,14 +69,15 @@ extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer, if(snr>1.0) fac=3000.0/snr; } - if(isym>=85 and icw[0]>0) { //Output the CW ID - freq=udata->ntxfreq; + if(isym>=udata->nsym and icw[0]>0) { //Output the CW ID + freq=udata->ntxfreq - udata->xit; dphi=twopi*freq/48000.0; + // float wpm=20.0; // int nspd=1.2*48000.0/wpm; // nspd=3072; //18.75 WPM nspd=2048 + 512; //22.5 WPM - int ic0=85*4*udata->nsps; + int ic0=udata->nsym*4*udata->dnsps; for(uint i=0 ; itwopi) phi -= twopi; @@ -99,17 +103,22 @@ extern "C" int d2aCallback(const void *inputBuffer, void *outputBuffer, return paContinue; } - baud=12000.0/udata->nsps; - freq=udata->ntxfreq + itone[isym]*baud; - dphi=twopi*freq/48000.0; + baud=12000.0/udata->dnsps; amp=32767.0; - int i0=84.983*4.0*udata->nsps; - int i1=85*4*udata->nsps; + int i0=(udata->nsym-0.017)*4.0*udata->dnsps; + int i1=udata->nsym*4.0*udata->dnsps; if(udata->btune) { //If tuning, no ramp down - i0=999*udata->nsps; + i0=999*udata->dnsps; i1=i0; } for(uint i=0 ; idnsps); //Actual fsample=48000 + if(udata->btune) isym=0; //If tuning, send pure tone + if(isym!=isym0) { + freq=udata->ntxfreq + itone[isym]*baud - udata->xit; + dphi=twopi*freq/48000.0; + isym0=isym; + } phi += dphi; if(phi>twopi) phi -= twopi; if(ic>i0) amp=0.98*amp; @@ -160,9 +169,15 @@ void SoundOutThread::run() } udata.txsnrdb=99.0; - udata.nsps=m_nsps; + udata.dnsps=m_nsps; + udata.nsym=85; + if(m_modeTx=="JT65") { + udata.dnsps=4096.0*12000.0/11025.0; + udata.nsym=126; + } udata.ntrperiod=m_TRperiod; udata.ntxfreq=m_txFreq; + udata.xit=m_xit; udata.ncall=0; udata.txMute=m_txMute; udata.bRestart=true; @@ -193,7 +208,12 @@ void SoundOutThread::run() if (qe) break; udata.txsnrdb=m_txsnrdb; - udata.nsps=m_nsps; + udata.dnsps=m_nsps; + udata.nsym=85; + if(m_modeTx=="JT65") { + udata.dnsps=4096.0*12000.0/11025.0; + udata.nsym=126; + } udata.ntrperiod=m_TRperiod; udata.ntxfreq=m_txFreq; udata.txMute=m_txMute; @@ -227,6 +247,10 @@ void SoundOutThread::setTxFreq(int n) m_txFreq=n; } +void SoundOutThread::setXIT(int n) +{ + m_xit=n; +} void SoundOutThread::setTxSNR(double snr) { diff --git a/soundout.h b/soundout.h index 3405b1370..a289afc99 100644 --- a/soundout.h +++ b/soundout.h @@ -27,19 +27,24 @@ public: void setOutputDevice(qint32 n); void setPeriod(int ntrperiod, int nsps); void setTxFreq(int n); + void setXIT(int n); void setTxSNR(double snr); void setTune(bool b); double samFacOut(); bool quitExecution; //If true, thread exits gracefully + QString m_modeTx; // Private members private: double m_txsnrdb; //if < 0, add noise to Tx audio double m_SamFacOut; //(Output sample rate)/48000.0 + qint32 m_nDevOut; //Output device number qint32 m_TRperiod; //T/R period (s) qint32 m_nsps; //Samples per symbol (at 12000 Hz) qint32 m_txFreq; + qint32 m_xit; + bool m_txOK; //Enable Tx audio bool m_txMute; //Mute temporarily bool m_tune; diff --git a/widegraph.cpp b/widegraph.cpp index 3deed3a35..97fc5cb35 100644 --- a/widegraph.cpp +++ b/widegraph.cpp @@ -18,7 +18,10 @@ WideGraph::WideGraph(QWidget *parent) : connect(ui->widePlot, SIGNAL(freezeDecode1(int)),this, SLOT(wideFreezeDecode(int))); - m_fMin=1000; + connect(ui->widePlot, SIGNAL(setFreq1(int,int)),this, + SLOT(setFreq2(int,int))); + + m_fMin=3000; ui->fMinSpinBox->setValue(m_fMin); //Restore user's settings @@ -39,15 +42,13 @@ WideGraph::WideGraph(QWidget *parent) : m_waterfallAvg = settings.value("WaterfallAvg",5).toInt(); ui->waterfallAvgSpinBox->setValue(m_waterfallAvg); ui->widePlot->m_bCurrent=settings.value("Current",false).toBool(); - ui->widePlot->m_bCumulative=settings.value("Cumulative",false).toBool(); - ui->widePlot->m_bJT9Sync=settings.value("JT9Sync",true).toBool(); + ui->widePlot->m_bCumulative=settings.value("Cumulative",true).toBool(); if(ui->widePlot->m_bCurrent) ui->spec2dComboBox->setCurrentIndex(0); if(ui->widePlot->m_bCumulative) ui->spec2dComboBox->setCurrentIndex(1); - if(ui->widePlot->m_bJT9Sync) ui->spec2dComboBox->setCurrentIndex(2); int nbpp=settings.value("BinsPerPixel",2).toInt(); ui->widePlot->setBinsPerPixel(nbpp); - m_qsoFreq=settings.value("QSOfreq",1500).toInt(); - ui->widePlot->setFQSO(m_qsoFreq,true); + m_slope=settings.value("Slope",0.0).toDouble(); + ui->slopeSpinBox->setValue(m_slope); settings.endGroup(); } @@ -72,18 +73,16 @@ void WideGraph::saveSettings() settings.setValue("WaterfallAvg",ui->waterfallAvgSpinBox->value()); settings.setValue("Current",ui->widePlot->m_bCurrent); settings.setValue("Cumulative",ui->widePlot->m_bCumulative); - settings.setValue("JT9Sync",ui->widePlot->m_bJT9Sync); settings.setValue("BinsPerPixel",ui->widePlot->binsPerPixel()); - settings.setValue("QSOfreq",ui->widePlot->fQSO()); + settings.setValue("Slope",m_slope); settings.endGroup(); } -void WideGraph::dataSink2(float s[], float red[], float df3, int ihsym, +void WideGraph::dataSink2(float s[], float df3, int ihsym, int ndiskdata) { static float splot[NSMAX]; static float swide[2048]; - static float rwide[2048]; int nbpp = ui->widePlot->binsPerPixel(); static int n=0; @@ -105,18 +104,14 @@ void WideGraph::dataSink2(float s[], float red[], float df3, int ihsym, // int w=ui->widePlot->plotWidth(); int i0=-1; //### int i=i0; - int jz=1000.0/df3; + int jz=5000.0/(nbpp*df3); for (int j=0; jwidePlot->draw(swide,rwide,i0); + ui->widePlot->draw(swide,i0); } } @@ -172,16 +167,16 @@ void WideGraph::keyPressEvent(QKeyEvent *e) } } -void WideGraph::setQSOfreq(int n) +void WideGraph::setRxFreq(int n) { - m_qsoFreq=n; - ui->widePlot->setFQSO(m_qsoFreq,true); - if(m_lockTxFreq) setTxFreq(m_qsoFreq); + m_rxFreq=n; + ui->widePlot->setRxFreq(m_rxFreq,true); + if(m_lockTxFreq) setTxFreq(m_rxFreq); } -int WideGraph::QSOfreq() +int WideGraph::rxFreq() { - return ui->widePlot->fQSO(); + return ui->widePlot->rxFreq(); } int WideGraph::nSpan() @@ -204,9 +199,9 @@ void WideGraph::wideFreezeDecode(int n) emit freezeDecode2(n); } -void WideGraph::setRxRange(int fMin, int fMax) +void WideGraph::setRxRange(int fMin) { - ui->widePlot->setRxRange(fMin,fMax); + ui->widePlot->setRxRange(fMin); ui->widePlot->DrawOverlay(); ui->widePlot->update(); } @@ -218,19 +213,16 @@ int WideGraph::getFmin() int WideGraph::getFmax() { - return m_fMax; + int n=ui->widePlot->getFmax(); + if(n>5000) n=5000; + return n; } -void WideGraph::setfMax(int n) +void WideGraph::setFmin(int n) { - m_fMax = n; - setRxRange(m_fMin,m_fMax); -} - -void WideGraph::setFcal(int n) -{ - m_fCal=n; - ui->widePlot->setFcal(n); + m_fMin = n; + ui->fMinSpinBox->setValue(n); + setRxRange(m_fMin); } void WideGraph::setPalette(QString palette) @@ -252,28 +244,65 @@ void WideGraph::setPeriod(int ntrperiod, int nsps) void WideGraph::setTxFreq(int n) { + emit setXIT2(n); ui->widePlot->setTxFreq(n); } +void WideGraph::setMode(QString mode) +{ + m_mode=mode; + ui->fMinSpinBox->setEnabled(m_mode=="JT9+JT65"); + ui->widePlot->setMode(mode); + ui->widePlot->DrawOverlay(); + ui->widePlot->update(); +} + +void WideGraph::setModeTx(QString modeTx) +{ + m_modeTx=modeTx; + ui->widePlot->setModeTx(modeTx); + ui->widePlot->DrawOverlay(); + ui->widePlot->update(); +} + void WideGraph::on_spec2dComboBox_currentIndexChanged(const QString &arg1) { ui->widePlot->m_bCurrent=false; ui->widePlot->m_bCumulative=false; - ui->widePlot->m_bJT9Sync=false; if(arg1=="Current") ui->widePlot->m_bCurrent=true; if(arg1=="Cumulative") ui->widePlot->m_bCumulative=true; - if(arg1=="JT9 Sync") ui->widePlot->m_bJT9Sync=true; } void WideGraph::on_fMinSpinBox_valueChanged(int n) { m_fMin=n; - setRxRange(m_fMin,m_fMax); + setRxRange(m_fMin); } -void WideGraph::on_fMaxSpinBox_valueChanged(int n) +void WideGraph::on_slopeSpinBox_valueChanged(double d) { - m_fMax=n; - setRxRange(m_fMin,m_fMax); + m_slope=d; } +void WideGraph::setSlope(double d) +{ + m_slope=d; + ui->slopeSpinBox->setValue(d); +} + +void WideGraph::setLockTxFreq(bool b) +{ + m_lockTxFreq=b; + ui->widePlot->m_lockTxFreq=b; +} +double WideGraph::getSlope() +{ + return m_slope; +} + +void WideGraph::setFreq2(int rxFreq, int txFreq) +{ + m_rxFreq=rxFreq; + m_txFreq=txFreq; + emit setFreq3(rxFreq,txFreq); +} diff --git a/widegraph.h b/widegraph.h index 0298c8741..5e626a602 100644 --- a/widegraph.h +++ b/widegraph.h @@ -14,34 +14,40 @@ public: explicit WideGraph(QWidget *parent = 0); ~WideGraph(); - void dataSink2(float s[], float red[], float df3, int ihsym, - int ndiskdata); - void setQSOfreq(int n); - int QSOfreq(); + void dataSink2(float s[], float df3, int ihsym, int ndiskdata); + void setRxFreq(int n); + int rxFreq(); int nSpan(); int nStartFreq(); int getFmin(); int getFmax(); float fSpan(); void saveSettings(); - void setRxRange(int fMin, int fMax); - void setfMax(int n); - void setFcal(int n); + void setRxRange(int fMin); + void setFmin(int n); void setPalette(QString palette); void setFsample(int n); void setPeriod(int ntrperiod, int nsps); void setTxFreq(int n); + void setMode(QString mode); + void setModeTx(QString modeTx); + void setSlope(double d); + void setLockTxFreq(bool b); + double getSlope(); double fGreen(); - qint32 m_qsoFreq; - bool m_lockTxFreq; + qint32 m_rxFreq; + qint32 m_txFreq; signals: void freezeDecode2(int n); void f11f12(int n); + void setXIT2(int n); + void setFreq3(int rxFreq, int txFreq); public slots: void wideFreezeDecode(int n); + void setFreq2(int rxFreq, int txFreq); protected: virtual void keyPressEvent( QKeyEvent *e ); @@ -53,11 +59,12 @@ private slots: void on_gainSpinBox_valueChanged(int arg1); void on_spec2dComboBox_currentIndexChanged(const QString &arg1); void on_fMinSpinBox_valueChanged(int n); - void on_fMaxSpinBox_valueChanged(int n); + void on_slopeSpinBox_valueChanged(double d); private: + double m_slope; + qint32 m_waterfallAvg; - qint32 m_fCal; qint32 m_fSample; qint32 m_TRperiod; qint32 m_nsps; @@ -65,6 +72,11 @@ private: qint32 m_fMin; qint32 m_fMax; + bool m_lockTxFreq; + + QString m_mode; + QString m_modeTx; + Ui::WideGraph *ui; }; diff --git a/widegraph.ui b/widegraph.ui index 70f7b0aa8..3a5cf775e 100644 --- a/widegraph.ui +++ b/widegraph.ui @@ -6,7 +6,7 @@ 0 0 - 712 + 799 326 @@ -68,25 +68,6 @@
- - - - - 16777215 - 25 - - - - true - - - FFT Bins/Pixel - - - 2 - - - @@ -97,7 +78,7 @@ - 40 + 110 0 @@ -113,6 +94,9 @@ + + Bins/Pixel + 1 @@ -143,25 +127,6 @@ - - - - - 16777215 - 25 - - - - true - - - N Avg - - - 2 - - - @@ -172,7 +137,7 @@ - 0 + 80 0 @@ -185,6 +150,9 @@ Number of FFTs averaged (controls waterfall scrolling rate) + + N Avg + 1 @@ -210,26 +178,13 @@ - - + + - 16777215 - 25 + 80 + 0 - - true - - - Gain - - - 2 - - - - - 38 @@ -239,6 +194,9 @@ Scaling (dB) applied to spectra before plotting + + Gain + -20 @@ -264,26 +222,13 @@ - - + + - 16777215 - 25 + 80 + 0 - - true - - - Zero - - - 2 - - - - - 38 @@ -293,6 +238,12 @@ Constant offset applied to waterfall data + + + + + Zero + -100 @@ -301,6 +252,31 @@ + + + + + 60 + 0 + + + + Slope + + + 1 + + + -2.000000000000000 + + + 2.000000000000000 + + + 0.100000000000000 + + + @@ -317,25 +293,6 @@ - - - - - 16777215 - 25 - - - - true - - - f Min - - - 2 - - - @@ -344,17 +301,32 @@ 0 + + + 110 + 0 + + - Minimum frequency for wideband decodes + Decode JT65 below this frequency, JT9 above + + + JT9 + + + JT65 - 1000 + 0 - 2000 + 5000 - 50 + 100 + + + 3000 @@ -374,66 +346,6 @@ - - - - - 16777215 - 25 - - - - true - - - f Max - - - 2 - - - - - - - - 0 - 0 - - - - Maximum frequency for wideband decodes - - - 1000 - - - 2000 - - - 50 - - - 2000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 8 - 20 - - - - @@ -452,11 +364,6 @@ Cumulative - - - JT9 Sync - - diff --git a/wsjtx.iss b/wsjtx.iss index 7f8a671f0..654ddcfd4 100644 --- a/wsjtx.iss +++ b/wsjtx.iss @@ -1,26 +1,29 @@ [Setup] AppName=wsjtx -AppVerName=wsjtx Version 1.0.0 r3323 +AppVerName=wsjtx Version 1.0.0 r3461 AppCopyright=Copyright (C) 2001-2013 by Joe Taylor, K1JT -DefaultDirName=c:\wsjtx -DefaultGroupName=wsjtx +DefaultDirName=c:\wsjtx2 +DefaultGroupName=wsjtx2 [Files] -Source: "c:\Users\joe\wsjt\wsjtx_install\wsjtx.exe"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx_install\jt9.exe"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx\lib\jt9code.exe"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx_install\rigctl.exe"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx_install\wsjt.ico"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx_install\afmhot.dat"; DestDir: "{app}"; -Source: "c:\Users\joe\wsjt\wsjtx_install\blue.dat"; DestDir: "{app}"; -Source: "c:\Users\joe\wsjt\wsjtx_install\CALL3.TXT"; DestDir: "{app}"; Flags: onlyifdoesntexist -Source: "c:\Users\joe\wsjt\QtSupport\*.dll"; DestDir: "{app}"; -Source: "c:\Users\joe\wsjt\wsjtx\shortcuts.txt"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx\mouse_commands.txt"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide.pdf"; DestDir: "{app}" -Source: "c:\Users\joe\wsjt\wsjtx_install\save\Samples\130418_1742.wav"; DestDir: "{app}\save\Samples"; +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\wsjtx.exe"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\jt9.exe"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx\lib\jt9code.exe"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\rigctl.exe"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\kvasd.exe"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\wsjt.ico"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\afmhot.dat"; DestDir: "{app}"; +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\blue.dat"; DestDir: "{app}"; +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\CALL3.TXT"; DestDir: "{app}"; Flags: onlyifdoesntexist +Source: "c:\Users\joe\wsjt\QtSupport\*.dll"; DestDir: "{app}"; +Source: "c:\Users\joe\wsjt_k1jt\wsjtx\shortcuts.txt"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx\mouse_commands.txt"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt\wsjtx\WSJT-X_Users_Guide.pdf"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx\WSJT-X_1.1_Quick_Start.pdf"; DestDir: "{app}" +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\save\Samples\130418_1742.wav"; DestDir: "{app}\save\Samples"; +Source: "c:\Users\joe\wsjt_k1jt\wsjtx_install\save\Samples\130610_2343.wav"; DestDir: "{app}\save\Samples"; [Icons] -Name: "{group}\wsjtx"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico -Name: "{userdesktop}\wsjtx"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico +Name: "{group}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico +Name: "{userdesktop}\wsjtx2"; Filename: "{app}\wsjtx.exe"; WorkingDir: {app}; IconFilename: {app}\wsjt.ico diff --git a/wsjtx.pro b/wsjtx.pro index d3acc2779..6e4272e1c 100644 --- a/wsjtx.pro +++ b/wsjtx.pro @@ -6,13 +6,12 @@ QT += core gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -CONFIG += qwt thread +CONFIG += thread #CONFIG += console TARGET = wsjtx DESTDIR = ../wsjtx_install -#DESTDIR = ../qt5_install -VERSION = 0.99 +VERSION = 1.1 TEMPLATE = app DEFINES = QT4 @@ -57,27 +56,22 @@ FORMS += mainwindow.ui about.ui devsetup.ui widegraph.ui \ RC_FILE = wsjtx.rc unix { -INCLUDEPATH += $$quote(/usr/include/qwt-qt4) LIBS += ../wsjtx/lib/libjt9.a LIBS += -lhamlib -LIBS += -lportaudio -lgfortran -lfftw3f -lqwt-qt4 +LIBS += -lportaudio -lgfortran -lfftw3f } win32 { -INCLUDEPATH += c:/qwt-6.0.1/include INCLUDEPATH += ../../hamlib-1.2.15.3/include LIBS += ../../hamlib-1.2.15.3/src/.libs/libhamlib.dll.a +#LIBS += ../../hamlib-1.2.15.3/lib/gcc/libhamlib.dll.a LIBS += ../wsjtx/lib/libjt9.a LIBS += ../wsjtx/libfftw3f_win.a LIBS += ../wsjtx/libpskreporter.a LIBS += ../wsjtx/libHRDInterface001.a -LIBS += ../QtSupport/palir-02.dll +#LIBS += ../QtSupport/palir-02.dll +LIBS += /users/joe/wsjt/QtSupport/palir-02.dll LIBS += libwsock32 LIBS += C:/MinGW/lib/libf95.a -CONFIG(release) { - LIBS += C:/qwt-6.0.1/lib/qwt.dll -} else { - LIBS += C:/qwt-6.0.1/lib/qwtd.dll - LIBS += -lusb -} + }