Work in progress... Q65 decoding now works when called as a subroutine.

This commit is contained in:
Joe Taylor 2022-12-09 19:08:35 -05:00
parent ff56d9fa0b
commit e26b2db967
11 changed files with 131 additions and 60 deletions

View File

@ -43,9 +43,6 @@ subroutine map65_mmdec(nutc,id2,nqd,nsubmode,nfa,nfb,nfqso,ntol,newdat, &
ndepth=2 !Does this make it too slow? ndepth=2 !Does this make it too slow?
ntrperiod=60 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 timer('dec_q65 ',0)
call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, & call my_q65%decode(q65_decoded,id2,nqd,nutc,ntrperiod,nsubmode,nfqso, &
ntol,ndepth,nfa,nfb,lclearave,single_decode,lagain,max_drift,lnewdat, & ntol,ndepth,nfa,nfb,lclearave,single_decode,lagain,max_drift,lnewdat, &

View File

@ -288,8 +288,8 @@ contains
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode) call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & ! open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', &
position='append',iostat=ios) ! position='append',iostat=ios)
if(ios.eq.0) then if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis. ! Save decoding parameters to q65_decoded.dat, for later analysis.
write(cmode,'(i3)') ntrperiod write(cmode,'(i3)') ntrperiod
@ -302,10 +302,10 @@ contains
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & ! write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & ! ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded) ! tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) ! close(22)
endif endif
endif endif
endif endif
@ -373,8 +373,8 @@ contains
if(iand(ndepth,128).ne.0 .and. .not.lagain .and. & if(iand(ndepth,128).ne.0 .and. .not.lagain .and. &
int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg int(abs(f0dec-nfqso)).le.ntol ) call q65_clravg !AutoClrAvg
call sec0(1,tdecode) call sec0(1,tdecode)
open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown', & ! open(22,file=trim(data_dir)//'/q65_decodes.dat',status='unknown',&
position='append',iostat=ios) ! position='append',iostat=ios)
if(ios.eq.0) then if(ios.eq.0) then
! Save decoding parameters to q65_decoded.dat, for later analysis. ! Save decoding parameters to q65_decoded.dat, for later analysis.
write(cmode,'(i3)') ntrperiod write(cmode,'(i3)') ntrperiod
@ -387,10 +387,10 @@ contains
'1x,a6,1x,a6,1x,a4,1x,a)' '1x,a6,1x,a6,1x,a4,1x,a)'
if(ntrperiod.le.30) fmt(5:5)='6' if(ntrperiod.le.30) fmt(5:5)='6'
if(idec.eq.3) nrc=0 if(idec.eq.3) nrc=0
write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, & ! write(22,fmt) nutc,cmode,nfqso,nQSOprogress,idec,idfbest,idtbest, &
ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, & ! ibw,ndistbest,nused,icand,ncand,nrc,ndepth,xdt,f0,snr2,plog, &
tdecode,mycall(1:6),c6,c4,trim(decoded) ! tdecode,mycall(1:6),c6,c4,trim(decoded)
close(22) ! close(22)
endif endif
endif endif
endif endif

View File

@ -217,10 +217,8 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, &
if(i2.eq.-9999 .and. ccf1(-i).ge.0.5*smax) i2=-i if(i2.eq.-9999 .and. ccf1(-i).ge.0.5*smax) i2=-i
enddo enddo
width=df*(i2-i1) width=df*(i2-i1)
if(ncw.eq.0) ccf1=0. if(ncw.eq.0) ccf1=0.
call q65_write_red(iz,xdt,ccf2_avg,ccf2) !### Need this call for WSJT-X
call q65_write_red(iz,xdt,ccf2_avg,ccf2)
if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then if(idec.lt.0 .and. (iavg.eq.0 .or. iavg.eq.2)) then
call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded)

View File

@ -43,6 +43,46 @@ extern struct { //This is "common/datcom/..." in Fortran
int junk1; //Used to test extent of copy to shared memory int junk1; //Used to test extent of copy to shared memory
int junk2; int junk2;
} datcom_; } 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 #endif // COMMONS_H

View File

