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