Working on QRA65, including simulator and test program.

This commit is contained in:
Joe Taylor 2020-09-26 16:49:06 -04:00
parent acd6253373
commit c3d8e4dd73
5 changed files with 105 additions and 57 deletions

View File

@ -96,8 +96,8 @@ program qra65sim
bandwidth_ratio=2500.0/6000.0 bandwidth_ratio=2500.0/6000.0
sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snrdb) sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snrdb)
if(snrdb.gt.90.0) sig=1.0 if(snrdb.gt.90.0) sig=1.0
write(*,1020) ifile,ntrperiod,f0,csubmode,xsnr,xdt,fspread,msgsent write(*,1020) ifile,ntrperiod,f0,csubmode,snrdb,xdt,fspread,msgsent
1020 format(i4,i6,f7.1,2x,a1,2x,f5.1,f6.2,f6.1,1x,a22) 1020 format(i4,i6,f7.1,2x,a1,2x,f5.1,f6.2,f6.1,2x,a22)
phi=0.d0 phi=0.d0
dphi=0.d0 dphi=0.d0
k=(xdt+0.5)*12000 !Start audio at t=xdt+0.5 s (TR=15 and 30 s) k=(xdt+0.5)*12000 !Start audio at t=xdt+0.5 s (TR=15 and 30 s)

View File

@ -78,7 +78,7 @@ contains
baud=12000.0/nsps baud=12000.0/nsps
df1=12000.0/nfft1 df1=12000.0/nfft1
! do i=1,NMAX ! do i=1,12000*ntrperiod
! write(61,3061) i/12000.0,iwave(i)/32767.0 ! write(61,3061) i/12000.0,iwave(i)/32767.0
!3061 format(2f12.6) !3061 format(2f12.6)
! enddo ! enddo
@ -120,24 +120,27 @@ contains
call timer('sync_q65',1) call timer('sync_q65',1)
! Downsample to give complex data at 6000 S/s ! Downsample to give complex data at 6000 S/s
call timer('down_q65',0)
fac=2.0/nfft1 fac=2.0/nfft1
c0=fac*iwave(1:nfft1) c0=fac*iwave(1:nfft1)
call four2a(c0,nfft1,1,-1,1) !Forward c2c FFT call four2a(c0,nfft1,1,-1,1) !Forward c2c FFT
c0(nfft2/2+1:nfft2)=0. !Zero the top half c0(nfft2/2+1:nfft2)=0. !Zero the top half
c0(0)=0.5*c0(0) c0(0)=0.5*c0(0)
call four2a(c0,nfft2,1,1,1) !Inverse c2c FFT call four2a(c0,nfft2,1,1,1) !Inverse c2c FFT
jpk=(xdt+0.5)*6000 - 384 !### Empirical ###
if(ntrperiod.ge.60) jpk=(xdt+1.0)*6000 - 384 !### TBD ###
if(jpk.lt.0) jpk=0
a=0. a=0.
a(1)=-(f0 + mode65*baud) !Data tones start mode65 bins higher a(1)=-(f0 + mode65*baud) !Data tones start mode65 bins higher
call twkfreq(c0,c0,ntrperiod*6000,6000.0,a) call twkfreq(c0,c0,ntrperiod*6000,6000.0,a)
call timer('down_q65',1)
jpk=(xdt+0.5)*6000 - 384 !### Empirical ###
if(ntrperiod.ge.60) jpk=(xdt+1.0)*6000 - 384 !### TBD ??? ###
if(jpk.lt.0) jpk=0
xdt=jpk/6000.0 - 0.5 xdt=jpk/6000.0 - 0.5
LL=64*(mode65+2) LL=64*(mode65+2)
NN=63 NN=63
call spec_qra65(c0(jpk:),nsps/2,s3,LL,NN) !Compute synchronized symbol spectra call timer('spec_q65',0)
call spec_qra65(c0(jpk:),nsps/2,s3,LL,NN) !Compute synced symbol spectra
call timer('spec_q65',1)
do j=1,63 !Normalize to symbol baseline do j=1,63 !Normalize to symbol baseline
call pctile(s3(:,j),LL,40,base) call pctile(s3(:,j),LL,40,base)
@ -188,7 +191,7 @@ contains
irc,qual,ntrperiod,fmid,w50) irc,qual,ntrperiod,fmid,w50)
else else
snr2=0. snr2=0.
nsnr=-25 nsnr=-25
!### TEMPORARY? ### !### TEMPORARY? ###
call this%callback(nutc,sync,nsnr,xdt,f0,decoded, & call this%callback(nutc,sync,nsnr,xdt,f0,decoded, &
irc,qual,ntrperiod,fmid,w50) irc,qual,ntrperiod,fmid,w50)