@ -54,6 +54,7 @@ set (libm65_FSRCS
jt65code.f90 jt65code.f90
k2grid.f90 k2grid.f90
lorentzian.f90 lorentzian.f90
m65c.f90
map65a.f90 map65a.f90
moon2.f90 moon2.f90
moondop.f90 moondop.f90

View File

@ -1,20 +1,23 @@
subroutine ftninit(appd) !subroutine ftninit()
subroutine ftninit
use timer_module, only: timer use timer_module, only: timer
use, intrinsic :: iso_c_binding, only: C_NULL_CHAR use, intrinsic :: iso_c_binding, only: C_NULL_CHAR
use FFTW3 use FFTW3
character*(*) appd ! character*(*) appd
character*1 appd
character addpfx*8 character addpfx*8
character wisfile*256 character wisfile*256
common/pfxcom/addpfx common/pfxcom/addpfx
appd='.'
addpfx=' ' addpfx=' '
call pfxdump(appd//'/prefixes.txt') call pfxdump(appd//'/prefixes.txt')
open(12,file=appd//'/q65w_decodes.txt',status='unknown') 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(19,file=appd//'/livecq.txt',status='unknown')
open(21,file=appd//'/map65_rx.log',status='unknown',access='append',err=950) ! open(21,file=appd//'/map65_rx.log',status='unknown',access='append',err=950)
open(26,file=appd//'/tmp26.txt',status='unknown') ! open(26,file=appd//'/tmp26.txt',status='unknown')
! Import FFTW wisdom, if available: ! Import FFTW wisdom, if available:
iret=fftwf_init_threads() !Initialize FFTW threading iret=fftwf_init_threads() !Initialize FFTW threading

View File

@ -86,7 +86,7 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
nsum=0 nsum=0
!### Should use AppDir! ### !### 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 df=96000.0/NFFT !df = 96000/NFFT = 2.930 Hz
if(nfsample.eq.95238) df=95238.1/NFFT 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. ! 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?) ! (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. done(1:km)=.false.
j=0 j=0
ilatest=-1 ilatest=-1
@ -373,27 +373,28 @@ subroutine map65a(dd,ss,savg,newdat,nutc,fcenter,ntol,idphi,nfa,nfb, &
cmode='#A' cmode='#A'
if(mode65.eq.2) cmode='#B' if(mode65.eq.2) cmode='#B'
if(mode65.eq.4) cmode='#C' if(mode65.eq.4) cmode='#C'
write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, & ! write(26,1014) f0,ndf,ndf0,ndf1,ndf2,dt,npol,nsync1, &
nsync2,nutc,decoded,cp,cmode ! nsync2,nutc,decoded,cp,cmode
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2) !1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,2x,a1,3x,a2)
ndecodes=ndecodes+1 ndecodes=ndecodes+1
write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, & ! write(21,1100) f0,ndf,dt,npol,nsync2,nutc,decoded,cp, &
cmode(1:1),cmode(2:2) ! cmode(1:1),cmode(2:2)
1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1) !1100 format(f8.3,i5,f5.1,2i4,i5.4,2x,a22,2x,a1,3x,a1,1x,a1)
endif endif
endif endif
j=j+nsiz(n) j=j+nsiz(n)
enddo !i=1,km enddo !i=1,km
write(26,1015) nutc ! write(26,1015) nutc
1015 format(37x,i6.4,' ') !1015 format(37x,i6.4,' ')
call flush(21) ! call flush(21)
call flush(26) ! call flush(26)
call display(nkeep,ftol) ! call display(nkeep,ftol)
ndecdone=2 ndecdone=2
900 close(23) 900 continue
! close(23)
call flush(12) call flush(12)
ndphi=0 ndphi=0
mcall3b=mcall3a mcall3b=mcall3a

View File

@ -40,9 +40,9 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
save save
if(newdat.eq.1) nutc00=-1 if(newdat.eq.1) nutc00=-1
open(9,file='wsjtx_dir.txt',status='old') ! open(9,file='wsjtx_dir.txt',status='old')
read(9,'(a)') wsjtx_dir !Establish the working directory ! read(9,'(a)') wsjtx_dir !Establish the working directory
close(9) ! close(9)
if(mycall0(1:1).ne.' ') mycall=mycall0 if(mycall0(1:1).ne.' ') mycall=mycall0
if(hiscall0(1:1).ne.' ') hiscall=hiscall0 if(hiscall0(1:1).ne.' ') hiscall=hiscall0
@ -139,10 +139,10 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
nsnr0=-99 !Default snr for no decode nsnr0=-99 !Default snr for no decode
! NB: Frequency of ipk is now shifted to 1000 Hz. ! NB: Frequency of ipk is now shifted to 1000 Hz.
call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, & call map65_mmdec(nutc,iwave,nqd,nsubmode,nfa,nfb,1000,ntol, &
newdat,nagain,max_drift,mycall,hiscall,hisgrid) newdat,nagain,max_drift,mycall,hiscall,hisgrid)
MHz=fcenter
MHz=fcenter
freq0=MHz + 0.001d0*ikhz freq0=MHz + 0.001d0*ikhz
if(nsnr0.gt.-99) then if(nsnr0.gt.-99) then
@ -172,18 +172,18 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
cmode=': ' cmode=': '
cmode(2:2)=char(ichar('A') + mode_q65-1) cmode(2:2)=char(ichar('A') + mode_q65-1)
freq1=freq0 + 0.001d0*(ikhz1-ikhz) freq1=freq0 + 0.001d0*(ikhz1-ikhz)
write(26,1014) freq1,ndf,0,0,0,xdt0,npol,0,nsnr0,nutc,msg0(1:22), & ! write(26,1014) freq1,ndf,0,0,0,xdt0,npol,0,nsnr0,nutc,msg0(1:22), &
':',cp,cmode ! ':',cp,cmode
1014 format(f8.3,i5,3i3,f5.1,i4,i3,i4,i5.4,4x,a22,1x,2a1,2x,a2) !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) ! Suppress writing duplicates (same time, decoded message, and frequency)
! to map65_rx.log ! to map65_rx.log
if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then if(nutc.ne.nutc00 .or. msg0(1:28).ne.msg00 .or. freq1.ne.freq1_00) then
! Write to file map65_rx.log: ! Write to file map65_rx.log:
ndecodes=ndecodes+1 ndecodes=ndecodes+1
write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28), & ! write(21,1110) freq1,ndf,xdt0,npol,nsnr0,nutc,msg0(1:28), &
cmode(2:2),cq0 ! cmode(2:2),cq0
1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': ',a1,2x,a3) !1110 format(f8.3,i5,f5.1,2i4,i5.4,2x,a28,': ',a1,2x,a3)
nutc00=nutc nutc00=nutc
msg00=msg0(1:28) msg00=msg0(1:28)
freq1_00=freq1 freq1_00=freq1
@ -196,8 +196,9 @@ subroutine q65b(nutc,nqd,nxant,fcenter,nfcal,nfsample,ikhz,mousedf,ntol,xpol, &
endif endif
endif endif
900 close(13) 900 continue
close(17) ! close(13)
! close(17)
call flush(6) call flush(6)
idec=-1 idec=-1
read(cq0(2:2),*) idec read(cq0(2:2),*) idec

View File

@ -12,11 +12,21 @@
extern "C" { extern "C" {
// Fortran procedures we need // Fortran procedures we need
void four2a_ (_Complex float *, int * nfft, int * ndim, int * isign, int * iform, int len); 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[]) int main(int argc, char *argv[])
{ {
QApplication a {argc, argv}; QApplication a {argc, argv};
// Initialize libgfortran:
_gfortran_set_args(argc, argv);
_gfortran_set_convert(0);
ftninit_();
// Override programs executable basename as application name. // Override programs executable basename as application name.
a.setApplicationName ("Q65W"); a.setApplicationName ("Q65W");
a.setApplicationVersion ("0.1"); a.setApplicationVersion ("0.1");

View File

@ -180,6 +180,8 @@ MainWindow::MainWindow(QWidget *parent) :
watcher2 = new QFutureWatcher<void>; watcher2 = new QFutureWatcher<void>;
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished())); connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
connect(&watcher3, SIGNAL(finished()),this,SLOT(decoderFinished()));
// Assign input device and start input thread // Assign input device and start input thread
soundInThread.setInputDevice(m_paInDevice); soundInThread.setInputDevice(m_paInDevice);
soundInThread.setRate(96000.0); soundInThread.setRate(96000.0);
@ -494,7 +496,7 @@ void MainWindow::dataSink(int k)
n=0; 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) if(ihsym==302) { //Decode at t=56 s (for Q65 and data from disk)
m_RxState=2; m_RxState=2;
@ -849,7 +851,16 @@ void MainWindow::diskWriteFinished() //diskWriteFinished
{ {
// qDebug() << "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() void MainWindow::on_actionDelete_all_tf2_files_in_SaveDir_triggered()
{ {
int i; int i;
@ -1003,7 +1014,8 @@ void MainWindow::decode() //decode()
datcom_.junk1=1234; //Cecck for these values in m65 datcom_.junk1=1234; //Cecck for these values in m65
datcom_.junk2=5678; 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; char *from = (char*) datcom_.d4;
int size=sizeof(datcom_); int size=sizeof(datcom_);
if(datcom_.newdat==0) { if(datcom_.newdat==0) {
@ -1012,14 +1024,17 @@ void MainWindow::decode() //decode()
from += noffset; from += noffset;
size -= 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_.nagain=0;
datcom_.ndiskdat=0; datcom_.ndiskdat=0;
m_map65RxLog=0; m_map65RxLog=0;
m_call3Modified=false; m_call3Modified=false;
QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start // QFile lockFile(m_appDir + "/.lock"); // Allow m65 to start
lockFile.remove(); // lockFile.remove();
watcher3.setFuture(QtConcurrent::run (std::bind (m65c_)));
decodeBusy(true); decodeBusy(true);
} }

View File

@ -42,6 +42,7 @@ public slots:
void dataSink(int k); void dataSink(int k);
void diskDat(); void diskDat();
void diskWriteFinished(); void diskWriteFinished();
void decoderFinished();
void freezeDecode(int n); void freezeDecode(int n);
void readFromStdout(); void readFromStdout();
void m65_error (QProcess::ProcessError); void m65_error (QProcess::ProcessError);
@ -173,6 +174,8 @@ private:
QFutureWatcher<void>* watcher1; QFutureWatcher<void>* watcher1;
QFutureWatcher<void>* watcher2; QFutureWatcher<void>* watcher2;
QFutureWatcher<void> watcher3; //For decoder
QProcess proc_m65; QProcess proc_m65;
QString m_path; QString m_path;
@ -227,6 +230,8 @@ extern "C" {
void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq, void astrosub00_ (int* nyear, int* month, int* nday, double* uth, int* nfreq,
const char* mygrid, int* ndop00, int len1); const char* mygrid, int* ndop00, int len1);
void m65c_(void);
} }
#endif // MAINWINDOW_H #endif // MAINWINDOW_H