From e26b2db9678c1519423208712d298fb1799e6b19 Mon Sep 17 00:00:00 2001 From: Joe Taylor <joe@princeton.edu> Date: Fri, 9 Dec 2022 19:08:35 -0500 Subject: [PATCH] Work in progress... Q65 decoding now works when called as a subroutine. --- lib/map65_mmdec.f90 | 5 +---- lib/q65_decode.f90 | 24 +++++++++++------------ lib/qra/q65/q65.f90 | 6 ++---- q65w/commons.h | 40 ++++++++++++++++++++++++++++++++++++++ q65w/libm65/CMakeLists.txt | 1 + q65w/libm65/ftninit.f90 | 13 ++++++++----- q65w/libm65/map65a.f90 | 29 ++++++++++++++------------- q65w/libm65/q65b.f90 | 31 +++++++++++++++-------------- q65w/main.cpp | 10 ++++++++++ q65w/mainwindow.cpp | 27 +++++++++++++++++++------ q65w/mainwindow.h | 5 +++++ 11 files changed, 131 insertions(+), 60 deletions(-) diff --git a/lib/map65_mmdec.f90 b/lib/map65_mmdec.f90 index e0456b788..dc62e6e7e 100644 --- a/lib/map65_mmdec.f90 +++ b/lib/map65_mmdec.f90 @@ -29,7 +29,7 @@ subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, & ! mygrid=transfer(params%mygrid,mygrid) ! hisgrid=transfer(params%hisgrid,hisgrid) datetime=' ' - + my_q65%decoded = 0 ncontest=0 nQSOprogress=0 @@ -43,9 +43,6 @@ subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, & ndepth=2 !Does this make it too slow? ntrperiod=60 - open(17,file=trim(temp_dir)//'/red.dat',status='unknown') - open(14,file=trim(temp_dir)//'/avemsg.txt',status='unknown') - call timer('dec_q65 ',0) call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, & ntol,ndepth,nfa,nfb,lclearave,single_decode,lagain,max_drift,lnewdat, & diff --git a/lib/q65_decode.f90 b/lib/q65_decode.f90 index 04e58eb86..515cdab6e 100644 --- a/lib/q65_decode.f90 +++ b/lib/q65_decode.f90 @@ -288,8 +288,8 @@ contains if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg call sec0(1,tdecode) - open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & - position='append',iostat=ios) +! open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & +! position='append',iostat=ios) if(ios.eq.0) then ! Save decoding parameters to q65_decoded.dat, for later analysis. write(cmode,'(i3)') ntrperiod @@ -302,10 +302,10 @@ contains '1x,a6,1x,a6,1x,a4,1x,a)' if(ntrperiod.le.30) fmt(5:5)='6' if(idec.eq.3) nrc=0 - write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & - ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & - tdecode,mycall(1:6),c6,c4,trim(decoded) - close(22) +! write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & +! ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & +! tdecode,mycall(1:6),c6,c4,trim(decoded) +! close(22) endif endif endif @@ -373,8 +373,8 @@ contains if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg call sec0(1,tdecode) - open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & - position='append',iostat=ios) +! open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown',& +! position='append',iostat=ios) if(ios.eq.0) then ! Save decoding parameters to q65_decoded.dat, for later analysis. write(cmode,'(i3)') ntrperiod @@ -387,10 +387,10 @@ contains '1x,a6,1x,a6,1x,a4,1x,a)' if(ntrperiod.le.30) fmt(5:5)='6' if(idec.eq.3) nrc=0 - write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & - ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & - tdecode,mycall(1:6),c6,c4,trim(decoded) - close(22) +! write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & +! ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & +! tdecode,mycall(1:6),c6,c4,trim(decoded) +! close(22) endif endif endif diff --git a/lib/qra/q65/q65.f90 b/lib/qra/q65/q65.f90 index 2133294ef..aa104bbfc 100644 --- a/lib/qra/q65/q65.f90 +++ b/lib/qra/q65/q65.f90 @@ -217,11 +217,9 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & if(i2.eq.-9999 .and. ccf1(-i).ge.0.5*smax) i2=-i enddo width=df*(i2-i1) - if(ncw.eq.0) ccf1=0. - - call q65_write_red(iz,xdt,ccf2_avg,ccf2) - + call q65_write_red(iz,xdt,ccf2_avg,ccf2) !### Need this call for WSJT-X + if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) endif diff --git a/q65w/commons.h b/q65w/commons.h index e8fff92bd..ecea5fb35 100644 --- a/q65w/commons.h +++ b/q65w/commons.h @@ -43,6 +43,46 @@ extern struct { //This is "common/datcom/..." in Fortran int junk1; //Used to test extent of copy to shared memory int junk2; } datcom_; + +extern struct { //This is "common/datcom/..." in Fortran + float d4[4*5760000]; //Raw I/Q data from Linrad + float ss[4*322*NFFT]; //Half-symbol spectra at 0,45,90,135 deg pol + float savg[4*NFFT]; //Avg spectra at 0,45,90,135 deg pol + double fcenter; //Center freq from Linrad (MHz) + int nutc; //UTC as integer, HHMM + int idphi; //Phase correction for Y pol'n, degrees + int mousedf; //User-selected DF + int mousefqso; //User-selected QSO freq (kHz) + int nagain; //1 ==> decode only at fQSO +/- Tol + int ndepth; //How much hinted decoding to do? + int ndiskdat; //1 ==> data read from *.tf2 or *.iq file + int neme; //Hinted decoding tries only for EME calls + int newdat; //1 ==> new data, must do long FFT + int nfa; //Low decode limit (kHz) + int nfb; //High decode limit (kHz) + int nfcal; //Frequency correction, for calibration (Hz) + int nfshift; //Shift of displayed center freq (kHz) + int mcall3; //1 ==> CALL3.TXT has been modified + int ntimeout; //Max for timeouts in Messages and BandMap + int ntol; //+/- decoding range around fQSO (Hz) + int nxant; //1 ==> add 45 deg to measured pol angle + int map65RxLog; //Flags to control log files + int nfsample; //Input sample rate + int nxpol; //1 if using xpol antennas, 0 otherwise + int nmode; //nmode = 10*m_modeQ65 + m_modeJT65 + int ndop00; //EME Self Doppler + int nsave; //Number of s3(64,63) spectra saved + int max_drift; //Maximum Q65 drift: units symbol_rate/TxT + int nhsym; //Number of available JT65 half-symbols + char mycall[12]; + char mygrid[6]; + char hiscall[12]; + char hisgrid[6]; + char datetime[20]; + int junk1; //Used to test extent of copy to shared memory + int junk2; +} datcom2_; + } #endif // COMMONS_H diff --git a/q65w/libm65/CMakeLists.txt b/q65w/libm65/CMakeLists.txt index fe5ee170c..6a4e1c841 100644 --- a/q65w/libm65/CMakeLists.txt +++ b/q65w/libm65/CMakeLists.txt @@ -54,6 +54,7 @@ set (libm65_FSRCS jt65code.f90 k2grid.f90 lorentzian.f90 + m65c.f90 map65a.f90 moon2.f90 moondop.f90 diff --git a/q65w/libm65/ftninit.f90 b/q65w/libm65/ftninit.f90 index c55bf04f6..f4217b6a0 100644 --- a/q65w/libm65/ftninit.f90 +++ b/q65w/libm65/ftninit.f90 @@ -1,20 +1,23 @@ -subroutine ftninit(appd) +!subroutine ftninit() +subroutine ftninit use timer_module, only: timer use, intrinsic :: iso_c_binding, only: C_NULL_CHAR use FFTW3 - character*(*) appd +! character*(*) appd + character*1 appd character addpfx*8 character wisfile*256 common/pfxcom/addpfx + appd='.' addpfx=' ' call pfxdump(appd//'/prefixes.txt') open(12,file=appd//'/q65w_decodes.txt',status='unknown') - open(13,file=appd//'/map65.log',status='unknown') + open(17,file=appd//'/red.dat',status='unknown') open(19,file=appd//'/livecq.txt',status='unknown') - open(21,file=appd//'/map65_rx.log',status='unknown',access='append',err=950) - open(26,file=appd//'/tmp26.txt',status='unknown') +! open(21,file=appd//'/map65_rx.log',status='unknown',access='append',err=950) +! open(26,file=appd//'/tmp26.txt',status='unknown') ! Import FFTW wisdom, if available: iret=fftwf_init_threads() !Initialize FFTW threading diff --git a/q65w/libm65/map65a.f90 b/q65w/libm65/map65a.f90 index 249bbf6e4..657d14269 100644 --- a/q65w/libm65/map65a.f90 +++ b/q65w/libm65/map65a.f90 @@ -86,7 +86,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, & nsum=0 !### Should use AppDir! ### - open(23,file='CALL3.TXT',status='unknown') +! open(23,file='CALL3.TXT',status='unknown') df=96000.0/NFFT !df = 96000/NFFT = 2.930 Hz if(nfsample.eq.95238) df=95238.1/NFFT @@ -305,7 +305,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, & ! Trim the list and produce a sorted index and sizes of groups. ! (Should trimlist remove all but best SNR for given UTC and message content?) -700 call trimlist(sig,km,ftol,indx,nsiz,nz) +700 call trimlist(sig,km,ftol,indx,nsiz,nz) done(1:km)=.false. j=0 ilatest=-1 @@ -373,27 +373,28 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, & cmode='#A' if(mode65.eq.2) cmode='#B' if(mode65.eq.4) cmode='#C' - write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, & - nsync2,nutc,decoded,cp,cmode -1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2) +! write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, & +! nsync2,nutc,decoded,cp,cmode +!1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2) ndecodes=ndecodes+1 - write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, & - cmode(1:1),cmode(2:2) -1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1) +! write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, & +! cmode(1:1),cmode(2:2) +!1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1) endif endif j=j+nsiz(n) enddo !i=1,km - write(26,1015) nutc -1015 format(37x,i6.4,' ') - call flush(21) - call flush(26) - call display(nkeep,ftol) +! write(26,1015) nutc +!1015 format(37x,i6.4,' ') +! call flush(21) +! call flush(26) +! call display(nkeep,ftol) ndecdone=2 -900 close(23) +900 continue +! close(23) call flush(12) ndphi=0 mcall3b=mcall3a diff --git a/q65w/libm65/q65b.f90 b/q65w/libm65/q65b.f90 index a45263de6..f65e3b3d7 100644 --- a/q65w/libm65/q65b.f90 +++ b/q65w/libm65/q65b.f90 @@ -40,10 +40,10 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & save if(newdat.eq.1) nutc00=-1 - open(9,file='wsjtx_dir.txt',status='old') - read(9,'(a)') wsjtx_dir !Establish the working directory - close(9) - +! open(9,file='wsjtx_dir.txt',status='old') +! read(9,'(a)') wsjtx_dir !Establish the working directory +! close(9) + if(mycall0(1:1).ne.' ') mycall=mycall0 if(hiscall0(1:1).ne.' ') hiscall=hiscall0 if(hisgrid(1:4).ne.' ') grid4=hisgrid(1:4) @@ -139,10 +139,10 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & nsnr0=-99 !Default snr for no decode ! NB: Frequency of ipk is now shifted to 1000 Hz. + call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, & newdat,nagain,max_drift,mycall,hiscall,hisgrid) - - MHz=fcenter + MHz=fcenter freq0=MHz + 0.001d0*ikhz if(nsnr0.gt.-99) then @@ -172,18 +172,18 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & cmode=': ' cmode(2:2)=char(ichar('A') + mode_q65-1) freq1=freq0 + 0.001d0*(ikhz1-ikhz) - write(26,1014) freq1,ndf,0,0,0,xdt0,npol,0,nsnr0,nutc,msg0(1:22), & - ':',cp,cmode -1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2) +! write(26,1014) freq1,ndf,0,0,0,xdt0,npol,0,nsnr0,nutc,msg0(1:22), & +! ':',cp,cmode +!1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2) ! Suppress writing duplicates (same time, decoded message, and frequency) ! to map65_rx.log if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then ! Write to file map65_rx.log: ndecodes=ndecodes+1 - write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28), & - cmode(2:2),cq0 -1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': ',a1,2x,a3) +! write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28), & +! cmode(2:2),cq0 +!1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': ',a1,2x,a3) nutc00=nutc msg00=msg0(1:28) freq1_00=freq1 @@ -195,9 +195,10 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, & 1121 format('~',i4.4,f9.3,f7.2,i5,2x,a,i6) endif endif - -900 close(13) - close(17) + +900 continue +! close(13) +! close(17) call flush(6) idec=-1 read(cq0(2:2),*) idec diff --git a/q65w/main.cpp b/q65w/main.cpp index a6b612244..eac86216d 100644 --- a/q65w/main.cpp +++ b/q65w/main.cpp @@ -12,11 +12,21 @@ extern "C" { // Fortran procedures we need void four2a_ (_Complex float *, int * nfft, int * ndim, int * isign, int * iform, int len); + + void _gfortran_set_args(int argc, char *argv[]); + void _gfortran_set_convert(int conv); + void ftninit_(void); } int main(int argc, char *argv[]) { QApplication a {argc, argv}; + +// Initialize libgfortran: + _gfortran_set_args(argc, argv); + _gfortran_set_convert(0); + ftninit_(); + // Override programs executable basename as application name. a.setApplicationName ("Q65W"); a.setApplicationVersion ("0.1"); diff --git a/q65w/mainwindow.cpp b/q65w/mainwindow.cpp index 30d6b96b9..d3f42e011 100644 --- a/q65w/mainwindow.cpp +++ b/q65w/mainwindow.cpp @@ -180,6 +180,8 @@ MainWindow::MainWindow(QWidget *parent) : watcher2 = new QFutureWatcher<void>; connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished())); + connect(&watcher3, SIGNAL(finished()),this,SLOT(decoderFinished())); + // Assign input device and start input thread soundInThread.setInputDevice(m_paInDevice); soundInThread.setRate(96000.0); @@ -494,7 +496,7 @@ void MainWindow::dataSink(int k) n=0; } - qDebug() << "aa" << ihsym << k << px; +// qDebug() << "aa" << ihsym << k << px; if(ihsym==302) { //Decode at t=56 s (for Q65 and data from disk) m_RxState=2; @@ -849,7 +851,16 @@ void MainWindow::diskWriteFinished() //diskWriteFinished { // qDebug() << "diskWriteFinished"; } - //Delete ../save/*.tf2 + +void MainWindow::decoderFinished() //diskWriteFinished +{ + m_map65RxLog=0; + m_startAnother=m_loopall; + ui->DecodeButton->setStyleSheet(""); + decodeBusy(false); +} + +//Delete ../save/*.tf2 void MainWindow::on_actionDelete_all_tf2_files_in_SaveDir_triggered() { int i; @@ -1003,7 +1014,8 @@ void MainWindow::decode() //decode() datcom_.junk1=1234; //Cecck for these values in m65 datcom_.junk2=5678; - char *to = (char*)mem_m65.data(); +// char *to = (char*)mem_m65.data(); + char *to = (char*) datcom2_.d4; char *from = (char*) datcom_.d4; int size=sizeof(datcom_); if(datcom_.newdat==0) { @@ -1012,14 +1024,17 @@ void MainWindow::decode() //decode() from += noffset; size -= noffset; } - memcpy(to, from, qMin(mem_m65.size(), size-8)); + memcpy(to, from, qMin(mem_m65.size(), size-4)); datcom_.nagain=0; datcom_.ndiskdat=0; m_map65RxLog=0; m_call3Modified=false; - QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start - lockFile.remove(); +// QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start +// lockFile.remove(); + + watcher3.setFuture(QtConcurrent::run (std::bind (m65c_))); + decodeBusy(true); } diff --git a/q65w/mainwindow.h b/q65w/mainwindow.h index a3beba068..b38cfaa10 100644 --- a/q65w/mainwindow.h +++ b/q65w/mainwindow.h @@ -42,6 +42,7 @@ public slots: void dataSink(int k); void diskDat(); void diskWriteFinished(); + void decoderFinished(); void freezeDecode(int n); void readFromStdout(); void m65_error (QProcess::ProcessError); @@ -173,6 +174,8 @@ private: QFutureWatcher<void>* watcher1; QFutureWatcher<void>* watcher2; + QFutureWatcher<void> watcher3; //For decoder + QProcess proc_m65; QString m_path; @@ -227,6 +230,8 @@ extern "C" { void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq, const char* mygrid, int* ndop00, int len1); + + void m65c_(void); } #endif // MAINWINDOW_H