View File

@ -6,7 +6,7 @@ subroutine sync_qra65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1)
integer ijpk(2) !Indices i and j at peak of ccf integer ijpk(2) !Indices i and j at peak of ccf
real, allocatable :: s1(:,:) !Symbol spectra, quarter-symbol steps real, allocatable :: s1(:,:) !Symbol spectra, quarter-symbol steps
real sync(85) !sync vector real sync(85) !sync vector
real ccf(-64:64,-15:15) real ccf(-64:64,-26:107)
complex, allocatable :: c0(:) !Complex spectrum of symbol complex, allocatable :: c0(:) !Complex spectrum of symbol
data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/ data isync/1,9,12,13,15,22,23,26,27,33,35,38,46,50,55,60,62,66,69,74,76,85/
data sync(1)/99.0/ data sync(1)/99.0/
@ -64,24 +64,20 @@ subroutine sync_qra65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1)
!3060 format(i6,f10.3,e12.3) !3060 format(i6,f10.3,e12.3)
! enddo ! enddo
dt4=nsps/(NSTEP*12000.0) !1/4 of symbol duration
j0=0.5/dt4
if(nsps.ge.7680) j0=1.0/dt4
ccf=0. ccf=0.
ia=min(64,nint(ntol/df)) ia=min(64,nint(ntol/df))
lag1=-1.0/dt4
lag2=4.0/dt4 + 0.9999
jadd=11
if(nsps.ge.3600) jadd=7
if(nsps.ge.7680) jadd=6
if(nsps.ge.16000) jadd=3
if(nsps.ge.41472) jadd=1
dt4=nsps/(NSTEP*12000.0) !1/4 of symbol duration
! print*,'DT range +/-',15*dt4
! j0=0.5/dt4
! if(nsps.ge.7680) j0=1.0/dt4
do i=-ia,ia do i=-ia,ia
do lag=-15,15 do lag=lag1,lag2
do k=1,85 do k=1,85
n=NSTEP*(k-1) + 1 n=NSTEP*(k-1) + 1
j=n+lag+jadd j=n+lag+j0
if(j.ge.1 .and. j.le.jz) then if(j.ge.1 .and. j.le.jz) then
ccf(i,lag)=ccf(i,lag) + sync(k)*s1(i0+i,j) ccf(i,lag)=ccf(i,lag) + sync(k)*s1(i0+i,j)
endif endif
@ -93,13 +89,14 @@ subroutine sync_qra65(iwave,nmax,mode65,nsps,nfqso,ntol,xdt,f0,snr1)
! write(61,3061) i,ccf(i,jpk) ! write(61,3061) i,ccf(i,jpk)
!3061 format(i5,e12.3) !3061 format(i5,e12.3)
! enddo ! enddo
! do j=-15,15 ! do j=lag1,lag2
! write(62,3061) j,ccf(ipk,j) ! write(62,3061) j,ccf(ipk,j)
! enddo ! enddo
ijpk=maxloc(ccf) ijpk=maxloc(ccf)
ipk=ijpk(1)-65 ipk=ijpk(1)-65
jpk=ijpk(2)-16 ! jpk=ijpk(2)-16
jpk=ijpk(2)-27
f0=nfqso + ipk*df f0=nfqso + ipk*df
xdt=jpk*dt4 xdt=jpk*dt4
snr1=maxval(ccf)/22.0 snr1=maxval(ccf)/22.0

View File

