From 35fd9febd3715d0e3e9651961f2c7ee21c604038 Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Thu, 6 Jul 2017 12:07:17 +0000 Subject: [PATCH] Baseline code with nsps=2048 in FT8. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7783 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- CMakeLists.txt | 3 +- lib/fsk4hf/ft8_downsample.f90 | 41 +++++++++++ lib/fsk4hf/ft8b.f90 | 133 ++++++---------------------------- lib/fsk4hf/sync8d.f90 | 54 ++++++++++++++ mainwindow.cpp | 2 + 5 files changed, 123 insertions(+), 110 deletions(-) create mode 100644 lib/fsk4hf/ft8_downsample.f90 create mode 100644 lib/fsk4hf/sync8d.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a7b68e03..6d884776d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,7 +394,7 @@ set (wsjt_FSRCS lib/fsk4hf/fsk4hf.f90 lib/fsk4hf/ft8b.f90 lib/fsk4hf/ft8d.f90 -# lib/fsk4hf/ft8filbig.f90 + lib/fsk4hf/ft8_downsample.f90 lib/fsk4hf/ft8sim.f90 lib/gen4.f90 lib/gen65.f90 @@ -503,6 +503,7 @@ set (wsjt_FSRCS lib/sync64.f90 lib/sync65.f90 lib/fsk4hf/sync8.f90 + lib/fsk4hf/sync8d.f90 lib/sync9.f90 lib/sync9f.f90 lib/sync9w.f90 diff --git a/lib/fsk4hf/ft8_downsample.f90 b/lib/fsk4hf/ft8_downsample.f90 new file mode 100644 index 000000000..2c8a43e30 --- /dev/null +++ b/lib/fsk4hf/ft8_downsample.f90 @@ -0,0 +1,41 @@ +subroutine ft8_downsample(dd,newdat,f0,c1) + +! Downconvert to complex data sampled at 187.5 Hz, 32 samples/symbol + + parameter (NMAX=15*12000) + parameter (NFFT1=200000,NFFT2=3125) !200000/64 = 3125 + logical newdat + complex c1(0:NFFT2-1) + complex cx(0:NFFT1/2) + real dd(NMAX),x(NFFT1) + equivalence (x,cx) + save cx + + if(newdat) then +! Data in dd have changed, recompute the long FFT + x(1:NMAX)=dd + x(NMAX+1:NFFT1)=0. !Zero-pad the x array + call four2a(cx,NFFT1,1,-1,0) !r2c FFT to freq domain + newdat=.false. + endif + + df=12000.0/NFFT1 + baud=12000.0/2048.0 + i0=nint(f0/df) + ft=f0+8.0*baud + it=min(nint(ft/df),NFFT1/2) + fb=f0-1.0*baud + ib=max(1,nint(fb/df)) + k=0 + c1=0. + do i=ib,it + c1(k)=cx(i) + k=k+1 + enddo + c1=cshift(c1,i0-ib) + call four2a(c1,NFFT2,1,1,1) !c2c FFT back to time domain + fac=1.0/sqrt(float(NFFT1)*NFFT2) + c1=fac*c1 + + return +end subroutine ft8_downsample diff --git a/lib/fsk4hf/ft8b.f90 b/lib/fsk4hf/ft8b.f90 index 32557340a..af7dd09c2 100644 --- a/lib/fsk4hf/ft8b.f90 +++ b/lib/fsk4hf/ft8b.f90 @@ -12,70 +12,39 @@ subroutine ft8b(dd0,newdat,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr) real dd0(15*12000) integer*1 decoded(KK),apmask(3*ND),cw(3*ND) integer itone(NN) - integer icos7(0:6) complex cd0(3125) - complex csync(0:6,32) complex ctwk(32) complex csymb(32) - logical newdat,first - data icos7/2,5,6,0,4,1,3/ - data first/.true./ - save first,twopi,fs2,dt2,taus,baud,csync - - if( first ) then - twopi=8.0*atan(1.0) - fs2=12000.0/64.0 - dt2=1/fs2 - taus=32*dt2 - baud=1/taus - do i=0,6 - phi=0.0 - dphi=twopi*icos7(i)*baud*dt2 - do j=1,32 - csync(i,j)=cmplx(cos(phi),sin(phi)) - phi=mod(phi+dphi,twopi) - enddo - enddo - first=.false. - endif + logical newdat max_iterations=40 norder=2 + fs2=12000.0/64.0 + dt2=1.0/fs2 + twopi=8.0*atan(1.0) + delfbest=0. + ibest=0 + ! if(abs(nfqso-f1).lt.10.0) norder=3 call timer('ft8_down',0) - call ft8_downsample(dd0,newdat,f1,cd0) + call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample call timer('ft8_down',1) - i0=xdt*fs2 + i0=nint(xdt*fs2) !Initial guess for start of signal smax=0.0 - do idt=i0-16,i0+16 - sync=0 - do i=0,6 - i1=idt+i*32 - i2=i1+36*32 - i3=i1+72*32 - term1=0.0 ! this needs to be fixed... - term2=0.0 - term3=0.0 - if( i1.ge.1 .and. i1+31.le.NP2 ) & - term1=abs(sum(cd0(i1:i1+31)*conjg(csync(i,1:32)))) - if( i2.ge.1 .and. i2+31.le.NP2 ) & - term2=abs(sum(cd0(i2:i2+31)*conjg(csync(i,1:32)))) - if( i3.ge.1 .and. i3+31.le.NP2 ) & - term3=abs(sum(cd0(i3:i3+31)*conjg(csync(i,1:32)))) - sync=sync+term1+term2+term3 - enddo - if( sync .gt. smax ) then - smax=sync - ibest=idt - endif + do idt=i0-16,i0+16 !Search over +/- half a symbol + call sync8d(cd0,idt,ctwk,0,sync) + if(sync.gt.smax) then + smax=sync + ibest=idt + endif enddo - xdt2=ibest*dt2 + xdt2=ibest*dt2 !Improved estimate for DT -! peak up the frequency - i0=xdt2*fs2 +! Now peak up in frequency + i0=nint(xdt2*fs2) smax=0.0 - do ifr=-5,5 + do ifr=-5,5 !Search over +/- 2.5 Hz delf=ifr*0.5 dphi=twopi*delf*dt2 phi=0.0 @@ -83,22 +52,7 @@ subroutine ft8b(dd0,newdat,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr) ctwk(i)=cmplx(cos(phi),sin(phi)) phi=mod(phi+dphi,twopi) enddo - sync=0.0 - do i=0,6 - i1=i0+i*32 - i2=i1+36*32 - i3=i1+72*32 - term1=0.0 ! this needs to be fixed... - term2=0.0 - term3=0.0 - if( i1.ge.1 .and. i1+31.le.NP2 ) & - term1=abs(sum(cd0(i1:i1+31)*conjg(ctwk*csync(i,1:32)))) - if( i2.ge.1 .and. i2+31.le.NP2 ) & - term2=abs(sum(cd0(i2:i2+31)*conjg(ctwk*csync(i,1:32)))) - if( i3.ge.1 .and. i3+31.le.NP2 ) & - term3=abs(sum(cd0(i3:i3+31)*conjg(ctwk*csync(i,1:32)))) - sync=sync+term1+term2+term3 - enddo + call sync8d(cd0,i0,ctwk,1,sync) if( sync .gt. smax ) then smax=sync delfbest=delf @@ -108,7 +62,9 @@ subroutine ft8b(dd0,newdat,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr) a(1)=-delfbest call twkfreq1(cd0,NP2,fs2,a,cd0) xdt=xdt2 - f1=f1+delfbest + f1=f1+delfbest !Improved estimate of DF + + call sync8d(cd0,i0,ctwk,2,sync) j=0 do k=1,NN @@ -185,48 +141,7 @@ subroutine ft8b(dd0,newdat,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr) xsnr=10.0*log10(xsnr)-27.0 if( xsnr .lt. -24.0 ) xsnr=-24.0 endif + 900 continue return end subroutine ft8b - -subroutine ft8_downsample(dd,newdat,f0,c1) - -! Downconvert to complex data sampled at 187.5 Hz, 32 samples/symbol - - parameter (NMAX=15*12000) - parameter (NFFT1=200000,NFFT2=3125) !200000/64 = 3125 - logical newdat - complex c1(0:NFFT2-1) - complex cx(0:NFFT1/2) - real dd(NMAX),x(NFFT1) - equivalence (x,cx) - save cx - - if(newdat) then -! Data in dd have changed, recompute the long FFT - x(1:NMAX)=dd - x(NMAX+1:NFFT1)=0. !Zero-pad the x array - call four2a(cx,NFFT1,1,-1,0) !r2c FFT to freq domain - newdat=.false. - endif - - df=12000.0/NFFT1 - baud=12000.0/2048.0 - i0=nint(f0/df) - ft=f0+8.0*baud - it=min(nint(ft/df),NFFT1/2) - fb=f0-1.0*baud - ib=max(1,nint(fb/df)) - k=0 - c1=0. - do i=ib,it - c1(k)=cx(i) - k=k+1 - enddo - c1=cshift(c1,i0-ib) - call four2a(c1,NFFT2,1,1,1) !c2c FFT back to time domain - fac=1.0/sqrt(float(NFFT1)*NFFT2) - c1=fac*c1 - - return -end subroutine ft8_downsample diff --git a/lib/fsk4hf/sync8d.f90 b/lib/fsk4hf/sync8d.f90 new file mode 100644 index 000000000..5bfc8e6b6 --- /dev/null +++ b/lib/fsk4hf/sync8d.f90 @@ -0,0 +1,54 @@ +subroutine sync8d(cd0,i0,ctwk,itwk,sync) + +! Compute sync power for a complex, downsampled FT8 signal. + + parameter(NP2=2812) + complex cd0(3125) + complex csync(0:6,32) + complex csync2(32) + complex ctwk(32) + complex z1,z2,z3 + logical first + integer icos7(0:6) + data icos7/2,5,6,0,4,1,3/ + data first/.true./ + save first,twopi,fs2,dt2,taus,baud,csync + + p(z1)=real(z1)**2 + aimag(z1)**2 !Statement function for power + +! Set some constants and compute the csync array. + if( first ) then + twopi=8.0*atan(1.0) + fs2=12000.0/64.0 !Sample rate after downsampling + dt2=1/fs2 !Corresponding sample interval + taus=32*dt2 !Symbol duration + baud=1/taus !Keying rate + do i=0,6 + phi=0.0 + dphi=twopi*icos7(i)*baud*dt2 + do j=1,32 + csync(i,j)=cmplx(cos(phi),sin(phi)) !Waveform for 7x7 Costas array + phi=mod(phi+dphi,twopi) + enddo + enddo + first=.false. + endif + + sync=0 + do i=0,6 !Sum over 7 Costas frequencies and + i1=i0+i*32 !three Costas arrays + i2=i1+36*32 + i3=i1+72*32 + csync2=csync(i,1:32) + if(itwk.eq.1) csync2=ctwk*csync2 !Tweak the frequency + z1=0. + z2=0. + z3=0. + if(i1.ge.1 .and. i1+31.le.NP2) z1=sum(cd0(i1:i1+31)*conjg(csync2)) + if(i2.ge.1 .and. i2+31.le.NP2) z2=sum(cd0(i2:i2+31)*conjg(csync2)) + if(i3.ge.1 .and. i3+31.le.NP2) z3=sum(cd0(i3:i3+31)*conjg(csync2)) + sync = sync + p(z1) + p(z2) + p(z3) + enddo + + return +end subroutine sync8d diff --git a/mainwindow.cpp b/mainwindow.cpp index 80b3eba24..a86079742 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -882,9 +882,11 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, splashTimer.setSingleShot (true); splashTimer.start (20 * 1000); + ui->actionFT8->setEnabled(false); if(m_config.my_callsign()=="K1JT" or m_config.my_callsign()=="K9AN" or m_config.my_callsign()=="G4WJS" || m_config.my_callsign () == "G3PQA") { ui->actionWSPR_LF->setEnabled(true); + ui->actionFT8->setEnabled(true); } if(!ui->cbMenus->isChecked()) { ui->cbMenus->setChecked(true);