diff --git a/UnitTests.txt b/UnitTests.txt index cac20ff92..f199243bd 100644 --- a/UnitTests.txt +++ b/UnitTests.txt @@ -1,50 +1,78 @@ Mode: Q65-30A -Data: 30A_K1JT_6m_Ionoscatter (62 files, DT 0.1 to 0.4) +Data: 30A_K1JT_6m_Ionoscatter (62 files, 6m ionoscatter DT 0.1 to 0.4) Message: "K1JT K9AN R-16" RxFreq: 1000/10 -Commit No_AP MyCall BothCalls ------------------------------------ -ef4787: 3 10 6 14 30 33 -ada5a6: 3 6 6 10 29 36 +Commit No_AP MyCall BothCalls +----------------------------------------------- +ef4787: 3 10 6 14 30 33 +ada5a6: 3 6 6 10 29 36 +10f574: 2 7 97.6 6 10 95.4 21 33 80.7 +b8ea4c: 2 7 100.5 6 10 96.9 21 33 81.0 Mode: Q65-30A -Data: 30A_N0AN_6m_Ionoscatter (69 files, DT=0 to 0.1) +Data: 30A_N0AN_6m_Ionoscatter (69 files, 6m ionoscatter) Message: "N0AN K1JT -19" RxFreq: 1500/10 -Commit No_AP MyCall BothCalls ------------------------------------ -ef4787: 7 14 16 22 38 40 -70a348: 38 43 -ada5a6: 10 17 11 23 40 46 +Commit No_AP MyCall BothCalls +------------------------------------------------ +ef4787: 7 14 16 22 38 40 +70a348: 38 43 +ada5a6: 10 17 11 23 40 46 +10f574: 8 16 99.4 15 24 91.8 34 44 68.8 +b8ea4c: 8 16 96.0 15 23 92.4 34 44 68.8 Mode: Q65-60B Data: 60B_1296_Troposcatter (75 files) Message: "VK7MO VK7PD QE38" RxFreq: 1000/10 -Commit No_AP MyCall BothCalls ------------------------------------ -ef4787: 1 2 11 23 64 67 -ada5a6: 1 5 14 28 64 67 +Commit No_AP MyCall BothCalls +-------------------------------------------------- +ef4787: 1 2 11 23 64 67 +ada5a6: 1 5 14 28 64 67 +10f574: 1 5 142.7 11 27 129.8 65 67 36.8 +b8ea4c: 1 5 144.3 11 27 132.2 65 67 39.3 Mode: Q65-60D Data: MsgAvg (22 files, simulated fDop = 50 Hz) Message: "K1ABC W9XYZ EN37" RxFreq: 1000/10 -Commit No_AP MyCall BothCalls ------------------------------------ -ef4787: 0 10 21 21 22 22 -ada5a6 0 11 21 21 22 22 +Commit No_AP MyCall BothCalls +------------------------------------------------ +ef4787: 0 10 21 21 22 22 +ada5a6 0 11 21 21 22 22 +10f574: 0 11 47.7 21 21 33.9 22 22 11.6 +b8ea4c: 0 11 46.4 21 21 33.8 22 22 11.9 Mode: Q65-60D -Data: Nil Average (40 files, simulated fDop = 0? Hz ) +Data: 60D_2 (21 files, 1296 troposcatter) Message: "VK7MO VK3WE QF32" -RxFreq: 1200/20 -Requires nsmo=1 ### +RxFreq: 1000/20 -Commit No_AP MyCall BothCalls ------------------------------------ -ef4787: 1 16 24 28 39 39 +Commit No_AP MyCall BothCalls +---------------------------------------------- +10f574: 5 5 33.6 7 8 31.8 12 14 25.1 +b8ea4v: 5 5 39.1 7 8 38.0 13 14 30.8 + +Mode: Q65-120D +Data: 120D (14 files, 10 GHz troposcatter) +Message: "VK7MO VK3WE QF32" +RxFreq: 1000/20 + +Commit No_AP MyCall BothCalls +---------------------------------------------- +10f574: 0 0 24.9 0 0 25.0 1 4 25.0 +b8ea4v: 0 0 39.1 0 0 25.4 1 5 40.1 + +Mode: Q65-60D +Data: 60D_10_GHz_EME (14 files) +Message: "VK7MO K6QPV DM12", "VK7MO K6QPV -15" +RxFreq: 1000/50 + +Commit No_AP MyCall BothCalls +---------------------------------------------- +10f574: 9 10 13.6 10 11 12.7 14 14 7.1 +b8ea4v: 9 10 13.7 10 11 12.6 14 14 7.5 diff --git a/lib/ana64.f90 b/lib/ana64.f90 index 1f3b54820..f7586756e 100644 --- a/lib/ana64.f90 +++ b/lib/ana64.f90 @@ -1,16 +1,16 @@ -subroutine ana64(dd,npts,c0) +subroutine ana64(iwave,npts,c0) use timer_module, only: timer - real dd(npts) !Raw data at 12000 Hz + integer*2 iwave(npts) !Raw data at 12000 Hz complex c0(0:npts-1) !Complex data at 6000 Hz save nfft1=npts nfft2=nfft1/2 df1=12000.0/nfft1 - fac=2.0/nfft1 - c0(0:npts-1)=fac*dd(1:npts) + fac=2.0/(32767.0*nfft1) + c0(0:npts-1)=fac*iwave(1:npts) call four2a(c0,nfft1,1,-1,1) !Forward c2c FFT c0(nfft2/2+1:nfft2-1)=0. c0(0)=0.5*c0(0) diff --git a/lib/decoder.f90 b/lib/decoder.f90 index 4129cd481..5a254a56b 100644 --- a/lib/decoder.f90 +++ b/lib/decoder.f90 @@ -205,11 +205,12 @@ subroutine multimode_decoder(ss,id2,params,nfsample) 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,params%nutc,params%ntr, & - params%nsubmode,params%nfqso,params%ntol,params%ndepth, & - params%nfa,params%nfb,logical(params%nclearave), & - params%emedelay,mycall,hiscall,hisgrid,params%nQSOProgress, & - ncontest,logical(params%lapcqonly),navg0) + call my_q65%decode(q65_decoded,id2,params%nutc,params%ntr, & + params%nsubmode,params%nfqso,params%ntol,params%ndepth, & + params%nfa,params%nfb,logical(params%nclearave), & + single_decode,logical(params%nagain), & + logical(params%newdat),params%emedelay,mycall,hiscall,hisgrid, & + params%nQSOProgress,ncontest,logical(params%lapcqonly),navg0) call timer('dec_q65 ',1) close(17) go to 800 diff --git a/lib/q65_decode.f90 b/lib/q65_decode.f90 index 86ecdb9d5..0bea7d8ee 100644 --- a/lib/q65_decode.f90 +++ b/lib/q65_decode.f90 @@ -26,9 +26,9 @@ module q65_decode contains - subroutine decode(this,callback,iwave,nutc,ntrperiod,nsubmode,nfqso, & - ntol,ndepth,nfa0,nfb0,lclearave,emedelay,mycall,hiscall,hisgrid, & - nQSOprogress,ncontest,lapcqonly,navg0) + subroutine decode(this,callback,iwave,nutc,ntrperiod,nsubmode,nfqso, & + ntol,ndepth,nfa0,nfb0,lclearave,single_decode,lagain,lnewdat0, & + emedelay,mycall,hiscall,hisgrid,nQSOprogress,ncontest,lapcqonly,navg0) ! Top-level routine that organizes the decoding of Q65 signals ! Input: iwave Raw data, i*2 @@ -49,6 +49,7 @@ contains use packjt77 use, intrinsic :: iso_c_binding use q65 !Shared variables + use prog_args parameter (NMAX=300*12000) !Max TRperiod is 300 s class(q65_decoder), intent(inout) :: this @@ -59,18 +60,26 @@ contains character*77 c77 character*78 c78 character*6 cutc + character c6*6,c4*4,cmode*4 + character*80 fmt integer*2 iwave(NMAX) !Raw data real, allocatable :: dd(:) !Raw data integer dat4(13) !Decoded message as 12 6-bit integers integer dgen(13) - logical lclearave,lapcqonly,unpk77_success + logical lclearave,lnewdat0,lapcqonly,unpk77_success + logical single_decode,lagain complex, allocatable :: c00(:) !Analytic signal, 6000 Sa/s complex, allocatable :: c0(:) !Analytic signal, 6000 Sa/s ! Start by setting some parameters and allocating storage for large arrays + call sec0(0,tdecode) nfa=nfa0 nfb=nfb0 + lnewdat=lnewdat0 idec=-1 + idf=0 + idt=0 + irc=0 mode_q65=2**nsubmode npts=ntrperiod*12000 nfft1=ntrperiod*12000 @@ -106,9 +115,12 @@ contains baud=12000.0/nsps this%callback => callback nFadingModel=1 - ibwa=max(1,int(1.8*log(baud*mode_q65)) + 2) - ibwb=min(10,ibwa+4) - if(iand(ndepth,3).eq.3) then + ibwa=max(1,int(1.8*log(baud*mode_q65)) + 1) + ibwb=min(10,ibwa+3) + if(iand(ndepth,3).ge.2) then + ibwa=max(1,int(1.8*log(baud*mode_q65)) + 2) + ibwb=min(10,ibwa+5) + else if(iand(ndepth,3).eq.3) then ibwa=max(1,ibwa-1) ibwb=min(10,ibwb+1) endif @@ -128,24 +140,16 @@ contains call timer('q65_dec0',1) if(idec.ge.0) then - dtdec=xdt !We have a list-decode result + dtdec=xdt !We have a list-decode result at nfqso f0dec=f0 go to 100 endif - if(snr1.lt.2.8) then - dtdec=0. !No reliable sync, abandon decoding attempt - f0dec=0. - go to 100 - endif - -! Prepare for a single-period decode woth iaptype = 0, 1, or 2 (also 4?) +! Prepare for a single-period decode with iaptype = 0, 1, 2, or 4 jpk0=(xdt+1.0)*6000 !Index of nominal start of signal if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000 !For shortest sequences if(jpk0.lt.0) jpk0=0 - fac=1.0/32767.0 - dd=fac*iwave(1:npts) - call ana64(dd,npts,c00) !Convert to complex c00() at 6000 Sa/s + call ana64(iwave,npts,c00) !Convert to complex c00() at 6000 Sa/s call ft8apset(mycall,hiscall,ncontest,apsym0,aph10) ! Generate ap symbols where(apsym0.eq.-1) apsym0=0 @@ -196,7 +200,7 @@ contains go to 100 endif -! There was no 'q3n' decode. Try for a 'q[012]n' decode. +! There was no 'q3n' decode. Try for a 'q[0124]n' decode. ! Call top-level routine in q65 module: establish sync and try for a q[012]n ! decode, this time using the cumulative 's1a' symbol spectra. @@ -229,17 +233,109 @@ contains call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & idec,nused,ntrperiod) if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode + call sec0(1,tdecode) + 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 + cmode(4:4)=char(ichar('A')+nsubmode) + c6=hiscall(1:6) + if(c6.eq.' ') c6=' ' + c4=hisgrid(1:4) + if(c4.eq.' ') c4=' ' + fmt='(i6.4,1x,a4,5i2,3i3,f6.2,f7.1,f7.2,f6.1,f6.2,'// & + '1x,a6,1x,a6,1x,a4,1x,a)' + if(ntrperiod.le.30) fmt(5:5)='6' + write(22,fmt) nutc,cmode,nQSOprogress,idec,idf,idt,ibw,nused, & + icand,ncand,xdt,f0,snr1,snr2,tdecode,mycall(1:6),c6,c4, & + trim(decoded) + close(22) + endif else ! Report snr1, even if no decode. nsnr=db(snr1) - 35.0 if(nsnr.lt.-35) nsnr=-35 idec=-1 - call this%callback(nutc,snr1,nsnr,xdt,f0,decoded, & + call this%callback(nutc,snr1,nsnr,xdt,f0,decoded, & idec,0,ntrperiod) endif navg0=1000*navg(0) + navg(1) + if(single_decode .or. lagain) go to 900 - return + do icand=1,ncand +! Prepare for single-period candidate decodes with iaptype = 0, 1, 2, or 4 + snr1=candidates(icand,1) + xdt= candidates(icand,2) + f0 = candidates(icand,3) + jpk0=(xdt+1.0)*6000 !Index of nominal start of signal + if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000 !For shortest sequences + if(jpk0.lt.0) jpk0=0 + call ana64(iwave,npts,c00) !Convert to complex c00() at 6000 Sa/s + call ft8apset(mycall,hiscall,ncontest,apsym0,aph10) ! Generate ap symbols + where(apsym0.eq.-1) apsym0=0 + + npasses=2 + if(nQSOprogress.eq.5) npasses=3 + if(lapcqonly) npasses=1 + iaptype=0 + do ipass=0,npasses !Loop over AP passes + apmask=0 !Try first with no AP information + apsymbols=0 + if(ipass.ge.1) then + ! Subsequent passes use AP information appropiate for nQSOprogress + call q65_ap(nQSOprogress,ipass,ncontest,lapcqonly,iaptype, & + apsym0,apmask1,apsymbols1) + write(c78,1050) apmask1 + read(c78,1060) apmask + write(c78,1050) apsymbols1 + read(c78,1060) apsymbols + endif + + call timer('q65loops',0) + call q65_loops(c00,npts/2,nsps/2,nsubmode,ndepth,jpk0, & + xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec) +! idec=-1 !### TEMPORARY ### + call timer('q65loops',1) + if(idec.ge.0) then + dtdec=xdt1 + f0dec=f1 + go to 200 !Successful decode, we're done + endif + enddo ! ipass + +200 decoded=' ' + if(idec.ge.0) then +! Unpack decoded message for display to user + write(c77,1000) dat4(1:12),dat4(13)/2 + call unpack77(c77,0,decoded,unpk77_success) !Unpack to get msgsent + nsnr=nint(snr2) + call this%callback(nutc,snr1,nsnr,dtdec,f0dec,decoded, & + idec,nused,ntrperiod) + if(iand(ndepth,128).ne.0) call q65_clravg !AutoClrAvg after decode + call sec0(1,tdecode) + 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 + cmode(4:4)=char(ichar('A')+nsubmode) + c6=hiscall(1:6) + if(c6.eq.' ') c6=' ' + c4=hisgrid(1:4) + if(c4.eq.' ') c4=' ' + fmt='(i6.4,1x,a4,5i2,3i3,f6.2,f7.1,f7.2,f6.1,f6.2,'// & + '1x,a6,1x,a6,1x,a4,1x,a)' + if(ntrperiod.le.30) fmt(5:5)='6' + write(22,fmt) nutc,cmode,nQSOprogress,idec,idf,idt,ibw,nused, & + icand,ncand,xdt,f0,snr1,snr2,tdecode,mycall(1:6),c6,c4, & + trim(decoded) + close(22) + endif + endif + enddo + +900 return end subroutine decode end module q65_decode diff --git a/lib/qra/q65/q65.f90 b/lib/qra/q65/q65.f90 index bca660c43..106df8a3c 100644 --- a/lib/qra/q65/q65.f90 +++ b/lib/qra/q65/q65.f90 @@ -11,12 +11,15 @@ module q65 38,46,50,55,60,62,66,69,74,76,85/) integer codewords(63,206) integer ibwa,ibwb,ncw,nsps,mode_q65,nfa,nfb - integer istep,nsmo,lag1,lag2,npasses,nused,iseq + integer idf,idt,ibw + integer istep,nsmo,lag1,lag2,npasses,nused,iseq,ncand integer i0,j0 integer navg(0:1) + logical lnewdat + real candidates(20,3) !snr, xdt, and f0 of top candidates real,allocatable,save :: s1a(:,:,:) !Cumulative symbol spectra real sync(85) !sync vector - real df,dtstep,dtdec,f0dec + real df,dtstep,dtdec,f0dec,ftol contains @@ -59,9 +62,8 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & logical first,lclearave real, allocatable :: s1(:,:) !Symbol spectra, 1/8-symbol steps real, allocatable :: s3(:,:) !Data-symbol energies s3(LL,63) - real, allocatable :: ccf(:,:) !CCF(freq,lag) - real, allocatable :: ccf1(:) !CCF(freq) at best lag - real, allocatable :: ccf2(:) !CCF(freq) at any lag + real, allocatable :: ccf1(:) !CCF(freq) at fixed lag (red) + real, allocatable :: ccf2(:) !Max CCF(freq) at any lag (orange) data first/.true./ save first @@ -80,6 +82,7 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & txt=85.0*nsps/12000.0 jz=(txt+1.0)*12000.0/istep !Number of symbol/NSTEP bins if(nsps.ge.6912) jz=(txt+2.0)*12000.0/istep !For TR 60 s and higher + ftol=ntol ia=ntol/df ia2=max(ia,10*mode_q65,nint(100.0/df)) nsmo=int(0.7*mode_q65*mode_q65) @@ -93,9 +96,8 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & allocate(s1(iz,jz)) allocate(s3(-64:LL-65,63)) - allocate(ccf(-ia2:ia2,-53:214)) allocate(ccf1(-ia2:ia2)) - allocate(ccf2(-ia2:ia2)) + allocate(ccf2(iz)) if(LL.ne.LL0 .or. iz.ne.iz0 .or. jz.ne.jz0 .or. lclearave) then if(allocated(s1a)) deallocate(s1a) allocate(s1a(iz,jz,0:1)) @@ -140,59 +142,36 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & ! Try list decoding via "Deep Likelihood". call timer('ccf_85 ',0) ! Try to synchronize using all 85 symbols - call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf,ccf1) + call q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) call timer('ccf_85 ',1) call timer('list_dec',0) call q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) call timer('list_dec',1) - if(idec.ne.0) then - ic=ia2/4; - base=(sum(ccf1(-ia2:-ia2+ic)) + sum(ccf1(ia2-ic:ia2)))/(2.0+2.0*ic); - ccf1=ccf1-base - smax=maxval(ccf1) - if(smax.gt.10.0) ccf1=10.0*ccf1/smax - base=(sum(ccf2(-ia2:-ia2+ic)) + sum(ccf2(ia2-ic:ia2)))/(2.0+2.0*ic); - ccf2=ccf2-base - smax=maxval(ccf2) - if(smax.gt.10.0) ccf2=10.0*ccf2/smax - endif endif ! Get 2d CCF and ccf2 using sync symbols only - call q65_ccf_22(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0a,xdta,ccf,ccf2) + call q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0a,xdta,ccf2) if(idec.lt.0) then f0=f0a xdt=xdta endif -! Estimate rms on ccf baseline - sq=0. - nsq=0 - jd=(lag2-lag1)/4 - do i=-ia2,ia2 - do j=lag1,lag2 - if(abs(j-jpk).gt.jd .and. abs(i-ipk).gt.ia/2) then - sq=sq + ccf(i,j)**2 - nsq=nsq+1 - endif - enddo - enddo - rms=sqrt(sq/nsq) - smax=ccf(ipk,jpk) - snr1=smax/rms - ccf2=ccf2/rms - if(snr1.gt.10.0) ccf2=(10.0/snr1)*ccf2 +! Estimate rms on ccf2 baseline + call q65_sync_curve(ccf2,1,iz,rms2) + smax=maxval(ccf2) + snr1=0. + if(rms2.gt.0) snr1=smax/rms2 if(idec.le.0) then -! The q3 decode attempt failed. Copy synchronied symbol spectra from s1 +! The q3 decode attempt failed. Copy synchronized symbol energies from s1 ! into s3 and prepare to try a more general decode. - ccf1=ccf(:,jpk)/rms - if(snr1.gt.10.0) ccf1=(10.0/snr1)*ccf1 call q65_s1_to_s3(s1,iz,jz,ipk,jpk,LL,mode_q65,sync,s3) endif smax=maxval(ccf1) + +! Estimate frequenct spread i1=-9999 i2=-9999 do i=-ia,ia @@ -201,16 +180,8 @@ subroutine q65_dec0(iavg,nutc,iwave,ntrperiod,nfqso,ntol,ndepth,lclearave, & enddo width=df*(i2-i1) -! Write data for the red and orange sync curves. - do i=-ia2,ia2 - freq=nfqso + i*df - if(freq.ge.float(nfa) .and. freq.le.float(nfb)) then - write(17,1100) freq,ccf1(i),xdt,ccf2(i) -1100 format(4f10.3) - endif - enddo - rewind 17 - + if(ncw.eq.0) ccf1=0. + call q65_write_red(iz,ia2,xdt,ccf1,ccf2) if(iavg.eq.2) then call q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) @@ -261,43 +232,31 @@ subroutine q65_symspec(iwave,nmax,iz,jz,s1) call smo121(s1(1:iz,j),iz) enddo enddo - s1a(:,:,iseq)=s1a(:,:,iseq) + s1 - navg(iseq)=navg(iseq) + 1 + if(lnewdat) then + s1a(:,:,iseq)=s1a(:,:,iseq) + s1 + navg(iseq)=navg(iseq) + 1 + endif return end subroutine q65_symspec subroutine q65_dec_q3(s1,iz,jz,s3,LL,ipk,jpk,snr2,dat4,idec,decoded) -! Copy synchronized symbol spectra from s1 into s3, then attempt a q3 decode. +! Copy synchronized symbol energies from s1 into s3, then attempt a q3 decode. character*37 decoded integer dat4(13) real s1(iz,jz) real s3(-64:LL-65,63) - i1=i0+ipk-64 - i2=i1+LL-1 - j=j0+jpk-7 - n=0 - do k=1,85 - j=j+8 - if(sync(k).gt.0.0) then - cycle - endif - n=n+1 - if(j.ge.1 .and. j.le.jz) then - do i=0,LL-1 - s3(i-64,n)=s1(i+i1,j) !Copy from s1 into s3 - enddo - endif - enddo + call q65_s1_to_s3(s1,iz,jz,ipk,jpk,LL,mode_q65,sync,s3) nsubmode=0 if(mode_q65.eq.2) nsubmode=1 if(mode_q65.eq.4) nsubmode=2 if(mode_q65.eq.8) nsubmode=3 if(mode_q65.eq.16) nsubmode=4 + if(mode_q65.eq.32) nsubmode=5 baud=12000.0/nsps do ibw=ibwa,ibwb @@ -366,17 +325,18 @@ subroutine q65_dec_q012(s3,LL,snr2,dat4,idec,decoded) 100 return end subroutine q65_dec_q012 -subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf,ccf1) +subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf1) ! Attempt synchronization using all 85 symbols, in advance of an ! attempt at q3 decoding. Return ccf1 for the "red sync curve". real s1(iz,jz) - real ccf(-ia2:ia2,-53:214) + real, allocatable :: ccf(:,:) !CCF(freq,lag) real ccf1(-ia2:ia2) integer ijpk(2) integer itone(85) - + + allocate(ccf(-ia2:ia2,-53:214)) ipk=0 jpk=0 ccf_best=0. @@ -387,10 +347,10 @@ subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf,ccf1) do j=1,85 if(j.eq.isync(i)) then i=i+1 - itone(j)=-1 + itone(j)=0 else k=k+1 - itone(j)=codewords(k,imsg) + itone(j)=codewords(k,imsg) + 1 endif enddo @@ -416,48 +376,90 @@ subroutine q65_ccf_85(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,imsg_best,ccf,ccf1) ijpk=maxloc(ccf(-ia:ia,:)) ipk=ijpk(1)-ia-1 jpk=ijpk(2)-53-1 - f0=nfqso + (ipk-mode_q65)*df + f0=nfqso + ipk*df xdt=jpk*dtstep imsg_best=imsg ccf1=ccf(:,jpk) endif enddo ! imsg + deallocate(ccf) return end subroutine q65_ccf_85 -subroutine q65_ccf_22(s1,iz,jz,nfqso,ia,ia2,ipk,jpk,f0,xdt,ccf,ccf2) +subroutine q65_ccf_22(s1,iz,jz,nfqso,ipk,jpk,f0,xdt,ccf2) ! Attempt synchronization using only the 22 sync symbols. Return ccf2 ! for the "orange sync curve". - - real s1(iz,jz) - real ccf(-ia2:ia2,-53:214) - real ccf2(-ia2:ia2) - integer ijpk(2) - ccf=0. - do lag=lag1,lag2 - do k=1,85 - n=NSTEP*(k-1) + 1 - j=n+lag+j0 - if(j.ge.1 .and. j.le.jz) then - do i=-ia2,ia2 - if(i0+i.lt.1 .or. i0+i.gt.iz) cycle - ccf(i,lag)=ccf(i,lag) + sync(k)*s1(i0+i,j) - enddo + real s1(iz,jz) + real ccf2(iz) !Orange sync curve + real, allocatable :: xdt2(:) + integer, allocatable :: indx(:) + + allocate(xdt2(iz)) + allocate(indx(iz)) + + ccfbest=0. + ibest=0 + lagpk=0 + lagbest=0 + do i=1,iz + ccfmax=0. + do lag=lag1,lag2 + ccft=0. + do k=1,85 + n=NSTEP*(k-1) + 1 + j=n+lag+j0 + if(j.ge.1 .and. j.le.jz) then + ccft=ccft + sync(k)*s1(i,j) + endif + enddo + if(ccft.gt.ccfmax) then + ccfmax=ccft + lagpk=lag endif enddo + ccf2(i)=ccfmax + xdt2(i)=lagpk*dtstep + if(ccfmax.gt.ccfbest .and. abs(i*df-nfqso).le.ftol) then + ccfbest=ccfmax + ibest=i + lagbest=lagpk + endif enddo - do i=-ia2,ia2 - ccf2(i)=maxval(ccf(i,:)) - enddo - ijpk=maxloc(ccf(-ia:ia,:)) - ipk=ijpk(1)-ia-1 - jpk=ijpk(2)-53-1 + +! Parameters for the top candidate: + ipk=ibest - i0 + jpk=lagbest f0=nfqso + ipk*df xdt=jpk*dtstep +! Save parameters for best candidates + i1=max(nfa,100)/df + i2=min(nfb,4900)/df + jzz=i2-i1+1 + call pctile(ccf2(i1:i2),jzz,40,base) + ccf2=ccf2/base + call indexx(ccf2(i1:i2),jzz,indx) + ncand=0 + maxcand=20 + do j=1,20 + i=indx(jzz-j+1)+i1-1 + if(ccf2(i).lt.3.4) exit !Candidate limit + f=i*df + if(f.ge.(nfqso-ftol) .and. f.le.(nfqso+ftol)) cycle + i3=max(1,i-67*mode_q65) + i4=min(iz,i+3*mode_q65) + biggest=maxval(ccf2(i3:i4)) + if(ccf2(i).ne.biggest) cycle + ncand=ncand+1 + candidates(ncand,1)=ccf2(i) + candidates(ncand,2)=xdt2(i) + candidates(ncand,3)=f + if(ncand.ge.maxcand) exit + enddo + return end subroutine q65_ccf_22 @@ -539,4 +541,52 @@ subroutine q65_s1_to_s3(s1,iz,jz,ipk,jpk,LL,mode_q65,sync,s3) return end subroutine q65_s1_to_s3 +subroutine q65_write_red(iz,ia2,xdt,ccf1,ccf2) + +! Write data for the red and orange sync curves to LU 17. + + real ccf1(-ia2:ia2) + real ccf2(iz) + + call q65_sync_curve(ccf1,-ia2,ia2,rms1) + call q65_sync_curve(ccf2,1,iz,rms2) + + rewind 17 + write(17,1000) xdt + do i=1,iz + freq=i*df + ii=i-i0 + if(freq.ge.float(nfa) .and. freq.le.float(nfb)) then + ccf1a=-99.0 + if(ii.ge.-ia2 .and. ii.le.ia2) ccf1a=ccf1(ii) + write(17,1000) freq,ccf1a,ccf2(i) +1000 format(3f10.3) + endif + enddo + + return +end subroutine q65_write_red + +subroutine q65_sync_curve(ccf1,ia,ib,rms1) + +! Condition the red or orange sync curve for plotting. + + real ccf1(ia:ib) + + ic=(ib-ia)/8; + nsum=2*(ic+1) + + base1=(sum(ccf1(ia:ia+ic)) + sum(ccf1(ib-ic:ib)))/nsum + ccf1=ccf1-base1 + sq=dot_product(ccf1(ia:ia+ic),ccf1(ia:ia+ic)) + & + dot_product(ccf1(ib-ic:ib),ccf1(ib-ic:ib)) + rms1=0. + if(nsum.gt.0) rms1=sqrt(sq/nsum) + if(rms1.gt.0.0) ccf1=2.0*ccf1/rms1 + smax1=maxval(ccf1) + if(smax1.gt.10.0) ccf1=10.0*ccf1/smax1 + + return +end subroutine q65_sync_curve + end module q65 diff --git a/lib/qra/q65/q65_loops.f90 b/lib/qra/q65/q65_loops.f90 index 808f45283..092997e69 100644 --- a/lib/qra/q65/q65_loops.f90 +++ b/lib/qra/q65/q65_loops.f90 @@ -6,7 +6,7 @@ subroutine q65_loops(c00,npts2,nsps2,nsubmode,ndepth,jpk0, & use q65 parameter (NN=63) - parameter (LN=1152*63) !LN=LL*NN; LL=64*(mode_q65+2), NN=63 + parameter (LN=2176*63) !LN=LL*NN; LL=64*(mode_q65+2), NN=63 complex c00(0:npts2-1) !Analytic representation of dd(), 6000 Hz complex ,allocatable :: c0(:) !Ditto, with freq shift character decoded*37 @@ -51,7 +51,7 @@ subroutine q65_loops(c00,npts2,nsps2,nsubmode,ndepth,jpk0, & jpk=jpk0 + nsps2*ndt/16 !tsym/16 if(jpk.lt.0) jpk=0 call timer('spec64 ',0) - call spec64(c0,nsps2,65,mode_q65,jpk,s3,LL,NN) + call spec64(c0,nsps2,mode_q65,jpk,s3,LL,NN) call timer('spec64 ',1) call pctile(s3,LL*NN,40,base) s3=s3/base @@ -75,9 +75,6 @@ subroutine q65_loops(c00,npts2,nsps2,nsubmode,ndepth,jpk0, & enddo ! idf (f0 loop) 100 if(irc.ge.0) then -! write(55,3055) ndepth,iaptype,idf,idt,ibw,ndist,irc,sum(s3(1:LL*NN)), & -! trim(decoded) -!3055 format(7i4,f10.1,1x,a) idec=iaptype snr2=esnodb - db(2500.0/baud) xdt1=xdt0 + nsps2*ndt/(16.0*6000.0) diff --git a/lib/qra64a.f90 b/lib/qra64a.f90 deleted file mode 100644 index d4189827d..000000000 --- a/lib/qra64a.f90 +++ /dev/null @@ -1,128 +0,0 @@ -subroutine qra64a(dd,npts,nf1,nf2,nfqso,ntol,mode64,minsync,ndepth, & - emedelay,mycall_12,hiscall_12,hisgrid_6,sync,nsnr,dtx,nfreq,decoded,nft) - - use packjt - use timer_module, only: timer - - parameter (NMAX=60*12000,LN=1152*63) - character decoded*22 - character*12 mycall_12,hiscall_12 - character*6 mycall,hiscall,hisgrid_6 - character*4 hisgrid - logical ltext - complex c00(0:720000) !Analytic signal for dd() - real dd(NMAX) !Raw data sampled at 12000 Hz - integer dat4(12) !Decoded message (as 12 integers) - data nc1z/-1/,nc2z/-1/,ng2z/-1/,maxaptypez/-1/ - save - - call timer('qra64a ',0) - irc=-1 - decoded=' ' - nft=99 - if(nfqso.lt.nf1 .or. nfqso.gt.nf2) go to 900 - - mycall=mycall_12(1:6) !### May need fixing? ### - hiscall=hiscall_12(1:6) - hisgrid=hisgrid_6(1:4) - call packcall(mycall,nc1,ltext) - call packcall(hiscall,nc2,ltext) - call packgrid(hisgrid,ng2,ltext) - nSubmode=0 - if(mode64.eq.2) nSubmode=1 - if(mode64.eq.4) nSubmode=2 - if(mode64.eq.8) nSubmode=3 - if(mode64.eq.16) nSubmode=4 - b90=1.0 - nFadingModel=1 - maxaptype=4 - if(iand(ndepth,64).ne.0) maxaptype=5 - call qra_params(ndepth,maxaptype,idfmax,idtmax,ibwmin,ibwmax,maxdist) - if(nc1.ne.nc1z .or. nc2.ne.nc2z .or. ng2.ne.ng2z .or. & - maxaptype.ne.maxaptypez) then - do naptype=0,maxaptype - if(naptype.eq.2 .and. maxaptype.eq.4) cycle - call qra64_dec(s3dummy,nc1,nc2,ng2,naptype,1,nSubmode,b90, & - nFadingModel,dat4,snr2,irc) - enddo - nc1z=nc1 - nc2z=nc2 - ng2z=ng2 - maxaptypez=maxaptype - endif - naptype=maxaptype - - call ana64(dd,npts,c00) - - call timer('sync64 ',0) - call sync64(c00,nf1,nf2,nfqso,ntol,minsync,mode64,emedelay,dtx,f0, & - jpk0,sync,sync2,width) - call timer('sync64 ',1) - nfreq=nint(f0) - if(mode64.eq.1 .and. minsync.ne.-1 .and. (sync-7.0).lt.minsync) go to 900 - - nsps=6912 - call timer('qraloops',0) - call qra_loops(c00,npts/2,nsps,64,mode64,nsubmode,nFadingModel, & - ndepth,nc1,nc2,ng2,naptype,jpk0,dtx,f0,width,snr2,irc,dat4) - call timer('qraloops',1) - - decoded=' ' - if(irc.ge.0) then - call unpackmsg(dat4,decoded) !Unpack the user message - call fmtmsg(decoded,iz) - if(index(decoded,"000AAA ").ge.1) then - ! Suppress a certain type of garbage decode. - decoded=' ' - irc=-1 - endif - nft=100 + irc - nsnr=nint(snr2) - else - snr2=0. - endif - nfreq=nint(f0) - -900 if(irc.lt.0) then - sy=max(1.0,sync) - if(nSubmode.eq.0) nsnr=nint(10.0*log10(sy)-35.0) !A - if(nSubmode.eq.1) nsnr=nint(10.0*log10(sy)-34.0) !B - if(nSubmode.eq.2) nsnr=nint(10.0*log10(sy)-29.0) !C - if(nSubmode.eq.3) nsnr=nint(10.0*log10(sy)-29.0) !D - if(nSubmode.eq.4) nsnr=nint(10.0*log10(sy)-24.0) !E - endif - call timer('qra64a ',1) - - return -end subroutine qra64a - -subroutine qra_params(ndepth,maxaptype,idf0max,idt0max,ibwmin,ibwmax,maxdist) - -! If file qra_params is present in CWD, read decoding params from it. - - integer iparam(7) - logical first,ex -! data iparam/3,5,11,11,0,11,60/ !Maximum effort - data iparam/3,5,7,7,0,4,15/ !Default values - data first/.true./ - save first,iparam - - if(first) then - inquire(file='qra_params',exist=ex) - if(ex) then - open(29,file='qra_params',status='old') - read(29,*) iparam - close(29) - endif - first=.false. - endif - ndepth=iparam(1) - maxaptype=iparam(2) - idf0max=iparam(3) - idt0max=iparam(4) - ibwmin=iparam(5) - ibwmax=iparam(6) - maxdist=iparam(7) - - return -end subroutine qra_params diff --git a/lib/spec64.f90 b/lib/spec64.f90 index cf43994dc..b3b7d54d6 100644 --- a/lib/spec64.f90 +++ b/lib/spec64.f90 @@ -1,4 +1,4 @@ -subroutine spec64(c0,nsps,mode,mode64,jpk,s3,LL,NN) +subroutine spec64(c0,nsps,mode_q65,jpk,s3,LL,NN) parameter (MAXFFT=20736) !### Fix this: @@ -11,41 +11,24 @@ subroutine spec64(c0,nsps,mode,mode64,jpk,s3,LL,NN) data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/ nfft=nsps - - if(mode.eq.64) then - do j=1,NN - jj=j+7 !Skip first Costas array - if(j.ge.33) jj=j+14 !Skip middle Costas array - ja=jpk + (jj-1)*nfft - jb=ja+nfft-1 - cs(0:nfft-1)=c0(ja:jb) - call four2a(cs,nfft,1,-1,1) - do ii=1,LL - i=ii-65 - if(i.lt.0) i=i+nfft - s3(ii,j)=real(cs(i))**2 + aimag(cs(i))**2 - enddo + j=0 + n=1 + do k=1,84 + if(k.eq.isync(n)) then + n=n+1 + cycle + endif + j=j+1 + ja=(k-1)*nsps + jpk + jb=ja+nsps-1 + cs(0:nfft-1)=c0(ja:jb) + call four2a(cs,nsps,1,-1,1) !c2c FFT to frequency + do ii=1,LL + i=ii-65+mode_q65 !mode_q65 = 1 2 4 8 16 for Q65 A B C D E + if(i.lt.0) i=i+nsps + s3(ii,j)=real(cs(i))**2 + aimag(cs(i))**2 enddo - else - j=0 - n=1 - do k=1,84 - if(k.eq.isync(n)) then - n=n+1 - cycle - endif - j=j+1 - ja=(k-1)*nsps + jpk - jb=ja+nsps-1 - cs(0:nfft-1)=c0(ja:jb) - call four2a(cs,nsps,1,-1,1) !c2c FFT to frequency - do ii=1,LL - i=ii-65+mode64 !mode64 = 1 2 4 8 16 for Q65 A B C D E - if(i.lt.0) i=i+nsps - s3(ii,j)=real(cs(i))**2 + aimag(cs(i))**2 - enddo - enddo - endif + enddo df=6000.0/nfft do i=1,LL diff --git a/lib/test_q65.f90 b/lib/test_q65.f90 index dc54f0ad0..29d3ebef8 100644 --- a/lib/test_q65.f90 +++ b/lib/test_q65.f90 @@ -73,7 +73,7 @@ program test_q65 ! 1 2 3 4 5 6 7 ! 123456789012345678901234567890123456789012345678901234567890123456789012345' cmd1='q65sim "K1ABC W9XYZ EN37 " A 1500 5.0 0.0 0.0 1 60 100 -10.0 > junk0' - cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 3 -b A -Q 3 -f 1500 *.wav > junk' + cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 3 -b A -Q 3 -f 1500 *.wav > junk' write(cmd1(10:33),'(a)') '"'//msg//'"' cmd1(35:35)=csubmode @@ -86,10 +86,10 @@ program test_q65 write(cmd1(62:66),'(i5)') nfiles write(cmd2(11:13),'(i3)') ntrperiod - write(cmd2(33:34),'(i2)') ndepth - write(cmd2(44:44),'(i1)') nQSOprogress - write(cmd2(49:52),'(i4)') nf0 - cmd2(39:39)=csubmode + write(cmd2(33:35),'(i3)') ndepth + write(cmd2(45:45),'(i1)') nQSOprogress + write(cmd2(50:53),'(i4)') nf0 + cmd2(40:40)=csubmode call system('rm -f *.wav') @@ -142,13 +142,14 @@ program test_q65 if(line(i0:i0).ne.' ') then i1=index(line,'q') idec=-1 - read(line(i1+1:),*) idec - endif - if(idec.lt.0) cycle - if(idec.ge.12) then - iavg=idec-10 - idec=1 + read(line(i1+1:i1+1),*) idec + if(line(i1+2:i1+2).eq.'*') then + iavg=10 + else + read(line(i1+2:i1+2),*,end=100) iavg + endif endif +100 if(idec.lt.0) cycle if(decok) then ndecn=ndecn + 1 if(iavg.le.1) ndec1=ndec1 + 1 diff --git a/samples/QRA64/QRA64C/161113_0111.wav b/samples/QRA64/QRA64C/161113_0111.wav deleted file mode 100644 index 03dec21bb..000000000 Binary files a/samples/QRA64/QRA64C/161113_0111.wav and /dev/null differ diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 397ca12af..132f8aa4c 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -3054,6 +3054,7 @@ void MainWindow::on_ClrAvgButton_clicked() if(m_msgAvgWidget != NULL) { if(m_msgAvgWidget->isVisible()) m_msgAvgWidget->displayAvg(""); } + if(m_mode=="Q65") ndecodes_label.setText("0 0"); } void MainWindow::msgAvgDecode2() diff --git a/widgets/plotter.cpp b/widgets/plotter.cpp index 2181bc619..14c13a50d 100644 --- a/widgets/plotter.cpp +++ b/widgets/plotter.cpp @@ -141,7 +141,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed) //move current data down one line (must do this before attaching a QPainter object) if(bScroll and !m_bReplot) m_WaterfallPixmap.scroll(0,1,0,0,m_w,m_h1); QPainter painter1(&m_WaterfallPixmap); - if(m_bFirst or bRed or (!m_bQ65_Sync and !m_bQ65_MultiSync) or m_mode!=m_mode0 + if(m_bFirst or bRed or !m_bQ65_Sync or m_mode!=m_mode0 or m_bResized or m_rxFreq!=m_rxFreq0) { m_2DPixmap = m_OverlayPixmap.copy(0,0,m_w,m_h2); m_bFirst=false; @@ -165,6 +165,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed) } static QPoint LineBuf[MAX_SCREENSIZE]; static QPoint LineBuf2[MAX_SCREENSIZE]; + static QPoint LineBuf3[MAX_SCREENSIZE]; j=0; j0=int(m_startFreq/m_fftBinWidth + 0.5); int iz=XfromFreq(5000.0); @@ -229,7 +230,7 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed) } - if(i==iz-1 and !m_bQ65_Sync and !m_bQ65_MultiSync) { + if(i==iz-1 and !m_bQ65_Sync) { painter2D.drawPolyline(LineBuf,j); } LineBuf[j].setX(i); @@ -273,28 +274,37 @@ void CPlotter::draw(float swide[], bool bScroll, bool bRed) painter2D.drawText(x1-4,y,"73"); } - if(bRed and (m_bQ65_Sync or m_bQ65_MultiSync)) { //Plot the Q65 red or orange sync curve + if(bRed and m_bQ65_Sync) { //Plot the Q65 red or orange sync curve int k=0; + int k2=0; std::ifstream f; f.open(m_redFile.toLatin1()); if(f) { int x,y; - float freq,sync,xdt,sync2; + float freq,xdt,sync,sync2; + f >> xdt; for(int i=0; i<99999; i++) { - f >> freq >> sync >> xdt >> sync2; + f >> freq >> sync >> sync2; if(f.eof()) break; x=XfromFreq(freq); - if(m_bQ65_MultiSync) sync=sync2; - y=m_h2*(0.9 - 0.09*gain2d*sync) - m_plot2dZero; - LineBuf2[k].setX(x); - LineBuf2[k].setY(y); + if(sync > -99.0 and sync != 0.0) { + y=m_h2*(0.9 - 0.09*gain2d*sync) - m_plot2dZero - 10; + LineBuf2[k2].setX(x); //Red sync curve + LineBuf2[k2].setY(y); + k2++; + } + y=m_h2*(0.9 - 0.09*gain2d*sync2) - m_plot2dZero; + LineBuf3[k].setX(x); //Orange sync curve + LineBuf3[k].setY(y); k++; } f.close(); QPen pen0(Qt::red,2); - if(m_bQ65_MultiSync) pen0.setColor("orange"); painter2D.setPen(pen0); - painter2D.drawPolyline(LineBuf2,k); + painter2D.drawPolyline(LineBuf2,k2); + pen0.setColor("orange"); + painter2D.setPen(pen0); + painter2D.drawPolyline(LineBuf3,k); if(m_bQ65_Sync) { QString t; t = t.asprintf("DT = %6.2f",xdt); diff --git a/widgets/plotter.h b/widgets/plotter.h index a4a8d6e04..582d36451 100644 --- a/widgets/plotter.h +++ b/widgets/plotter.h @@ -82,8 +82,7 @@ public: bool Reference() const {return m_bReference;} void setQ65_Sync(bool b) {m_bQ65_Sync = b;} bool Q65_Sync() const {return m_bQ65_Sync;} - void setQ65_MultiSync(bool b) {m_bQ65_MultiSync = b;} - bool Q65_MultiSync() const {return m_bQ65_MultiSync;} void drawRed(int ia, int ib, float swide[]); + void drawRed(int ia, int ib, float swide[]); void setVHF(bool bVHF); void setRedFile(QString fRed); void setFST4_FreqRange(int fLow,int fHigh); @@ -117,7 +116,6 @@ private: bool m_bReference; bool m_bReference0; bool m_bQ65_Sync; - bool m_bQ65_MultiSync; bool m_bVHF; bool m_bSingleDecode; bool m_bFirst=true; diff --git a/widgets/widegraph.cpp b/widgets/widegraph.cpp index 6f6736029..bb53279cd 100644 --- a/widgets/widegraph.cpp +++ b/widgets/widegraph.cpp @@ -71,13 +71,11 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) : ui->widePlot->setLinearAvg(m_settings->value("LinearAvg",false).toBool()); ui->widePlot->setReference(m_settings->value("Reference",false).toBool()); ui->widePlot->setQ65_Sync(m_settings->value("Q65_Sync",false).toBool()); - ui->widePlot->setQ65_MultiSync(m_settings->value("Q65_MultiSync",false).toBool()); if(ui->widePlot->current()) ui->spec2dComboBox->setCurrentIndex(0); if(ui->widePlot->cumulative()) ui->spec2dComboBox->setCurrentIndex(1); if(ui->widePlot->linearAvg()) ui->spec2dComboBox->setCurrentIndex(2); if(ui->widePlot->Reference()) ui->spec2dComboBox->setCurrentIndex(3); if(ui->widePlot->Q65_Sync()) ui->spec2dComboBox->setCurrentIndex(4); - if(ui->widePlot->Q65_MultiSync()) ui->spec2dComboBox->setCurrentIndex(5); int nbpp=m_settings->value("BinsPerPixel",2).toInt(); ui->widePlot->setBinsPerPixel(nbpp); ui->sbPercent2dPlot->setValue(m_Percent2DScreen); @@ -135,7 +133,6 @@ void WideGraph::saveSettings() //saveS m_settings->setValue ("LinearAvg", ui->widePlot->linearAvg()); m_settings->setValue ("Reference", ui->widePlot->Reference()); m_settings->setValue ("Q65_Sync", ui->widePlot->Q65_Sync()); - m_settings->setValue ("Q65_MultiSync", ui->widePlot->Q65_MultiSync()); m_settings->setValue ("BinsPerPixel", ui->widePlot->binsPerPixel ()); m_settings->setValue ("StartFreq", ui->widePlot->startFreq ()); m_settings->setValue ("WaterfallPalette", m_waterfallPalette); @@ -323,7 +320,6 @@ void WideGraph::on_spec2dComboBox_currentIndexChanged(int index) ui->widePlot->setLinearAvg(false); ui->widePlot->setReference(false); ui->widePlot->setQ65_Sync(false); - ui->widePlot->setQ65_MultiSync(false); ui->smoSpinBox->setEnabled(false); switch (index) { @@ -343,9 +339,6 @@ void WideGraph::on_spec2dComboBox_currentIndexChanged(int index) case 4: ui->widePlot->setQ65_Sync(true); break; - case 5: - ui->widePlot->setQ65_MultiSync(true); - break; } replot(); } diff --git a/widgets/widegraph.ui b/widgets/widegraph.ui index 202482f54..758cad8c4 100644 --- a/widgets/widegraph.ui +++ b/widgets/widegraph.ui @@ -340,11 +340,6 @@ Q65_Sync - - - Q65_MultiSync - -