@ -1,16 +1,15 @@
program test_qra65 program test_qra65
character*70 cmd1,cmd2,line character*71 cmd1,cmd2,line
character*22 msg character*22 msg
character*8 arg character*8 arg
integer nretcode(0:11) integer nretcode(0:11)
integer fDop
logical decok logical decok
nargs=iargc() nargs=iargc()
if(nargs.ne.7) then if(nargs.ne.8) then
print*,'Usage: test_qra65 "msg" ndepth freq DT fDop nfiles SNR' print*,'Usage: test_qra65 "msg" ndepth freq DT fDop TRp nfiles SNR'
print*,'Example: test_qra65 "K1ABC W9XYZ EN37" 3 1500 0.0 5 100 0' print*,'Example: test_qra65 "K1ABC W9XYZ EN37" 3 1500 0.0 5.0 60 100 -20'
print*,' SNR = 0 to loop over all relevant SNRs' print*,' SNR = 0 to loop over all relevant SNRs'
go to 999 go to 999
endif endif
@ -24,32 +23,61 @@ program test_qra65
call getarg(5,arg) call getarg(5,arg)
read(arg,*) fDop read(arg,*) fDop
call getarg(6,arg) call getarg(6,arg)
read(arg,*) nfiles read(arg,*) ntrperiod
call getarg(7,arg) call getarg(7,arg)
read(arg,*) nfiles
call getarg(8,arg)
read(arg,*) nsnr read(arg,*) nsnr
! 1 2 3 4 5 6 if(ntrperiod.eq.15) then
! 1234567890123456789012345678901234567890123456789012345678901234' nsps=1800
cmd1='qra65sim "K1ABC W9XYZ EN37 " A 1500 5.0 0.0 100 -10 > junk0' i50=-21
cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 1 *.wav > junk' else if(ntrperiod.eq.30) then
nsps=3600
write(cmd1(10:33),'(a)') '"'//msg//'"' i50=-24
write(cmd1(37:40),'(i4)') nf0 else if(ntrperiod.eq.60) then
write(cmd1(41:45),'(i5)') fDop nsps=7680
write(cmd1(46:50),'(f5.2)') dt i50=-28
write(cmd1(51:55),'(i5)') nfiles else if(ntrperiod.eq.120) then
write(cmd2(32:32),'(i1)') ndepth nsps=16000
call system('rm -f *.wav') i50=-31
else if(ntrperiod.eq.300) then
write(*,1000) (j,j=0,11) nsps=41472
write(12,1000) (j,j=0,11) i50=-35
1000 format(/'SNR d Dop Sync Dec1 DecN Bad',i5,11i4,' tdec'/83('-')) else
ia=-12 stop 'Invalid TR period'
ib=-30 endif
ia=i50 + 8
ib=i50 - 5
if(nsnr.ne.0) then if(nsnr.ne.0) then
ia=nsnr ia=nsnr
ib=nsnr ib=nsnr
endif endif
baud=12000.0/nsps
tsym=1.0/baud
! 1 2 3 4 5 6 7
! 12345678901234567890123456789012345678901234567890123456789012345678901'
cmd1='qra65sim "K1ABC W9XYZ EN37 " A 1500 5.0 0.0 60 100 -10 > junk0'
cmd2='jt9 -3 -p 15 -L 300 -H 3000 -d 1 *.wav > junk'
write(cmd1(10:33),'(a)') '"'//msg//'"'
write(cmd1(37:40),'(i4)') nf0
write(cmd1(41:45),'(f5.1)') fDop
write(cmd1(46:50),'(f5.2)') dt
write(cmd1(51:54),'(i4)') ntrperiod
write(cmd1(55:59),'(i5)') nfiles
write(cmd2(11:13),'(i3)') ntrperiod
write(cmd2(33:33),'(i1)') ndepth
call system('rm -f *.wav')
write(*,1000) (j,j=0,11)
write(12,1000) (j,j=0,11)
1000 format(/'SNR d Dop Sync Dec1 DecN Bad',i6,11i4,' tdec dtavg dtrms'/97('-'))
dterr=3.0*tsym/4.0
nferr=max(1,nint(0.5*baud))
do nsnr=ia,ib,-1 do nsnr=ia,ib,-1
nsync=0 nsync=0
@ -57,7 +85,9 @@ program test_qra65
nfalse=0 nfalse=0
nretcode=0 nretcode=0
navg=0 navg=0
write(cmd1(57:59),'(i3)') nsnr sumxdt=0.
sqxdt=0.
write(cmd1(61:63),'(i3)') nsnr
call system(cmd1) call system(cmd1)
call sec0(0,tdec) call sec0(0,tdec)
call system(cmd2) call system(cmd2)
@ -65,10 +95,11 @@ program test_qra65
open(10,file='junk',status='unknown') open(10,file='junk',status='unknown')
n=0 n=0
do iline=1,9999 do iline=1,9999
read(10,'(a70)',end=10) line read(10,'(a71)',end=10) line
if(len(trim(line)).lt.60) cycle if(len(trim(line)).lt.60) cycle
read(line(11:20),*) xdt,nf read(line(11:20),*) xdt,nf
if(abs(xdt-dt).lt.0.15 .and. abs(nf-nf0).lt.4) nsync=nsync+1 ! if(ntrperiod.eq.60) xdt=xdt-0.5 !### TEMPORARY ###
if(abs(xdt-dt).le.dterr .and. abs(nf-nf0).le.nferr) nsync=nsync+1
read(line(60:),*) irc,iavg read(line(60:),*) irc,iavg
if(irc.lt.0) cycle if(irc.lt.0) cycle
decok=index(line,'W9XYZ').gt.0 decok=index(line,'W9XYZ').gt.0
@ -76,6 +107,8 @@ program test_qra65
i=irc i=irc
if(i.le.11) then if(i.le.11) then
ndecodes=ndecodes + 1 ndecodes=ndecodes + 1
sumxdt=sumxdt + xdt
sqxdt=sqxdt + xdt*xdt
navg=navg + 1 navg=navg + 1
else else
i=mod(i,10) i=mod(i,10)
@ -88,9 +121,17 @@ program test_qra65
endif endif
enddo enddo
10 close(10) 10 close(10)
write(*,1100) nsnr,ndepth,fDop,nsync,ndecodes,navg,nfalse,nretcode,tdec/nfiles xdt_avg=0.
write(12,1100) nsnr,ndepth,fDop,nsync,ndecodes,navg,nfalse,nretcode,tdec/nfiles xdt_rms=0.
1100 format(i3,i2,i3,3i5,i4,i6,11i4,f6.2) if(ndecodes.ge.2) then
xdt_avg=sumxdt/ndecodes
xdt_rms=sqxdt/(ndecodes-1) - xdt_avg*xdt_avg
endif
write(*,1100) nsnr,ndepth,fDop,nsync,ndecodes,navg,nfalse,nretcode, &
tdec/nfiles,xdt_avg,xdt_rms
write(12,1100) nsnr,ndepth,fDop,nsync,ndecodes,navg,nfalse,nretcode, &
tdec/nfiles,xdt_avg,xdt_rms
1100 format(i3,i2,f5.1,3i5,i4,i6,11i4,3f6.2)
flush(6) flush(6)
flush(12) flush(12)
enddo enddo

View File

@ -6326,23 +6326,30 @@ void MainWindow::on_actionQRA64_triggered()
void MainWindow::on_actionQRA65_triggered() void MainWindow::on_actionQRA65_triggered()
{ {
on_actionFST4_triggered(); // on_actionFST4_triggered();
m_mode="QRA65"; m_mode="QRA65";
m_modeTx="QRA65"; m_modeTx="QRA65";
ui->actionQRA65->setChecked(true); ui->actionQRA65->setChecked(true);
switch_mode(Modes::QRA65); switch_mode(Modes::QRA65);
setup_status_bar(true); setup_status_bar(true);
m_nsps=6912; //For symspec only
m_FFTSize = m_nsps / 2;
Q_EMIT FFTSize(m_FFTSize);
m_hsymStop=49; m_hsymStop=49;
ui->sbTR->values ({15, 30, 60, 120, 300}); ui->sbTR->values ({15, 30, 60, 120, 300});
on_sbTR_valueChanged (ui->sbTR->value()); on_sbTR_valueChanged (ui->sbTR->value());
ui->sbSubmode->setMaximum(3); ui->sbSubmode->setMaximum(3);
ui->sbSubmode->setValue(m_nSubMode); m_wideGraph->setMode(m_mode); ui->sbSubmode->setValue(m_nSubMode); m_wideGraph->setMode(m_mode);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx); m_wideGraph->setModeTx(m_modeTx);
m_wideGraph->setPeriod(m_TRperiod,6912); m_wideGraph->setPeriod(m_TRperiod,6912);
m_wideGraph->setTol(ui->sbFtol->value()); m_wideGraph->setTol(ui->sbFtol->value());
m_wideGraph->setRxFreq(ui->RxFreqSpinBox->value());
m_wideGraph->setTxFreq(ui->TxFreqSpinBox->value());
// 0123456789012345678901234567890123 // 0123456789012345678901234567890123
displayWidgets(nWidgets("1111110101101101000100000011000000")); displayWidgets(nWidgets("1111110101101101000100000011000000"));
statusChanged();} statusChanged();
}
void MainWindow::on_actionISCAT_triggered() void MainWindow::on_actionISCAT_triggered()
{ {