Removing leftover ft8 files. Cleaning up sync code.
This commit is contained in:
parent
7dc0298b18
commit
77405cc968
@ -289,7 +289,6 @@ set (wsjt_FSRCS
|
||||
lib/jt4_decode.f90
|
||||
lib/jt65_decode.f90
|
||||
lib/jt65_mod.f90
|
||||
lib/ft8_decode.f90
|
||||
lib/jt9_decode.f90
|
||||
lib/options.f90
|
||||
lib/packjt.f90
|
||||
@ -298,6 +297,8 @@ set (wsjt_FSRCS
|
||||
lib/timer_impl.f90
|
||||
lib/timer_module.f90
|
||||
lib/wavhdr.f90
|
||||
lib/js8a_module.f90
|
||||
lib/js8a_decode.f90
|
||||
lib/js8b_module.f90
|
||||
lib/js8b_decode.f90
|
||||
lib/js8c_module.f90
|
||||
@ -320,8 +321,6 @@ set (wsjt_FSRCS
|
||||
lib/averms.f90
|
||||
lib/azdist.f90
|
||||
lib/badmsg.f90
|
||||
lib/ft8/baseline.f90
|
||||
# lib/js8/baselinejs8.f90
|
||||
lib/bpdecode40.f90
|
||||
lib/bpdecode144.f90
|
||||
lib/ft8/bpdecode174.f90
|
||||
@ -386,17 +385,8 @@ set (wsjt_FSRCS
|
||||
lib/fqso_first.f90
|
||||
lib/freqcal.f90
|
||||
lib/ft8/ft8apset.f90
|
||||
lib/ft8/ft8b.f90
|
||||
# lib/js8/js8params.f90
|
||||
# lib/js8/js8b.f90
|
||||
lib/ft8/ft8code.f90
|
||||
lib/ft8/ft8_downsample.f90
|
||||
# lib/js8/js8_downsample.f90
|
||||
lib/ft8/ft8sim.f90
|
||||
lib/ft8/genft8.f90
|
||||
lib/js8/genjs8.f90
|
||||
lib/ft8/genft8refsig.f90
|
||||
# lib/js8/genjs8refsig.f90
|
||||
lib/geodist.f90
|
||||
lib/getlags.f90
|
||||
lib/getmet4.f90
|
||||
@ -417,8 +407,7 @@ set (wsjt_FSRCS
|
||||
lib/jplsubs.f
|
||||
lib/jt9fano.f90
|
||||
lib/jtmsg.f90
|
||||
lib/ldpcsim144.f90
|
||||
lib/ft8/ldpcsim174.f90
|
||||
lib/js8/ldpcsim174js8a.f90
|
||||
lib/js8/ldpcsim174js8b.f90
|
||||
lib/js8/ldpcsim174js8c.f90
|
||||
lib/js8/ldpcsim174js8e.f90
|
||||
@ -460,8 +449,6 @@ set (wsjt_FSRCS
|
||||
lib/spec9f.f90
|
||||
lib/stdmsg.f90
|
||||
lib/subtract65.f90
|
||||
lib/ft8/subtractft8.f90
|
||||
# lib/js8/subtractjs8.f90
|
||||
lib/sun.f90
|
||||
lib/symspec.f90
|
||||
lib/symspec2.f90
|
||||
@ -469,10 +456,6 @@ set (wsjt_FSRCS
|
||||
lib/sync4.f90
|
||||
lib/sync64.f90
|
||||
lib/sync65.f90
|
||||
lib/ft8/sync8.f90
|
||||
# lib/js8/syncjs8.f90
|
||||
lib/ft8/sync8d.f90
|
||||
# lib/js8/syncjs8d.f90
|
||||
lib/sync9.f90
|
||||
lib/sync9f.f90
|
||||
lib/sync9w.f90
|
||||
@ -997,8 +980,8 @@ endif (WIN32)
|
||||
add_library (wsjt_qtmm STATIC ${wsjt_qtmm_CXXSRCS} ${wsjt_qtmm_GENUISRCS})
|
||||
target_link_libraries (wsjt_qtmm Qt5::Multimedia)
|
||||
|
||||
add_executable (ldpcsim174 lib/ft8/ldpcsim174.f90 wsjtx.rc)
|
||||
target_link_libraries (ldpcsim174 wsjt_fort wsjt_cxx)
|
||||
add_executable (ldpcsim174js8a lib/js8/ldpcsim174js8a.f90 wsjtx.rc)
|
||||
target_link_libraries (ldpcsim174js8a wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (ldpcsim174js8b lib/js8/ldpcsim174js8b.f90 wsjtx.rc)
|
||||
target_link_libraries (ldpcsim174js8b wsjt_fort wsjt_cxx)
|
||||
|
@ -3,7 +3,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
!$ use omp_lib
|
||||
use prog_args
|
||||
use timer_module, only: timer
|
||||
use ft8_decode
|
||||
use js8a_decode
|
||||
use js8b_decode
|
||||
use js8c_decode
|
||||
use js8e_decode
|
||||
@ -12,9 +12,9 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
include 'jt9com.f90'
|
||||
include 'timer_common.inc'
|
||||
|
||||
type, extends(ft8_decoder) :: counting_ft8_decoder
|
||||
type, extends(js8a_decoder) :: counting_js8a_decoder
|
||||
integer :: decoded
|
||||
end type counting_ft8_decoder
|
||||
end type counting_js8a_decoder
|
||||
|
||||
type, extends(js8b_decoder) :: counting_js8b_decoder
|
||||
integer :: decoded
|
||||
@ -41,7 +41,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
character(len=12) :: mycall, hiscall
|
||||
character(len=6) :: mygrid, hisgrid
|
||||
save
|
||||
type(counting_ft8_decoder) :: my_js8a
|
||||
type(counting_js8a_decoder) :: my_js8a
|
||||
type(counting_js8b_decoder) :: my_js8b
|
||||
type(counting_js8c_decoder) :: my_js8c
|
||||
type(counting_js8e_decoder) :: my_js8e
|
||||
@ -69,10 +69,6 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
|
||||
|
||||
10 nfail=0
|
||||
if(params%nmode.eq.8) then
|
||||
c2fox=' '
|
||||
g2fox=' '
|
||||
nsnrfox=-99
|
||||
nfreqfox=-99
|
||||
n30z=0
|
||||
nwrap=0
|
||||
nfox=0
|
||||
@ -235,10 +231,6 @@ contains
|
||||
ichar(w(4:4)).ge.ichar('0') .and. ichar(w(4:4)).le.ichar('9'))
|
||||
|
||||
if(first) then
|
||||
c2fox=' '
|
||||
g2fox=' '
|
||||
nsnrfox=-99
|
||||
nfreqfox=-99
|
||||
n30z=0
|
||||
nwrap=0
|
||||
nfox=0
|
||||
@ -291,11 +283,6 @@ contains
|
||||
n30z=n30
|
||||
n30=n30+nwrap
|
||||
nfox=nfox+1
|
||||
c2fox(nfox)=c2
|
||||
g2fox(nfox)=g2
|
||||
nsnrfox(nfox)=snr
|
||||
nfreqfox(nfox)=nint(freq)
|
||||
n30fox(nfox)=n30
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -305,10 +292,10 @@ contains
|
||||
end subroutine js8_decoded
|
||||
|
||||
subroutine js8a_decoded (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
use ft8_decode
|
||||
use js8a_decode
|
||||
implicit none
|
||||
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
class(js8a_decoder), intent(inout) :: this
|
||||
real, intent(in) :: sync
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
@ -323,7 +310,7 @@ contains
|
||||
call js8_decoded(sync, snr, dt, freq, decoded, nap, qual, submode)
|
||||
|
||||
select type(this)
|
||||
type is (counting_ft8_decoder)
|
||||
type is (counting_js8a_decoder)
|
||||
this%decoded = this%decoded + 1
|
||||
end select
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
subroutine baseline(s,nfa,nfb,sbase)
|
||||
|
||||
! Fit baseline to spectrum (for FT8)
|
||||
! Input: s(npts) Linear scale in power
|
||||
! Output: sbase(npts) Baseline
|
||||
|
||||
implicit real*8 (a-h,o-z)
|
||||
|
||||
include 'ft8_params.f90'
|
||||
|
||||
real*4 s(NSPS)
|
||||
real*4 sbase(NSPS)
|
||||
real*4 base
|
||||
real*8 x(1000),y(1000),a(5)
|
||||
data nseg/10/,npct/10/
|
||||
|
||||
df=12000.0/(NSPS*2.0d0) !3.125 Hz
|
||||
ia=max(1,nint(nfa/df))
|
||||
ib=nint(nfb/df)
|
||||
do i=ia,ib
|
||||
s(i)=10.0*log10(s(i)) !Convert to dB scale
|
||||
enddo
|
||||
|
||||
nterms=5
|
||||
nlen=(ib-ia+1)/nseg !Length of test segment
|
||||
i0=(ib-ia+1)/2 !Midpoint
|
||||
k=0
|
||||
do n=1,nseg !Loop over all segments
|
||||
ja=ia + (n-1)*nlen
|
||||
jb=ja+nlen-1
|
||||
call pctile(s(ja),nlen,npct,base) !Find lowest npct of points
|
||||
do i=ja,jb
|
||||
if(s(i).le.base) then
|
||||
if (k.lt.1000) k=k+1 !Save all "lower envelope" points
|
||||
x(k)=i-i0
|
||||
y(k)=s(i)
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
kz=k
|
||||
a=0.
|
||||
call polyfit(x,y,y,kz,nterms,0,a,chisqr) !Fit a low-order polynomial
|
||||
do i=ia,ib
|
||||
t=i-i0
|
||||
sbase(i)=a(1)+t*(a(2)+t*(a(3)+t*(a(4)+t*(a(5))))) + 0.65
|
||||
! write(51,3051) i*df,s(i),sbase(i)
|
||||
!3051 format(3f12.3)
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine baseline
|
@ -1,54 +0,0 @@
|
||||
subroutine ft8_downsample(dd,newdat,f0,c1)
|
||||
|
||||
! Downconvert to complex data sampled at 200 Hz ==> 32 samples/symbol
|
||||
|
||||
include 'ft8_params.f90'
|
||||
|
||||
parameter (NDFFT1=NSPS*NDD, NDFFT2=NDFFT1/NDOWN) ! Downconverted FFT Size - 192000/60 = 3200
|
||||
|
||||
logical newdat,first
|
||||
|
||||
complex c1(0:NDFFT2-1)
|
||||
complex cx(0:NDFFT1/2)
|
||||
real dd(NMAX),x(NDFFT1),taper(0:NDD)
|
||||
equivalence (x,cx)
|
||||
data first/.true./
|
||||
save cx,first,taper
|
||||
|
||||
if(first) then
|
||||
pi=4.0*atan(1.0)
|
||||
do i=0,NDD
|
||||
taper(i)=0.5*(1.0+cos(i*pi/NDD))
|
||||
enddo
|
||||
first=.false.
|
||||
endif
|
||||
if(newdat) then
|
||||
! Data in dd have changed, recompute the long FFT
|
||||
x(1:NMAX)=dd
|
||||
x(NMAX+1:NDFFT1)=0. !Zero-pad the x array
|
||||
call four2a(cx,NDFFT1,1,-1,0) !r2c FFT to freq domain
|
||||
newdat=.false.
|
||||
endif
|
||||
|
||||
df=12000.0/NDFFT1
|
||||
baud=12000.0/NSPS
|
||||
i0=nint(f0/df)
|
||||
ft=f0+8.5*baud
|
||||
it=min(nint(ft/df),NDFFT1/2)
|
||||
fb=f0-1.5*baud
|
||||
ib=max(1,nint(fb/df))
|
||||
k=0
|
||||
c1=0.
|
||||
do i=ib,it
|
||||
c1(k)=cx(i)
|
||||
k=k+1
|
||||
enddo
|
||||
c1(0:NDD)=c1(0:NDD)*taper(NDD:0:-1)
|
||||
c1(k-1-NDD:k-1)=c1(k-1-NDD:k-1)*taper
|
||||
c1=cshift(c1,i0-ib)
|
||||
call four2a(c1,NDFFT2,1,1,1) !c2c FFT back to time domain
|
||||
fac=1.0/sqrt(float(NDFFT1)*NDFFT2)
|
||||
c1=fac*c1
|
||||
|
||||
return
|
||||
end subroutine ft8_downsample
|
@ -1,27 +0,0 @@
|
||||
! LDPC (174,87) code
|
||||
|
||||
!parameter (NSPS=480) !Samples per symbol at 12000 S/s
|
||||
!parameter (NTXDUR=5) !TX Duration in Seconds
|
||||
!parameter (NDOWNSPS=16) !Downsampled samples per symbol
|
||||
!parameter (AZ=6.0) !Near dupe sync spacing
|
||||
!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins
|
||||
|
||||
! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=16, NDD=136) ! 200 Hz
|
||||
! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120) ! 160 Hz
|
||||
! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=24, NDD=100) ! 80 Hz
|
||||
parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100) ! 50 Hz
|
||||
! parameter (NSPS=3840, NTXDUR=30, NDOWNSPS=32, NDD=100) ! 25 Hz
|
||||
|
||||
parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time.
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.64d0)
|
||||
|
||||
parameter (KK=87) !Information bits (75 + CRC12)
|
||||
parameter (ND=58) !Data symbols
|
||||
parameter (NS=21) !Sync symbols (3 @ Costas 7x7)
|
||||
parameter (NN=NS+ND) !Total channel symbols (79)
|
||||
parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680)
|
||||
parameter (NMAX=NTXDUR*12000) !Samples in iwave (180,000)
|
||||
parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra
|
||||
parameter (NSTEP=NSPS/4) !Rough time-sync step size
|
||||
parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps)
|
||||
parameter (NDOWN=NSPS/NDOWNSPS) !Downsample factor to 32 samples per symbol
|
1
lib/ft8/ft8_params.f90
Symbolic link
1
lib/ft8/ft8_params.f90
Symbolic link
@ -0,0 +1 @@
|
||||
../js8/js8_params.f90
|
452
lib/ft8/ft8b.f90
452
lib/ft8/ft8b.f90
@ -1,452 +0,0 @@
|
||||
subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||
napwid,lsubtract,nagain,iaptype,mycall12,mygrid6,hiscall12,bcontest, &
|
||||
sync0,f1,xdt,xbase,apsym,nharderrors,dmin,nbadcrc,ipass,iera,msg37,xsnr)
|
||||
|
||||
use crc
|
||||
use timer_module, only: timer
|
||||
include 'ft8_params.f90'
|
||||
parameter(NP2=2812)
|
||||
character*37 msg37
|
||||
character message*22,msgsent*22,origmsg*22
|
||||
character*12 mycall12,hiscall12
|
||||
character*6 mycall6,mygrid6,hiscall6,c1,c2
|
||||
character*87 cbits
|
||||
logical bcontest
|
||||
real a(5)
|
||||
real s1(0:7,ND),s2(0:7,NN),s1sort(8*ND)
|
||||
real ps(0:7),psl(0:7)
|
||||
real bmeta(3*ND),bmetb(3*ND),bmetap(3*ND)
|
||||
real llr(3*ND),llra(3*ND),llr0(3*ND),llr1(3*ND),llrap(3*ND) !Soft symbols
|
||||
real dd0(NMAX)
|
||||
integer*1 decoded(KK),decoded0(KK),apmask(3*ND),cw(3*ND)
|
||||
integer*1 msgbits(KK)
|
||||
integer apsym(KK)
|
||||
integer mcq(28),mde(28),mrrr(16),m73(16),mrr73(16)
|
||||
integer itone(NN)
|
||||
integer indxs1(8*ND)
|
||||
integer icos7(0:6),ip(1)
|
||||
integer nappasses(0:5) !Number of decoding passes to use for each QSO state
|
||||
integer naptypes(0:5,4) ! (nQSOProgress, decoding pass) maximum of 4 passes for now
|
||||
integer*1, target:: i1hiscall(12)
|
||||
complex cd0(0:3199)
|
||||
complex ctwk(NDOWNSPS)
|
||||
complex csymb(NDOWNSPS)
|
||||
logical first,newdat,lsubtract,lapon,lapcqonly,nagain
|
||||
equivalence (s1,s1sort)
|
||||
data icos7/4,2,5,6,1,3,0/
|
||||
data mcq/1,1,1,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,1/
|
||||
data mrrr/0,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1/
|
||||
data m73/0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0/
|
||||
data mde/1,1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,0,0,0,1/
|
||||
data mrr73/0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,1/
|
||||
data first/.true./
|
||||
save nappasses,naptypes
|
||||
|
||||
if(first) then
|
||||
mcq=2*mcq-1
|
||||
mde=2*mde-1
|
||||
mrrr=2*mrrr-1
|
||||
m73=2*m73-1
|
||||
mrr73=2*mrr73-1
|
||||
nappasses(0)=2
|
||||
nappasses(1)=2
|
||||
nappasses(2)=2
|
||||
nappasses(3)=4
|
||||
nappasses(4)=4
|
||||
nappasses(5)=3
|
||||
|
||||
! iaptype
|
||||
!------------------------
|
||||
! 1 CQ ??? ???
|
||||
! 2 MyCall ??? ???
|
||||
! 3 MyCall DxCall ???
|
||||
! 4 MyCall DxCall RRR
|
||||
! 5 MyCall DxCall 73
|
||||
! 6 MyCall DxCall RR73
|
||||
! 7 ??? DxCall ???
|
||||
|
||||
naptypes(0,1:4)=(/1,2,0,0/)
|
||||
naptypes(1,1:4)=(/2,3,0,0/)
|
||||
naptypes(2,1:4)=(/2,3,0,0/)
|
||||
naptypes(3,1:4)=(/3,4,5,6/)
|
||||
naptypes(4,1:4)=(/3,4,5,6/)
|
||||
naptypes(5,1:4)=(/3,1,2,0/)
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
max_iterations=30
|
||||
nharderrors=-1
|
||||
fs2=12000.0/NDOWN
|
||||
dt2=1.0/fs2
|
||||
twopi=8.0*atan(1.0)
|
||||
delfbest=0.
|
||||
ibest=0
|
||||
|
||||
call timer('ft8_down',0)
|
||||
call ft8_downsample(dd0,newdat,f1,cd0) !Mix f1 to baseband and downsample
|
||||
call timer('ft8_down',1)
|
||||
|
||||
i0=nint((xdt+0.5)*fs2) !Initial guess for start of signal
|
||||
smax=0.0
|
||||
do idt=i0-8,i0+8 !Search over +/- one quarter symbol
|
||||
call sync8d(cd0,idt,ctwk,0,sync)
|
||||
if(sync.gt.smax) then
|
||||
smax=sync
|
||||
ibest=idt
|
||||
endif
|
||||
enddo
|
||||
xdt2=ibest*dt2 !Improved estimate for DT
|
||||
|
||||
! Now peak up in frequency
|
||||
i0=nint(xdt2*fs2)
|
||||
smax=0.0
|
||||
do ifr=-5,5 !Search over +/- 2.5 Hz
|
||||
delf=ifr*0.5
|
||||
dphi=twopi*delf*dt2
|
||||
phi=0.0
|
||||
do i=1,NDOWNSPS
|
||||
ctwk(i)=cmplx(cos(phi),sin(phi))
|
||||
phi=mod(phi+dphi,twopi)
|
||||
enddo
|
||||
call sync8d(cd0,i0,ctwk,1,sync)
|
||||
if( sync .gt. smax ) then
|
||||
smax=sync
|
||||
delfbest=delf
|
||||
endif
|
||||
enddo
|
||||
a=0.0
|
||||
a(1)=-delfbest
|
||||
call twkfreq1(cd0,NP2,fs2,a,cd0)
|
||||
xdt=xdt2
|
||||
f1=f1+delfbest !Improved estimate of DF
|
||||
|
||||
call sync8d(cd0,i0,ctwk,2,sync)
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
i1=ibest+(k-1)*NDOWNSPS
|
||||
csymb=cmplx(0.0,0.0)
|
||||
!if( i1.ge.1 .and. i1+31 .le. NP2 ) csymb=cd0(i1:i1+31)
|
||||
if( i1.ge.0 .and. i1+(NDOWNSPS-1) .le. NP2-1 ) csymb=cd0(i1:i1+(NDOWNSPS-1))
|
||||
call four2a(csymb,NDOWNSPS,1,-1,1)
|
||||
s2(0:7,k)=abs(csymb(1:8))/1e3
|
||||
enddo
|
||||
|
||||
! sync quality check
|
||||
is1=0
|
||||
is2=0
|
||||
is3=0
|
||||
do k=1,7
|
||||
ip=maxloc(s2(:,k))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is1=is1+1
|
||||
ip=maxloc(s2(:,k+36))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is2=is2+1
|
||||
ip=maxloc(s2(:,k+72))
|
||||
if(icos7(k-1).eq.(ip(1)-1)) is3=is3+1
|
||||
enddo
|
||||
! hard sync sum - max is 21
|
||||
nsync=is1+is2+is3
|
||||
|
||||
if(nsync .le. 6) then ! bail out
|
||||
call timer('badnsync', 0)
|
||||
nbadcrc=1
|
||||
call timer('badnsync', 1)
|
||||
return
|
||||
endif
|
||||
|
||||
j=0
|
||||
do k=1,NN
|
||||
if(k.le.7) cycle
|
||||
if(k.ge.37 .and. k.le.43) cycle
|
||||
if(k.gt.72) cycle
|
||||
j=j+1
|
||||
s1(0:7,j)=s2(0:7,k)
|
||||
enddo
|
||||
|
||||
call indexx(s1sort,8*ND,indxs1)
|
||||
xmeds1=s1sort(indxs1(nint(0.5*8*ND)))
|
||||
s1=s1/xmeds1
|
||||
|
||||
do j=1,ND
|
||||
i4=3*j-2
|
||||
i2=3*j-1
|
||||
i1=3*j
|
||||
! Max amplitude
|
||||
ps=s1(0:7,j)
|
||||
r1=max(ps(1),ps(3),ps(5),ps(7))-max(ps(0),ps(2),ps(4),ps(6))
|
||||
r2=max(ps(2),ps(3),ps(6),ps(7))-max(ps(0),ps(1),ps(4),ps(5))
|
||||
r4=max(ps(4),ps(5),ps(6),ps(7))-max(ps(0),ps(1),ps(2),ps(3))
|
||||
bmeta(i4)=r4
|
||||
bmeta(i2)=r2
|
||||
bmeta(i1)=r1
|
||||
bmetap(i4)=r4
|
||||
bmetap(i2)=r2
|
||||
bmetap(i1)=r1
|
||||
! Max log metric
|
||||
psl=log(ps+1e-32)
|
||||
r1=max(psl(1),psl(3),psl(5),psl(7))-max(psl(0),psl(2),psl(4),psl(6))
|
||||
r2=max(psl(2),psl(3),psl(6),psl(7))-max(psl(0),psl(1),psl(4),psl(5))
|
||||
r4=max(psl(4),psl(5),psl(6),psl(7))-max(psl(0),psl(1),psl(2),psl(3))
|
||||
bmetb(i4)=r4
|
||||
bmetb(i2)=r2
|
||||
bmetb(i1)=r1
|
||||
|
||||
! Metric for Cauchy noise
|
||||
! r1=log(ps(1)**3+ps(3)**3+ps(5)**3+ps(7)**3)- &
|
||||
! log(ps(0)**3+ps(2)**3+ps(4)**3+ps(6)**3)
|
||||
! r2=log(ps(2)**3+ps(3)**3+ps(6)**3+ps(7)**3)- &
|
||||
! log(ps(0)**3+ps(1)**3+ps(4)**3+ps(5)**3)
|
||||
! r4=log(ps(4)**3+ps(5)**3+ps(6)**3+ps(7)**3)- &
|
||||
! log(ps(0)**3+ps(1)**3+ps(2)**3+ps(3)**3)
|
||||
! Metric for AWGN, no fading
|
||||
! bscale=2.5
|
||||
! b0=bessi0(bscale*ps(0))
|
||||
! b1=bessi0(bscale*ps(1))
|
||||
! b2=bessi0(bscale*ps(2))
|
||||
! b3=bessi0(bscale*ps(3))
|
||||
! b4=bessi0(bscale*ps(4))
|
||||
! b5=bessi0(bscale*ps(5))
|
||||
! b6=bessi0(bscale*ps(6))
|
||||
! b7=bessi0(bscale*ps(7))
|
||||
! r1=log(b1+b3+b5+b7)-log(b0+b2+b4+b6)
|
||||
! r2=log(b2+b3+b6+b7)-log(b0+b1+b4+b5)
|
||||
! r4=log(b4+b5+b6+b7)-log(b0+b1+b2+b3)
|
||||
|
||||
if(nQSOProgress .eq. 0 .or. nQSOProgress .eq. 5) then
|
||||
! When bits 88:115 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with no-ap bits 116 and 117. Take care of metrics for bits 116 and 117.
|
||||
if(j.eq.39) then ! take care of bits that live in symbol 39
|
||||
if(apsym(28).lt.0) then
|
||||
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
else
|
||||
bmetap(i2)=max(ps(6),ps(7))-max(ps(4),ps(5))
|
||||
bmetap(i1)=max(ps(5),ps(7))-max(ps(4),ps(6))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
! When bits 116:143 are set as ap bits, bit 115 lives in symbol 39 along
|
||||
! with ap bits 116 and 117. Take care of metric for bit 115.
|
||||
! if(j.eq.39) then ! take care of bit 115
|
||||
! iii=2*(apsym(29)+1)/2 + (apsym(30)+1)/2 ! known values of bits 116 & 117
|
||||
! if(iii.eq.0) bmetap(i4)=ps(4)-ps(0)
|
||||
! if(iii.eq.1) bmetap(i4)=ps(5)-ps(1)
|
||||
! if(iii.eq.2) bmetap(i4)=ps(6)-ps(2)
|
||||
! if(iii.eq.3) bmetap(i4)=ps(7)-ps(3)
|
||||
! endif
|
||||
|
||||
! bit 144 lives in symbol 48 and will be 1 if it is set as an ap bit.
|
||||
! take care of metrics for bits 142 and 143
|
||||
if(j.eq.48) then ! bit 144 is always 1
|
||||
bmetap(i4)=max(ps(5),ps(7))-max(ps(1),ps(3))
|
||||
bmetap(i2)=max(ps(3),ps(7))-max(ps(1),ps(5))
|
||||
endif
|
||||
|
||||
! bit 154 lives in symbol 52 and will be 0 if it is set as an ap bit
|
||||
! take care of metrics for bits 155 and 156
|
||||
if(j.eq.52) then ! bit 154 will be 0 if it is set as an ap bit.
|
||||
bmetap(i2)=max(ps(2),ps(3))-max(ps(0),ps(1))
|
||||
bmetap(i1)=max(ps(1),ps(3))-max(ps(0),ps(2))
|
||||
endif
|
||||
|
||||
enddo
|
||||
|
||||
call normalizebmet(bmeta,3*ND)
|
||||
call normalizebmet(bmetb,3*ND)
|
||||
call normalizebmet(bmetap,3*ND)
|
||||
|
||||
scalefac=2.83
|
||||
llr0=scalefac*bmeta
|
||||
llr1=scalefac*bmetb
|
||||
llra=scalefac*bmetap ! llr's for use with ap
|
||||
apmag=scalefac*(maxval(abs(bmetap))*1.01)
|
||||
|
||||
! pass #
|
||||
!------------------------------
|
||||
! 1 regular decoding
|
||||
! 2 erase 24
|
||||
! 3 erase 48
|
||||
! 4 ap pass 1
|
||||
! 5 ap pass 2
|
||||
! 6 ap pass 3
|
||||
! 7 ap pass 4, etc.
|
||||
|
||||
if(lapon) then
|
||||
if(.not.lapcqonly) then
|
||||
npasses=4+nappasses(nQSOProgress)
|
||||
else
|
||||
npasses=5
|
||||
endif
|
||||
else
|
||||
npasses=4
|
||||
endif
|
||||
|
||||
do ipass=1,npasses
|
||||
|
||||
llr=llr0
|
||||
if(ipass.eq.2) llr=llr1
|
||||
if(ipass.eq.3) llr(1:24)=0.
|
||||
if(ipass.eq.4) llr(1:48)=0.
|
||||
if(ipass.le.4) then
|
||||
apmask=0
|
||||
llrap=llr
|
||||
iaptype=0
|
||||
endif
|
||||
|
||||
if(ipass .gt. 4) then
|
||||
if(.not.lapcqonly) then
|
||||
iaptype=naptypes(nQSOProgress,ipass-4)
|
||||
else
|
||||
iaptype=1
|
||||
endif
|
||||
if(iaptype.ge.3 .and. (abs(f1-nfqso).gt.napwid .and. abs(f1-nftx).gt.napwid) ) cycle
|
||||
if(iaptype.eq.1 .or. iaptype.eq.2 ) then ! AP,???,???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! first 28 bits are AP
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
if(iaptype.eq.1) llrap(88:115)=apmag*mcq
|
||||
if(iaptype.eq.2) llrap(88:115)=apmag*apsym(1:28)
|
||||
llrap(116:117)=llra(116:117)
|
||||
llrap(142:143)=llra(142:143)
|
||||
llrap(144)=-apmag
|
||||
endif
|
||||
if(iaptype.eq.3) then ! mycall, dxcall, ???
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)
|
||||
llrap(144)=-apmag
|
||||
endif
|
||||
if(iaptype.eq.4 .or. iaptype.eq.5 .or. iaptype.eq.6) then
|
||||
apmask=0
|
||||
apmask(88:115)=1 ! mycall
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144:159)=1 ! RRR or 73 or RR73
|
||||
llrap=llr
|
||||
llrap(88:143)=apmag*apsym(1:56)
|
||||
if(iaptype.eq.4) llrap(144:159)=apmag*mrrr
|
||||
if(iaptype.eq.5) llrap(144:159)=apmag*m73
|
||||
if(iaptype.eq.6) llrap(144:159)=apmag*mrr73
|
||||
endif
|
||||
if(iaptype.eq.7) then ! ???, dxcall, ???
|
||||
apmask=0
|
||||
apmask(116:143)=1 ! hiscall
|
||||
apmask(144)=1 ! not free text
|
||||
llrap=llr
|
||||
llrap(115)=llra(115)
|
||||
llrap(116:143)=apmag*apsym(29:56)
|
||||
llrap(144)=-apmag
|
||||
endif
|
||||
endif
|
||||
|
||||
cw=0
|
||||
call timer('bpd174 ',0)
|
||||
call bpdecode174(llrap,apmask,max_iterations,decoded,cw,nharderrors, &
|
||||
niterations)
|
||||
call timer('bpd174 ',1)
|
||||
dmin=0.0
|
||||
if(ndepth.eq.3 .and. nharderrors.lt.0) then
|
||||
ndeep=3
|
||||
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then
|
||||
if((ipass.eq.3 .or. ipass.eq.4) .and. .not.nagain) then
|
||||
ndeep=3
|
||||
else
|
||||
ndeep=4
|
||||
endif
|
||||
endif
|
||||
if(nagain) ndeep=5
|
||||
call timer('osd174 ',0)
|
||||
call osd174(llrap,apmask,ndeep,decoded,cw,nharderrors,dmin)
|
||||
call timer('osd174 ',1)
|
||||
endif
|
||||
nbadcrc=1
|
||||
message=' '
|
||||
xsnr=-99.0
|
||||
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
|
||||
if(nharderrors.ge.0 .and. nharderrors+dmin.lt.60.0 .and. &
|
||||
.not.(sync.lt.2.0 .and. nharderrors.gt.35) .and. &
|
||||
.not.(ipass.gt.2 .and. nharderrors.gt.39) .and. &
|
||||
.not.(ipass.eq.4 .and. nharderrors.gt.30) &
|
||||
) then
|
||||
call chkcrc12a(decoded,nbadcrc)
|
||||
else
|
||||
nharderrors=-1
|
||||
cycle
|
||||
endif
|
||||
i3bit=4*decoded(73) + 2*decoded(74) + decoded(75)
|
||||
if(nbadcrc.eq.0) then
|
||||
decoded0=decoded
|
||||
call extractmessage174(decoded,origmsg,ncrcflag)
|
||||
decoded=decoded0
|
||||
|
||||
message(1:12)=origmsg(1:12)
|
||||
call genft8(message,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
|
||||
xsig=0.0
|
||||
xnoi=0.0
|
||||
do i=1,NN
|
||||
xsig=xsig+s2(itone(i),i)**2
|
||||
ios=mod(itone(i)+4,7)
|
||||
xnoi=xnoi+s2(ios,i)**2
|
||||
enddo
|
||||
xsnr=0.001
|
||||
if(xnoi.gt.0 .and. xnoi.lt.xsig) xsnr=xsig/xnoi-1.0
|
||||
xsnr=10.0*log10(xsnr)-27.0
|
||||
xsnr2=db(xsig/xbase - 1.0) - 32.0
|
||||
if(.not.nagain) xsnr=min(xsnr, xsnr2)
|
||||
if(xsnr .lt. -24.0) xsnr=-24.0
|
||||
|
||||
msg37=origmsg//' '
|
||||
|
||||
msg37(22:22) = char(48 + i3bit)
|
||||
|
||||
return
|
||||
endif
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine ft8b
|
||||
|
||||
subroutine normalizebmet(bmet,n)
|
||||
real bmet(n)
|
||||
|
||||
bmetav=sum(bmet)/real(n)
|
||||
bmet2av=sum(bmet*bmet)/real(n)
|
||||
var=bmet2av-bmetav*bmetav
|
||||
if( var .gt. 0.0 ) then
|
||||
bmetsig=sqrt(var)
|
||||
else
|
||||
bmetsig=sqrt(bmet2av)
|
||||
endif
|
||||
bmet=bmet/bmetsig
|
||||
return
|
||||
end subroutine normalizebmet
|
||||
|
||||
|
||||
function bessi0(x)
|
||||
! From Numerical Recipes
|
||||
real bessi0,x
|
||||
double precision p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9,y
|
||||
save p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9
|
||||
data p1,p2,p3,p4,p5,p6,p7/1.0d0,3.5156229d0,3.0899424d0,1.2067492d0, &
|
||||
0.2659732d0,0.360768d-1,0.45813d-2/
|
||||
data q1,q2,q3,q4,q5,q6,q7,q8,q9/0.39894228d0,0.1328592d-1, &
|
||||
0.225319d-2,-0.157565d-2,0.916281d-2,-0.2057706d-1, &
|
||||
0.2635537d-1,-0.1647633d-1,0.392377d-2/
|
||||
|
||||
if (abs(x).lt.3.75) then
|
||||
y=(x/3.75)**2
|
||||
bessi0=p1+y*(p2+y*(p3+y*(p4+y*(p5+y*(p6+y*p7)))))
|
||||
else
|
||||
ax=abs(x)
|
||||
y=3.75/ax
|
||||
bessi0=(exp(ax)/sqrt(ax))*(q1+y*(q2+y*(q3+y*(q4 &
|
||||
+y*(q5+y*(q6+y*(q7+y*(q8+y*q9))))))))
|
||||
endif
|
||||
return
|
||||
end function bessi0
|
||||
|
@ -1,103 +0,0 @@
|
||||
program ft8code
|
||||
|
||||
! Provides examples of message packing, LDPC(144,87) encoding, bit and
|
||||
! symbol ordering, and other details of the FT8 protocol.
|
||||
|
||||
use packjt
|
||||
use crc
|
||||
include 'ft8_params.f90' !Set various constants
|
||||
include 'ft8_testmsg.f90'
|
||||
parameter (NWAVE=NN*NSPS)
|
||||
|
||||
character*40 msg,msgchk
|
||||
character*37 msg37
|
||||
character*6 c1,c2
|
||||
character*9 comment
|
||||
character*22 msgsent,message
|
||||
character*6 mygrid6
|
||||
character bad*1,msgtype*10
|
||||
character*87 cbits
|
||||
logical bcontest
|
||||
integer itone(NN)
|
||||
integer dgen(12)
|
||||
integer*1 msgbits(KK),decoded(KK),decoded0(KK)
|
||||
data mygrid6/'EM48 '/
|
||||
|
||||
! Get command-line argument(s)
|
||||
nargs=iargc()
|
||||
if(nargs.ne.1 .and. nargs.ne.3) then
|
||||
print*
|
||||
print*,'Program ft8code: Provides examples of message packing, ', &
|
||||
'LDPC(174,87) encoding,'
|
||||
print*,'bit and symbol ordering, and other details of the FT8 protocol.'
|
||||
print*
|
||||
print*,'Usage: ft8code [-c grid] "message" # Results for specified message'
|
||||
print*,' ft8code -t # Examples of all message types'
|
||||
go to 999
|
||||
endif
|
||||
|
||||
bcontest=.false.
|
||||
call getarg(1,msg) !Message to be transmitted
|
||||
if(len(trim(msg)).eq.2 .and. msg(1:2).eq.'-t') then
|
||||
testmsg(NTEST+1)='KA1ABC RR73; WB9XYZ <KH1/KH7Z> -11'
|
||||
nmsg=NTEST+1
|
||||
else if(len(trim(msg)).eq.2 .and. msg(1:2).eq.'-c') then
|
||||
bcontest=.true.
|
||||
call getarg(2,mygrid6)
|
||||
call getarg(3,msg)
|
||||
msgchk=msg
|
||||
nmsg=1
|
||||
else
|
||||
msgchk=msg
|
||||
call fmtmsg(msgchk,iz) !To upper case; collapse multiple blanks
|
||||
nmsg=1
|
||||
endif
|
||||
|
||||
write(*,1010)
|
||||
1010 format(" Message Decoded Err? Type"/76("-"))
|
||||
|
||||
do imsg=1,nmsg
|
||||
if(nmsg.gt.1) msg=testmsg(imsg)
|
||||
call fmtmsg(msg,iz) !To upper case, collapse multiple blanks
|
||||
msgchk=msg
|
||||
|
||||
! Generate msgsent, msgbits, and itone
|
||||
call packmsg(msg(1:22),dgen,itype,bcontest)
|
||||
msgtype=""
|
||||
if(itype.eq.1) msgtype="Std Msg"
|
||||
if(itype.eq.2) msgtype="Type 1 pfx"
|
||||
if(itype.eq.3) msgtype="Type 1 sfx"
|
||||
if(itype.eq.4) msgtype="Type 2 pfx"
|
||||
if(itype.eq.5) msgtype="Type 2 sfx"
|
||||
if(itype.eq.6) msgtype="Free text"
|
||||
i3bit=0
|
||||
call genft8(msg(1:22),mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
|
||||
decoded=msgbits
|
||||
i3bit=4*decoded(73) + 2*decoded(74) + decoded(75)
|
||||
iFreeText=decoded(57)
|
||||
decoded0=decoded
|
||||
if(i3bit.eq.1) decoded(57:)=0
|
||||
call extractmessage174(decoded,message,ncrcflag)
|
||||
decoded=decoded0
|
||||
|
||||
bad=" "
|
||||
comment=' '
|
||||
if(itype.ne.6 .and. message.ne.msgchk) bad="*"
|
||||
if(itype.eq.6 .and. message(1:13).ne.msgchk(1:13)) bad="*"
|
||||
if(itype.eq.6 .and. len(trim(msgchk)).gt.13) comment='truncated'
|
||||
write(*,1020) imsg,msgchk,message,bad,i3bit,itype,msgtype,comment
|
||||
1020 format(i2,'.',1x,a22,1x,a22,1x,a1,2i2,1x,a10,1x,a9)
|
||||
|
||||
enddo
|
||||
|
||||
if(nmsg.eq.1) then
|
||||
write(*,1030) msgbits(1:56)
|
||||
1030 format(/'Call1: ',28i1,' Call2: ',28i1)
|
||||
write(*,1032) msgbits(57:72),msgbits(73:75),msgbits(76:87)
|
||||
1032 format('Grid: ',16i1,' 3Bit: ',3i1,' CRC12: ',12i1)
|
||||
write(*,1034) itone
|
||||
1034 format(/'Channel symbols:'/79i1)
|
||||
endif
|
||||
|
||||
999 end program ft8code
|
@ -1,63 +0,0 @@
|
||||
program ft8d
|
||||
|
||||
! Decode FT8 data read from *.wav files.
|
||||
|
||||
include 'ft8_params.f90'
|
||||
character*12 arg
|
||||
character infile*80,datetime*13,message*22
|
||||
real s(NH1,NHSYM)
|
||||
real candidate(3,100)
|
||||
integer ihdr(11)
|
||||
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||
real dd(NMAX)
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.lt.3) then
|
||||
print*,'Usage: ft8d MaxIt Norder file1 [file2 ...]'
|
||||
print*,'Example ft8d 40 2 *.wav'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,arg)
|
||||
read(arg,*) max_iterations
|
||||
call getarg(2,arg)
|
||||
read(arg,*) norder
|
||||
nfiles=nargs-2
|
||||
|
||||
twopi=8.0*atan(1.0)
|
||||
fs=12000.0 !Sample rate
|
||||
dt=1.0/fs !Sample interval (s)
|
||||
tt=NSPS*dt !Duration of "itone" symbols (s)
|
||||
ts=2*NSPS*dt !Duration of OQPSK symbols (s)
|
||||
baud=1.0/tt !Keying rate (baud)
|
||||
txt=NZ*dt !Transmission length (s)
|
||||
nfa=100.0
|
||||
nfb=3000.0
|
||||
nfqso=1500.0
|
||||
|
||||
do ifile=1,nfiles
|
||||
call getarg(ifile+2,infile)
|
||||
open(10,file=infile,status='old',access='stream')
|
||||
read(10,end=999) ihdr,iwave
|
||||
close(10)
|
||||
j2=index(infile,'.wav')
|
||||
read(infile(j2-6:j2-1),*) nutc
|
||||
datetime=infile(j2-13:j2-1)
|
||||
call sync8(iwave,nfa,nfb,nfqso,s,candidate,ncand)
|
||||
syncmin=2.0
|
||||
dd=iwave
|
||||
do icand=1,ncand
|
||||
sync=candidate(3,icand)
|
||||
if( sync.lt.syncmin) cycle
|
||||
f1=candidate(1,icand)
|
||||
xdt=candidate(2,icand)
|
||||
nsnr=min(99,nint(10.0*log10(sync)-25.5))
|
||||
call ft8b(dd,nfqso,f1,xdt,nharderrors,dmin,nbadcrc,message,xsnr)
|
||||
nsnr=xsnr
|
||||
xdt=xdt-0.6
|
||||
write(*,1110) datetime,0,nsnr,xdt,f1,message,nharderrors,dmin
|
||||
1110 format(a13,2i4,f6.2,f7.1,' ~ ',a22,i6,f7.1)
|
||||
enddo
|
||||
enddo ! ifile loop
|
||||
|
||||
999 end program ft8d
|
||||
|
@ -1,172 +0,0 @@
|
||||
program ft8sim
|
||||
|
||||
! Generate simulated data for a 15-second HF/6m mode using 8-FSK.
|
||||
! Output is saved to a *.wav file.
|
||||
|
||||
use wavhdr
|
||||
include 'ft8_params.f90' !Set various constants
|
||||
parameter (NWAVE=NN*NSPS)
|
||||
type(hdr) h !Header for .wav file
|
||||
character arg*12,fname*17
|
||||
character msg40*40,msg*22,msgsent*22,msg0*22
|
||||
character*6 mygrid6
|
||||
logical bcontest
|
||||
complex c0(0:NMAX-1)
|
||||
complex c(0:NMAX-1)
|
||||
real wave(NMAX)
|
||||
integer itone(NN)
|
||||
integer*1 msgbits(KK)
|
||||
integer*2 iwave(NMAX) !Generated full-length waveform
|
||||
data mygrid6/'EM48 '/
|
||||
|
||||
! Get command-line argument(s)
|
||||
nargs=iargc()
|
||||
if(nargs.ne.8) then
|
||||
print*,'Usage: ft8sim "message" nsig|f0 DT fdop del width nfiles snr'
|
||||
print*,'Examples: ft8sim "K1ABC W9XYZ EN37" 1500.0 0.0 0.1 1.0 0 10 -18'
|
||||
print*,' ft8sim "K1ABC W9XYZ EN37" 10 0.0 0.1 1.0 25 10 -18'
|
||||
print*,' ft8sim "K1ABC W9XYZ EN37" 25 0.0 0.1 1.0 25 10 -18'
|
||||
print*,' ft8sim "K1ABC RR73; W9XYZ <KH1/KH7Z> -11" 300 0 0 0 25 1 -10'
|
||||
print*,'Make nfiles negative to invoke 72-bit contest mode.'
|
||||
go to 999
|
||||
endif
|
||||
call getarg(1,msg40) !Message to be transmitted
|
||||
call getarg(2,arg)
|
||||
read(arg,*) f0 !Frequency (only used for single-signal)
|
||||
call getarg(3,arg)
|
||||
read(arg,*) xdt !Time offset from nominal (s)
|
||||
call getarg(4,arg)
|
||||
read(arg,*) fspread !Watterson frequency spread (Hz)
|
||||
call getarg(5,arg)
|
||||
read(arg,*) delay !Watterson delay (ms)
|
||||
call getarg(6,arg)
|
||||
read(arg,*) width !Filter transition width (Hz)
|
||||
call getarg(7,arg)
|
||||
read(arg,*) nfiles !Number of files
|
||||
call getarg(8,arg)
|
||||
read(arg,*) snrdb !SNR_2500
|
||||
nsig=1
|
||||
if(f0.lt.100.0) then
|
||||
nsig=f0
|
||||
f0=1500
|
||||
endif
|
||||
|
||||
bcontest=nfiles.lt.0
|
||||
nfiles=abs(nfiles)
|
||||
twopi=8.0*atan(1.0)
|
||||
fs=12000.0 !Sample rate (Hz)
|
||||
dt=1.0/fs !Sample interval (s)
|
||||
tt=NSPS*dt !Duration of symbols (s)
|
||||
baud=1.0/tt !Keying rate (baud)
|
||||
bw=8*baud !Occupied bandwidth (Hz)
|
||||
txt=NZ*dt !Transmission length (s)
|
||||
bandwidth_ratio=2500.0/(fs/2.0)
|
||||
sig=sqrt(2*bandwidth_ratio) * 10.0**(0.05*snrdb)
|
||||
if(snrdb.gt.90.0) sig=1.0
|
||||
txt=NN*NSPS/12000.0
|
||||
|
||||
! Source-encode, then get itone()
|
||||
if(index(msg40,';').le.0) then
|
||||
i3bit=0
|
||||
msg=msg40(1:22)
|
||||
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
write(*,1000) f0,xdt,txt,snrdb,bw,msgsent
|
||||
1000 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||
' BW:',f4.1,2x,a22)
|
||||
else
|
||||
call foxgen_wrap(msg40,msgbits,itone)
|
||||
write(*,1001) f0,xdt,txt,snrdb,bw,msg40
|
||||
1001 format('f0:',f9.3,' DT:',f6.2,' TxT:',f6.1,' SNR:',f6.1, &
|
||||
' BW:',f4.1,2x,a40)
|
||||
endif
|
||||
|
||||
write(*,1030) msgbits(1:56)
|
||||
1030 format(/'Call1: ',28i1,' Call2: ',28i1)
|
||||
write(*,1032) msgbits(57:72),msgbits(73:75),msgbits(76:87)
|
||||
1032 format('Grid: ',16i1,' 3Bit: ',3i1,' CRC12: ',12i1)
|
||||
write(*,1034) itone
|
||||
1034 format(/'Channel symbols:'/79i1/)
|
||||
|
||||
msg0=msg
|
||||
do ifile=1,nfiles
|
||||
c=0.
|
||||
do isig=1,nsig
|
||||
c0=0.
|
||||
if(nsig.eq.2) then
|
||||
if(index(msg,'R-').gt.0) f0=500
|
||||
i1=index(msg,' ')
|
||||
msg(i1+4:i1+4)=char(ichar('A')+isig-1)
|
||||
if(isig.eq.2) then
|
||||
f0=f0+100
|
||||
endif
|
||||
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
endif
|
||||
if(nsig.eq.25) then
|
||||
f0=(isig+2)*100.0
|
||||
else if(nsig.eq.50) then
|
||||
msg=msg0
|
||||
f0=1000.0 + (isig-1)*60.0
|
||||
i1=index(msg,' ')
|
||||
i2=index(msg(i1+1:),' ') + i1
|
||||
msg(i1+2:i1+2)=char(ichar('0')+mod(isig-1,10))
|
||||
msg(i1+3:i1+3)=char(ichar('A')+mod(isig-1,26))
|
||||
msg(i1+4:i1+4)=char(ichar('A')+mod(isig-1,26))
|
||||
msg(i1+5:i1+5)=char(ichar('A')+mod(isig-1,26))
|
||||
write(msg(i2+3:i2+4),'(i2.2)') isig-1
|
||||
if(ifile.ge.2 .and. isig.eq.ifile-1) then
|
||||
write(msg(i2+1:i2+4),1002) -isig
|
||||
1002 format('R',i3.2)
|
||||
f0=600.0 + mod(isig-1,5)*60.0
|
||||
endif
|
||||
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
|
||||
endif
|
||||
k=-1 + nint((xdt+0.5+0.01*gran())/dt)
|
||||
! k=-1 + nint((xdt+0.5)/dt)
|
||||
ia=k+1
|
||||
phi=0.0
|
||||
do j=1,NN !Generate complex waveform
|
||||
dphi=twopi*(f0+itone(j)*baud)*dt
|
||||
do i=1,NSPS
|
||||
k=k+1
|
||||
phi=mod(phi+dphi,twopi)
|
||||
if(k.ge.0 .and. k.lt.NMAX) c0(k)=cmplx(cos(phi),sin(phi))
|
||||
enddo
|
||||
enddo
|
||||
if(fspread.ne.0.0 .or. delay.ne.0.0) call watterson(c0,NMAX,fs,delay,fspread)
|
||||
c=c+sig*c0
|
||||
enddo
|
||||
ib=k
|
||||
wave=real(c)
|
||||
peak=maxval(abs(wave(ia:ib)))
|
||||
rms=sqrt(dot_product(wave(ia:ib),wave(ia:ib))/NWAVE)
|
||||
nslots=1
|
||||
if(width.gt.0.0) call filt8(f0,nslots,width,wave)
|
||||
|
||||
if(snrdb.lt.90) then
|
||||
do i=1,NMAX !Add gaussian noise at specified SNR
|
||||
xnoise=gran()
|
||||
! wave(i)=wave(i) + xnoise
|
||||
! if(i.ge.ia .and. i.le.ib) write(30,3001) i,wave(i)/peak
|
||||
!3001 format(i8,f12.6)
|
||||
wave(i)=wave(i) + xnoise
|
||||
enddo
|
||||
endif
|
||||
|
||||
fac=32767.0
|
||||
rms=100.0
|
||||
if(snrdb.ge.90.0) iwave(1:NMAX)=nint(fac*wave)
|
||||
if(snrdb.lt.90.0) iwave(1:NMAX)=nint(rms*wave)
|
||||
|
||||
h=default_header(12000,NMAX)
|
||||
write(fname,1102) ifile
|
||||
1102 format('000000_',i6.6,'.wav')
|
||||
open(10,file=fname,status='unknown',access='stream')
|
||||
write(10) h,iwave !Save to *.wav file
|
||||
close(10)
|
||||
write(*,1110) ifile,xdt,f0,snrdb,fname
|
||||
1110 format(i4,f7.2,f8.2,f7.1,2x,a17)
|
||||
enddo
|
||||
|
||||
999 end program ft8sim
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
subroutine genft8refsig(itone,cref,f0)
|
||||
include 'ft8_params.f90'
|
||||
|
||||
complex cref(NN*NSPS)
|
||||
integer itone(NN)
|
||||
real*8 twopi,phi,dphi,dt,xnsps
|
||||
data twopi/0.d0/
|
||||
save twopi
|
||||
if( twopi .lt. 0.1 ) twopi=8.d0*atan(1.d0)
|
||||
|
||||
xnsps=NSPS*1.0d0
|
||||
dt=1.d0/12000.d0
|
||||
phi=0.d0
|
||||
k=1
|
||||
do i=1,NN
|
||||
dphi=twopi*(f0*dt+itone(i)/xnsps)
|
||||
do is=1,NSPS
|
||||
cref(k)=cmplx(cos(phi),sin(phi))
|
||||
phi=mod(phi+dphi,twopi)
|
||||
k=k+1
|
||||
enddo
|
||||
enddo
|
||||
return
|
||||
end subroutine genft8refsig
|
@ -1,63 +0,0 @@
|
||||
subroutine subtractft8(dd,itone,f0,dt)
|
||||
|
||||
! Subtract an ft8 signal
|
||||
!
|
||||
! Measured signal : dd(t) = a(t)cos(2*pi*f0*t+theta(t))
|
||||
! Reference signal : cref(t) = exp( j*(2*pi*f0*t+phi(t)) )
|
||||
! Complex amp : cfilt(t) = LPF[ dd(t)*CONJG(cref(t)) ]
|
||||
! Subtract : dd(t) = dd(t) - 2*REAL{cref*cfilt}
|
||||
|
||||
use timer_module, only: timer
|
||||
|
||||
include 'ft8_params.f90'
|
||||
parameter (NFRAME=NSPS*NN)
|
||||
parameter (NFFT=NMAX, NFILT=1400)
|
||||
|
||||
real*4 dd(NMAX), window(-NFILT/2:NFILT/2)
|
||||
complex cref,camp,cfilt,cw
|
||||
integer itone(NN)
|
||||
logical first
|
||||
data first/.true./
|
||||
common/heap8/cref(NFRAME),camp(NMAX),cfilt(NMAX),cw(NMAX)
|
||||
save first
|
||||
|
||||
nstart=dt*12000+1
|
||||
call genft8refsig(itone,cref,f0)
|
||||
camp=0.
|
||||
do i=1,nframe
|
||||
id=nstart-1+i
|
||||
if(id.ge.1.and.id.le.NMAX) camp(i)=dd(id)*conjg(cref(i))
|
||||
enddo
|
||||
|
||||
if(first) then
|
||||
! Create and normalize the filter
|
||||
pi=4.0*atan(1.0)
|
||||
fac=1.0/float(nfft)
|
||||
sum=0.0
|
||||
do j=-NFILT/2,NFILT/2
|
||||
window(j)=cos(pi*j/NFILT)**2
|
||||
sum=sum+window(j)
|
||||
enddo
|
||||
cw=0.
|
||||
cw(1:NFILT+1)=window/sum
|
||||
cw=cshift(cw,NFILT/2+1)
|
||||
call four2a(cw,nfft,1,-1,1)
|
||||
cw=cw*fac
|
||||
first=.false.
|
||||
endif
|
||||
|
||||
cfilt=0.0
|
||||
cfilt(1:nframe)=camp(1:nframe)
|
||||
call four2a(cfilt,nfft,1,-1,1)
|
||||
cfilt(1:nfft)=cfilt(1:nfft)*cw(1:nfft)
|
||||
call four2a(cfilt,nfft,1,1,1)
|
||||
|
||||
! Subtract the reconstructed signal
|
||||
do i=1,nframe
|
||||
j=nstart+i-1
|
||||
if(j.ge.1 .and. j.le.NMAX) dd(j)=dd(j)-2*REAL(cfilt(i)*cref(i))
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine subtractft8
|
||||
|
@ -1,144 +0,0 @@
|
||||
subroutine sync8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
|
||||
include 'ft8_params.f90'
|
||||
complex cx(0:NH1)
|
||||
real s(NH1,NHSYM)
|
||||
real savg(NH1)
|
||||
real sbase(NH1)
|
||||
real x(NFFT1)
|
||||
real sync2d(NH1,-JZ:JZ)
|
||||
real red(NH1)
|
||||
real candidate0(3,200)
|
||||
real candidate(3,200)
|
||||
real dd(NMAX)
|
||||
integer jpeak(NH1)
|
||||
integer indx(NH1)
|
||||
integer ii(1)
|
||||
integer icos7(0:6)
|
||||
data icos7/4,2,5,6,1,3,0/ !Costas 7x7 tone pattern
|
||||
equivalence (x,cx)
|
||||
|
||||
! Compute symbol spectra, stepping by NSTEP steps.
|
||||
savg=0.
|
||||
tstep=NSTEP/12000.0
|
||||
df=12000.0/NFFT1 !3.125 Hz
|
||||
fac=1.0/300.0
|
||||
do j=1,NHSYM
|
||||
ia=(j-1)*NSTEP + 1
|
||||
ib=ia+NSPS-1
|
||||
x(1:NSPS)=fac*dd(ia:ib)
|
||||
x(NSPS+1:)=0.
|
||||
call four2a(x,NFFT1,1,-1,0) !r2c FFT
|
||||
do i=1,NH1
|
||||
s(i,j)=real(cx(i))**2 + aimag(cx(i))**2
|
||||
enddo
|
||||
savg=savg + s(1:NH1,j) !Average spectrum
|
||||
enddo
|
||||
call baseline(savg,nfa,nfb,sbase)
|
||||
|
||||
ia=max(1,nint(nfa/df))
|
||||
ib=nint(nfb/df)
|
||||
nssy=NSPS/NSTEP ! # steps per symbol
|
||||
nfos=NFFT1/NSPS ! # frequency bin oversampling factor
|
||||
jstrt=0.5/tstep
|
||||
|
||||
candidate0=0.
|
||||
k=0
|
||||
|
||||
do i=ia,ib
|
||||
do j=-JZ,+JZ
|
||||
ta=0.
|
||||
tb=0.
|
||||
tc=0.
|
||||
t0a=0.
|
||||
t0b=0.
|
||||
t0c=0.
|
||||
do n=0,6
|
||||
k=j+jstrt+nssy*n
|
||||
if(k.ge.1.and.k.le.NHSYM) then
|
||||
ta=ta + s(i+nfos*icos7(n),k)
|
||||
t0a=t0a + sum(s(i:i+nfos*6:nfos,k))
|
||||
endif
|
||||
tb=tb + s(i+nfos*icos7(n),k+nssy*36)
|
||||
t0b=t0b + sum(s(i:i+nfos*6:nfos,k+nssy*36))
|
||||
if(k+nssy*72.le.NHSYM) then
|
||||
tc=tc + s(i+nfos*icos7(n),k+nssy*72)
|
||||
t0c=t0c + sum(s(i:i+nfos*6:nfos,k+nssy*72))
|
||||
endif
|
||||
enddo
|
||||
t=ta+tb+tc
|
||||
t0=t0a+t0b+t0c
|
||||
t0=(t0-t)/6.0
|
||||
sync_abc=t/t0
|
||||
|
||||
t=tb+tc
|
||||
t0=t0b+t0c
|
||||
t0=(t0-t)/6.0
|
||||
sync_bc=t/t0
|
||||
sync2d(i,j)=max(sync_abc,sync_bc)
|
||||
enddo
|
||||
enddo
|
||||
|
||||
red=0.
|
||||
do i=ia,ib
|
||||
ii=maxloc(sync2d(i,-JZ:JZ)) - 1 - JZ
|
||||
j0=ii(1)
|
||||
jpeak(i)=j0
|
||||
red(i)=sync2d(i,j0)
|
||||
! write(52,3052) i*df,red(i),db(red(i))
|
||||
!3052 format(3f12.3)
|
||||
enddo
|
||||
iz=ib-ia+1
|
||||
call indexx(red(ia:ib),iz,indx)
|
||||
ibase=indx(nint(0.40*iz)) - 1 + ia
|
||||
if(ibase.lt.1) ibase=1
|
||||
if(ibase.gt.nh1) ibase=nh1
|
||||
base=red(ibase)
|
||||
red=red/base
|
||||
|
||||
do i=1,min(200,iz)
|
||||
n=ia + indx(iz+1-i) - 1
|
||||
if(red(n).lt.syncmin.or.isnan(red(n)).or.k.eq.200) exit
|
||||
k=k+1
|
||||
candidate0(1,k)=n*df
|
||||
candidate0(2,k)=(jpeak(n)-1)*tstep
|
||||
candidate0(3,k)=red(n)
|
||||
enddo
|
||||
ncand=k
|
||||
|
||||
! Put nfqso at top of list, and save only the best of near-dupe freqs.
|
||||
do i=1,ncand
|
||||
if(abs(candidate0(1,i)-nfqso).lt.10.0) candidate0(1,i)=-candidate0(1,i)
|
||||
if(i.ge.2) then
|
||||
do j=1,i-1
|
||||
fdiff=abs(candidate0(1,i))-abs(candidate0(1,j))
|
||||
if(abs(fdiff).lt.AZ) then ! note: this dedupe difference is dependent on symbol spacing
|
||||
if(candidate0(3,i).ge.candidate0(3,j)) candidate0(3,j)=0.
|
||||
if(candidate0(3,i).lt.candidate0(3,j)) candidate0(3,i)=0.
|
||||
endif
|
||||
enddo
|
||||
endif
|
||||
enddo
|
||||
|
||||
fac=20.0/maxval(s)
|
||||
s=fac*s
|
||||
|
||||
! Sort by sync
|
||||
! call indexx(candidate0(3,1:ncand),ncand,indx)
|
||||
! Sort by frequency
|
||||
call indexx(candidate0(1,1:ncand),ncand,indx)
|
||||
k=1
|
||||
! do i=ncand,1,-1
|
||||
do i=1,ncand
|
||||
j=indx(i)
|
||||
! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then
|
||||
if( candidate0(3,j) .ge. syncmin ) then
|
||||
candidate(1,k)=abs(candidate0(1,j))
|
||||
candidate(2,k)=candidate0(2,j)
|
||||
candidate(3,k)=candidate0(3,j)
|
||||
k=k+1
|
||||
endif
|
||||
enddo
|
||||
ncand=k-1
|
||||
return
|
||||
end subroutine sync8
|
@ -1,56 +0,0 @@
|
||||
subroutine sync8d(cd0,i0,ctwk,itwk,sync)
|
||||
|
||||
! Compute sync power for a complex, downsampled FT8 signal.
|
||||
|
||||
include 'ft8_params.f90'
|
||||
|
||||
parameter(NP2=2812)
|
||||
complex cd0(3125)
|
||||
complex csync(0:6,NDOWNSPS)
|
||||
complex csync2(NDOWNSPS)
|
||||
complex ctwk(NDOWNSPS)
|
||||
complex z1,z2,z3
|
||||
logical first
|
||||
integer icos7(0:6)
|
||||
data icos7/4,2,5,6,1,3,0/
|
||||
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/NDOWN !Sample rate after downsampling
|
||||
dt2=1/fs2 !Corresponding sample interval
|
||||
taus=NDOWNSPS*dt2 !Symbol duration
|
||||
baud=1.0/taus !Keying rate
|
||||
do i=0,6
|
||||
phi=0.0
|
||||
dphi=twopi*icos7(i)*baud*dt2
|
||||
do j=1,NDOWNSPS
|
||||
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*NDOWNSPS !three Costas arrays
|
||||
i2=i1+36*NDOWNSPS
|
||||
i3=i1+72*NDOWNSPS
|
||||
csync2=csync(i,1:NDOWNSPS)
|
||||
if(itwk.eq.1) csync2=ctwk*csync2 !Tweak the frequency
|
||||
z1=0.
|
||||
z2=0.
|
||||
z3=0.
|
||||
if(i1.ge.1 .and. i1+(NDOWNSPS-1).le.NP2) z1=sum(cd0(i1:i1+(NDOWNSPS-1))*conjg(csync2))
|
||||
if(i2.ge.1 .and. i2+(NDOWNSPS-1).le.NP2) z2=sum(cd0(i2:i2+(NDOWNSPS-1))*conjg(csync2))
|
||||
if(i3.ge.1 .and. i3+(NDOWNSPS-1).le.NP2) z3=sum(cd0(i3:i3+(NDOWNSPS-1))*conjg(csync2))
|
||||
sync = sync + p(z1) + p(z2) + p(z3)
|
||||
enddo
|
||||
|
||||
return
|
||||
end subroutine sync8d
|
BIN
lib/ft8_decode.mod
Normal file
BIN
lib/ft8_decode.mod
Normal file
Binary file not shown.
@ -1,2 +1 @@
|
||||
parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
parameter (NWRITELOG=0) !Write log file?
|
||||
parameter (NWRITELOG=1) !Write log file?
|
||||
|
19
lib/js8/js8a_params.f90
Normal file
19
lib/js8/js8a_params.f90
Normal file
@ -0,0 +1,19 @@
|
||||
parameter (NCOSTAS=1) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
|
||||
parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=62) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
|
||||
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz
|
||||
parameter (ASTART=0.5) !Start delay in seconds
|
||||
parameter (ASYNCMIN=1.5) !Minimum Sync
|
||||
|
||||
parameter (KK=87) !Information bits (75 + CRC12)
|
||||
parameter (ND=58) !Data symbols
|
||||
parameter (NS=21) !Sync symbols (3 @ Costas 7x7)
|
||||
parameter (NN=NS+ND) !Total channel symbols (79)
|
||||
parameter (NZ=NSPS*NN) !Samples in full 15 s waveform (151,680)
|
||||
parameter (NMAX=NTXDUR*12000) !Samples in iwave (180,000)
|
||||
parameter (NFFT1=2*NSPS, NH1=NFFT1/2) !Length of FFTs for symbol spectra
|
||||
parameter (NSTEP=NSPS/4) !Rough time-sync step size
|
||||
parameter (NHSYM=NMAX/NSTEP-3) !Number of symbol spectra (1/4-sym steps)
|
||||
parameter (NDOWN=NSPS/NDOWNSPS) !Downsample factor to 32 samples per symbol
|
||||
parameter (NQSYMBOL=NDOWNSPS/4) !Downsample factor of a quarter symbol
|
@ -1,23 +1,6 @@
|
||||
!parameter (NSPS=480) !Samples per symbol at 12000 S/s
|
||||
!parameter (NTXDUR=5) !TX Duration in Seconds
|
||||
!parameter (NDOWNSPS=16) !Downsampled samples per symbol
|
||||
!parameter (AZ=6.0) !Near dupe sync spacing
|
||||
!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins
|
||||
!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ?
|
||||
parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
|
||||
|
||||
! parameter (NSPS=384, NTXDUR=4, NDOWNSPS=16, NDD=150, JZ=116) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=16, NDD=160, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=16, NDD=136, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s
|
||||
! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120, JZ=116) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s
|
||||
! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s
|
||||
! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s
|
||||
! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s
|
||||
parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=144) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s
|
||||
! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
|
||||
! parameter (NSPS=4000, NTXDUR=30, NDOWNSPS=20, NDD=90, JZ=62) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s
|
||||
parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=144) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s
|
||||
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz
|
||||
parameter (ASTART=0.2) !Start delay in seconds
|
||||
|
@ -1,23 +1,6 @@
|
||||
!parameter (NSPS=480) !Samples per symbol at 12000 S/s
|
||||
!parameter (NTXDUR=5) !TX Duration in Seconds
|
||||
!parameter (NDOWNSPS=16) !Downsampled samples per symbol
|
||||
!parameter (AZ=6.0) !Near dupe sync spacing
|
||||
!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins
|
||||
!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ?
|
||||
parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
|
||||
|
||||
! parameter (NSPS=384, NTXDUR=4, NDOWNSPS=16, NDD=150, JZ=116) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=16, NDD=160, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=16, NDD=136, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s
|
||||
parameter (NSPS=600, NTXDUR=6, NDOWNSPS=12, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s
|
||||
! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s
|
||||
! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s
|
||||
! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s
|
||||
! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=116) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s
|
||||
! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
|
||||
! parameter (NSPS=4000, NTXDUR=30, NDOWNSPS=20, NDD=90, JZ=62) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s
|
||||
parameter (NSPS=600, NTXDUR=6, NDOWNSPS=12, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s
|
||||
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz
|
||||
parameter (ASTART=0.1) !Start delay in seconds
|
||||
|
@ -494,3 +494,42 @@ subroutine js8dec(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
|
||||
|
||||
return
|
||||
end subroutine js8dec
|
||||
|
||||
subroutine normalizebmet(bmet,n)
|
||||
real bmet(n)
|
||||
|
||||
bmetav=sum(bmet)/real(n)
|
||||
bmet2av=sum(bmet*bmet)/real(n)
|
||||
var=bmet2av-bmetav*bmetav
|
||||
if( var .gt. 0.0 ) then
|
||||
bmetsig=sqrt(var)
|
||||
else
|
||||
bmetsig=sqrt(bmet2av)
|
||||
endif
|
||||
bmet=bmet/bmetsig
|
||||
return
|
||||
end subroutine normalizebmet
|
||||
|
||||
|
||||
function bessi0(x)
|
||||
! From Numerical Recipes
|
||||
real bessi0,x
|
||||
double precision p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9,y
|
||||
save p1,p2,p3,p4,p5,p6,p7,q1,q2,q3,q4,q5,q6,q7,q8,q9
|
||||
data p1,p2,p3,p4,p5,p6,p7/1.0d0,3.5156229d0,3.0899424d0,1.2067492d0, &
|
||||
0.2659732d0,0.360768d-1,0.45813d-2/
|
||||
data q1,q2,q3,q4,q5,q6,q7,q8,q9/0.39894228d0,0.1328592d-1, &
|
||||
0.225319d-2,-0.157565d-2,0.916281d-2,-0.2057706d-1, &
|
||||
0.2635537d-1,-0.1647633d-1,0.392377d-2/
|
||||
|
||||
if (abs(x).lt.3.75) then
|
||||
y=(x/3.75)**2
|
||||
bessi0=p1+y*(p2+y*(p3+y*(p4+y*(p5+y*(p6+y*p7)))))
|
||||
else
|
||||
ax=abs(x)
|
||||
y=3.75/ax
|
||||
bessi0=(exp(ax)/sqrt(ax))*(q1+y*(q2+y*(q3+y*(q4 &
|
||||
+y*(q5+y*(q6+y*(q7+y*(q8+y*q9))))))))
|
||||
endif
|
||||
return
|
||||
end function bessi0
|
||||
|
@ -1,24 +1,6 @@
|
||||
!parameter (NSPS=480) !Samples per symbol at 12000 S/s
|
||||
!parameter (NTXDUR=5) !TX Duration in Seconds
|
||||
!parameter (NDOWNSPS=16) !Downsampled samples per symbol
|
||||
!parameter (AZ=6.0) !Near dupe sync spacing
|
||||
!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins
|
||||
!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ?
|
||||
parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
|
||||
|
||||
! parameter (NSPS=384, NTXDUR=4, NDOWNSPS=12, NDD=125, JZ=250) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s
|
||||
! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s
|
||||
! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s
|
||||
! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s
|
||||
! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s
|
||||
! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=116) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s
|
||||
! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
|
||||
parameter (NSPS=3840, NTXDUR=28, NDOWNSPS=32, NDD=90, JZ=32) ! 25 Hz 3.125 baud 8 wpm -28.0dB (1.0Eb/N0) 25.28s
|
||||
! parameter (NSPS=4000, NTXDUR=28, NDOWNSPS=40, NDD=90, JZ=32) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s
|
||||
parameter (NSPS=3840, NTXDUR=28, NDOWNSPS=32, NDD=90, JZ=32) ! 25 Hz 3.125 baud 8 wpm -28.0dB (1.0Eb/N0) 25.28s
|
||||
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz
|
||||
parameter (ASTART=0.5) !Start delay in seconds
|
||||
|
@ -1,24 +1,6 @@
|
||||
!parameter (NSPS=480) !Samples per symbol at 12000 S/s
|
||||
!parameter (NTXDUR=5) !TX Duration in Seconds
|
||||
!parameter (NDOWNSPS=16) !Downsampled samples per symbol
|
||||
!parameter (AZ=6.0) !Near dupe sync spacing
|
||||
!parameter (NDD=136) !Downconverted FFT Bins - 100 Bins
|
||||
!parameter (JZ=62) !Sync Search Space over +/- 2.5s relative to 0.5s TX start time. 2.48 = 62/4/(12000/1920) ?
|
||||
parameter (NCOSTAS=2) !Which JS8 Costas Arrays to use (1=original, 2=three symmetrical costas)
|
||||
|
||||
|
||||
parameter (NSPS=384, NTXDUR=4, NDOWNSPS=12, NDD=125, JZ=250) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=384, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 250 Hz 31.25 baud 48 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
! parameter (NSPS=480, NTXDUR=5, NDOWNSPS=12, NDD=125, JZ=116) ! 200 Hz 25 baud 48 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=480, NTXDUR=6, NDOWNSPS=20, NDD=150, JZ=116) ! 200 Hz 25 baud 40 wpm -19.0dB (1.0Eb/N0) 3.16s
|
||||
! parameter (NSPS=500, NTXDUR=6, NDOWNSPS=20, NDD=144, JZ=116) ! 192 Hz 24 baud 40 wpm -19.4dB (1.0Eb/N0) 3.29s
|
||||
! parameter (NSPS=600, NTXDUR=6, NDOWNSPS=24, NDD=120, JZ=172) ! 160 Hz 20 baud 40 wpm -20.0dB (1.0Eb/N0) 3.95s
|
||||
! parameter (NSPS=768, NTXDUR=8, NDOWNSPS=24, NDD=125, JZ=116) ! 125 Hz 15.625 baud 32 wpm -21.0dB (1.0Eb/N0) 5.05s
|
||||
! parameter (NSPS=800, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 120 Hz 15 baud 32 wpm -21.2dB (1.0Eb/N0) 5.26s
|
||||
! parameter (NSPS=960, NTXDUR=8, NDOWNSPS=24, NDD=100, JZ=116) ! 100 Hz 12.50 baud 32 wpm -22.0dB (1.0Eb/N0) 5.92s
|
||||
! parameter (NSPS=1200, NTXDUR=10, NDOWNSPS=20, NDD=100, JZ=116) ! 80 Hz 10 baud 24 wpm -23.0dB (1.0Eb/N0) 7.90s
|
||||
! parameter (NSPS=1920, NTXDUR=15, NDOWNSPS=32, NDD=100, JZ=116) ! 50 Hz 6.250 baud 16 wpm -25.0dB (1.0Eb/N0) 12.64s
|
||||
! parameter (NSPS=3840, NTXDUR=30, NDOWNSPS=32, NDD=94, JZ=116) ! 24 Hz 3.125 baud 8 wpm -28.0dB (1.0Eb/N0) 25.28s
|
||||
! parameter (NSPS=4000, NTXDUR=28, NDOWNSPS=20, NDD=90, JZ=32) ! 24 Hz 3 baud 8 wpm -28.2dB (1.0Eb/N0) 26.33s
|
||||
parameter (NSPS=384, NTXDUR=4, NDOWNSPS=12, NDD=125, JZ=250) ! 250 Hz 31.25 baud 60 wpm -18.0dB (1.0Eb/N0) 2.52s
|
||||
|
||||
parameter (AZ=12000.0/(1.0*NSPS)*0.8d0) !Dedupe overlap in Hz
|
||||
parameter (ASTART=0.1) !Start delay in seconds
|
||||
|
@ -1,9 +1,10 @@
|
||||
program ldpcsim174
|
||||
program ldpcsim174js8
|
||||
! End to end test of the (174,75)/crc12 encoder and decoder.
|
||||
use crc
|
||||
use packjt
|
||||
|
||||
include 'ft8_params.f90'
|
||||
include 'js8_params.f90'
|
||||
include 'js8a_params.f90'
|
||||
|
||||
character*22 msg,msgsent,msgreceived
|
||||
character*8 arg
|
||||
@ -234,4 +235,4 @@ do i=1,87
|
||||
enddo
|
||||
close(25)
|
||||
|
||||
end program ldpcsim174
|
||||
end program ldpcsim174js8
|
@ -144,7 +144,6 @@ subroutine syncjs8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
enddo
|
||||
ncand=k
|
||||
|
||||
|
||||
! Save only the best of near-dupe freqs.
|
||||
do i=1,ncand
|
||||
if(i.ge.2) then
|
||||
@ -158,23 +157,18 @@ subroutine syncjs8(dd,nfa,nfb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
endif
|
||||
enddo
|
||||
|
||||
! Put nfqso at top of list
|
||||
do i=1,ncand
|
||||
if(abs(candidate0(1,i)-nfqso).lt.10.0) candidate0(1,i)=-candidate0(1,i)
|
||||
enddo
|
||||
|
||||
fac=20.0/maxval(s)
|
||||
s=fac*s
|
||||
|
||||
! Sort by sync
|
||||
! call indexx(candidate0(3,1:ncand),ncand,indx)
|
||||
|
||||
! Sort by frequency
|
||||
call indexx(candidate0(1,1:ncand),ncand,indx)
|
||||
|
||||
k=1
|
||||
! do i=ncand,1,-1
|
||||
do i=1,ncand
|
||||
j=indx(i)
|
||||
! if( candidate0(3,j) .ge. syncmin .and. candidate0(2,j).ge.-1.5 ) then
|
||||
if( candidate0(3,j) .ge. syncmin ) then
|
||||
candidate(1,k)=abs(candidate0(1,j))
|
||||
candidate(2,k)=candidate0(2,j)
|
||||
|
@ -1,25 +1,16 @@
|
||||
module ft8_decode
|
||||
module js8a_decode
|
||||
|
||||
parameter (MAXFOX=1000)
|
||||
character*12 c2fox(MAXFOX)
|
||||
character*4 g2fox(MAXFOX)
|
||||
integer nsnrfox(MAXFOX)
|
||||
integer nfreqfox(MAXFOX)
|
||||
integer n30fox(MAXFOX)
|
||||
integer n30z
|
||||
integer nfox
|
||||
|
||||
type :: ft8_decoder
|
||||
procedure(ft8_decode_callback), pointer :: callback
|
||||
type :: js8a_decoder
|
||||
procedure(js8a_decode_callback), pointer :: callback
|
||||
contains
|
||||
procedure :: decode
|
||||
end type ft8_decoder
|
||||
end type js8a_decoder
|
||||
|
||||
abstract interface
|
||||
subroutine ft8_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
import ft8_decoder
|
||||
subroutine js8a_decode_callback (this,sync,snr,dt,freq,decoded,nap,qual)
|
||||
import js8a_decoder
|
||||
implicit none
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
class(js8a_decoder), intent(inout) :: this
|
||||
real, intent(in) :: sync
|
||||
integer, intent(in) :: snr
|
||||
real, intent(in) :: dt
|
||||
@ -27,7 +18,7 @@ module ft8_decode
|
||||
character(len=37), intent(in) :: decoded
|
||||
integer, intent(in) :: nap
|
||||
real, intent(in) :: qual
|
||||
end subroutine ft8_decode_callback
|
||||
end subroutine js8a_decode_callback
|
||||
end interface
|
||||
|
||||
contains
|
||||
@ -37,11 +28,11 @@ contains
|
||||
mycall12,mygrid6,hiscall12,hisgrid6)
|
||||
! use wavhdr
|
||||
use timer_module, only: timer
|
||||
include 'ft8/ft8_params.f90'
|
||||
! type(hdr) h
|
||||
use js8a_module
|
||||
|
||||
class(ft8_decoder), intent(inout) :: this
|
||||
procedure(ft8_decode_callback) :: callback
|
||||
class(js8a_decoder), intent(inout) :: this
|
||||
procedure(js8a_decode_callback) :: callback
|
||||
real s(NH1,NHSYM)
|
||||
real sbase(NH1)
|
||||
real candidate(3,200)
|
||||
@ -83,7 +74,7 @@ contains
|
||||
if(ndepth.ge.2) npass=3
|
||||
do ipass=1,npass
|
||||
newdat=.true. ! Is this a problem? I hijacked newdat.
|
||||
syncmin=1.5
|
||||
syncmin=ASYNCMIN
|
||||
if(ipass.eq.1) then
|
||||
lsubtract=.true.
|
||||
if(ndepth.eq.1) lsubtract=.false.
|
||||
@ -96,9 +87,14 @@ contains
|
||||
lsubtract=.false.
|
||||
endif
|
||||
|
||||
call timer('sync8 ',0)
|
||||
call sync8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
call timer('sync8 ',1)
|
||||
call timer('syncjs8 ',0)
|
||||
call syncjs8(dd,ifa,ifb,syncmin,nfqso,s,candidate,ncand,sbase)
|
||||
call timer('syncjs8 ',1)
|
||||
|
||||
if(NWRITELOG.eq.1) then
|
||||
write(*,*) '<DecodeDebug>', ncand, "candidates"
|
||||
flush(6)
|
||||
endif
|
||||
|
||||
do icand=1,ncand
|
||||
sync=candidate(3,icand)
|
||||
@ -106,16 +102,28 @@ contains
|
||||
xdt=candidate(2,icand)
|
||||
xbase=10.0**(0.1*(sbase(nint(f1/(12000.0/NFFT1)))-40.0)) ! 3.125Hz
|
||||
nsnr0=min(99,nint(10.0*log10(sync) - 25.5)) !### empirical ###
|
||||
call timer('ft8b ',0)
|
||||
call ft8b(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lft8apon, &
|
||||
|
||||
if(NWRITELOG.eq.1) then
|
||||
write(*,*) '<DecodeDebug> candidate', icand, 'f1', f1, 'sync', sync, 'xdt', xdt, 'xbase', xbase
|
||||
flush(6)
|
||||
endif
|
||||
|
||||
call timer('js8dec ',0)
|
||||
call js8dec(dd,newdat,nQSOProgress,nfqso,nftx,ndepth,lft8apon, &
|
||||
lapcqonly,napwid,lsubtract,nagain,iaptype,mycall12,mygrid6, &
|
||||
hiscall12,bcontest,sync,f1,xdt,xbase,apsym,nharderrors,dmin, &
|
||||
nbadcrc,iappass,iera,msg37,xsnr)
|
||||
message=msg37(1:22) !###
|
||||
nsnr=nint(xsnr)
|
||||
xdt=xdt-0.5
|
||||
xdt=xdt-ASTART
|
||||
hd=nharderrors+dmin
|
||||
call timer('ft8b ',1)
|
||||
|
||||
if(NWRITELOG.eq.1) then
|
||||
write(*,*) '<DecodeDebug> candidate', icand, 'hard', hd, 'nbadcrc', nbadcrc
|
||||
flush(6)
|
||||
endif
|
||||
|
||||
call timer('js8dec ',1)
|
||||
if(nbadcrc.eq.0) then
|
||||
ldupe=.false.
|
||||
do id=1,ndecodes
|
||||
@ -131,9 +139,14 @@ contains
|
||||
call this%callback(sync,nsnr,xdt,f1,msg37,iaptype,qual)
|
||||
endif
|
||||
endif
|
||||
|
||||
if(NWRITELOG.eq.1) then
|
||||
write(*,*) '<DecodeDebug> ---'
|
||||
flush(6)
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
return
|
||||
end subroutine decode
|
||||
|
||||
end module ft8_decode
|
||||
end module js8a_decode
|
13
lib/js8a_module.f90
Normal file
13
lib/js8a_module.f90
Normal file
@ -0,0 +1,13 @@
|
||||
module js8a_module
|
||||
include 'js8/js8_params.f90'
|
||||
include 'js8/js8a_params.f90'
|
||||
|
||||
contains
|
||||
include 'js8/baselinejs8.f90'
|
||||
include 'js8/syncjs8.f90'
|
||||
include 'js8/js8_downsample.f90'
|
||||
include 'js8/syncjs8d.f90'
|
||||
include 'js8/genjs8refsig.f90'
|
||||
include 'js8/subtractjs8.f90'
|
||||
include 'js8/js8dec.f90'
|
||||
end module js8a_module
|
@ -1,175 +0,0 @@
|
||||
program ldpcsim
|
||||
|
||||
use, intrinsic :: iso_c_binding
|
||||
use iso_c_binding, only: c_loc,c_size_t
|
||||
use hashing
|
||||
use packjt
|
||||
parameter(NRECENT=10)
|
||||
character*12 recent_calls(NRECENT)
|
||||
character*22 msg,msgsent,msgreceived
|
||||
character*8 arg
|
||||
integer*1, allocatable :: codeword(:), decoded(:), message(:)
|
||||
integer*1, target:: i1Msg8BitBytes(10)
|
||||
integer*1 i1hash(4)
|
||||
integer*1 msgbits(80)
|
||||
integer*4 i4Msg6BitWords(13)
|
||||
integer ihash
|
||||
integer nerrtot(128),nerrdec(128)
|
||||
real*8, allocatable :: lratio(:), rxdata(:), rxavgd(:)
|
||||
real, allocatable :: yy(:), llr(:)
|
||||
equivalence(ihash,i1hash)
|
||||
|
||||
do i=1,NRECENT
|
||||
recent_calls(i)=' '
|
||||
enddo
|
||||
nerrtot=0
|
||||
nerrdec=0
|
||||
|
||||
nargs=iargc()
|
||||
if(nargs.ne.4) then
|
||||
print*,'Usage: ldpcsim niter navg #trials s '
|
||||
print*,'eg: ldpcsim 10 1 1000 0.75'
|
||||
return
|
||||
endif
|
||||
call getarg(1,arg)
|
||||
read(arg,*) max_iterations
|
||||
call getarg(2,arg)
|
||||
read(arg,*) navg
|
||||
call getarg(3,arg)
|
||||
read(arg,*) ntrials
|
||||
call getarg(4,arg)
|
||||
read(arg,*) s
|
||||
|
||||
! don't count hash bits as data bits
|
||||
N=128
|
||||
K=72
|
||||
rate=real(K)/real(N)
|
||||
|
||||
write(*,*) "rate: ",rate
|
||||
|
||||
write(*,*) "niter= ",max_iterations," navg= ",navg," s= ",s
|
||||
|
||||
allocate ( codeword(N), decoded(K), message(K) )
|
||||
allocate ( lratio(N), rxdata(N), rxavgd(N), yy(N), llr(N) )
|
||||
|
||||
msg="K9AN K1JT EN50"
|
||||
call packmsg(msg,i4Msg6BitWords,itype,.false.) !Pack into 12 6-bit bytes
|
||||
call unpackmsg(i4Msg6BitWords,msgsent,.false.,' ') !Unpack to get msgsent
|
||||
write(*,*) "message sent ",msgsent
|
||||
|
||||
i4=0
|
||||
ik=0
|
||||
im=0
|
||||
do i=1,12
|
||||
nn=i4Msg6BitWords(i)
|
||||
do j=1, 6
|
||||
ik=ik+1
|
||||
i4=i4+i4+iand(1,ishft(nn,j-6))
|
||||
i4=iand(i4,255)
|
||||
if(ik.eq.8) then
|
||||
im=im+1
|
||||
! if(i4.gt.127) i4=i4-256
|
||||
i1Msg8BitBytes(im)=i4
|
||||
ik=0
|
||||
endif
|
||||
enddo
|
||||
enddo
|
||||
|
||||
ihash=nhash(c_loc(i1Msg8BitBytes),int(9,c_size_t),146)
|
||||
ihash=2*iand(ihash,32767) !Generate the 8-bit hash
|
||||
i1Msg8BitBytes(10)=i1hash(1) !Hash code to byte 10
|
||||
mbit=0
|
||||
do i=1, 10
|
||||
i1=i1Msg8BitBytes(i)
|
||||
do ibit=1,8
|
||||
mbit=mbit+1
|
||||
msgbits(mbit)=iand(1,ishft(i1,ibit-8))
|
||||
enddo
|
||||
enddo
|
||||
call encode_msk144(msgbits,codeword)
|
||||
call init_random_seed()
|
||||
|
||||
write(*,*) "Eb/N0 SNR2500 ngood nundetected nbadhash sigma"
|
||||
do idb = -6, 14
|
||||
db=idb/2.0-1.0
|
||||
sigma=1/sqrt( 2*rate*(10**(db/10.0)) )
|
||||
ngood=0
|
||||
nue=0
|
||||
nbadhash=0
|
||||
|
||||
do itrial=1, ntrials
|
||||
rxavgd=0d0
|
||||
do iav=1,navg
|
||||
call sgran()
|
||||
! Create a realization of a noisy received word
|
||||
do i=1,N
|
||||
rxdata(i) = 2.0*codeword(i)-1.0 + sigma*gran()
|
||||
enddo
|
||||
rxavgd=rxavgd+rxdata
|
||||
enddo
|
||||
rxdata=rxavgd
|
||||
nerr=0
|
||||
do i=1,N
|
||||
if( rxdata(i)*(2*codeword(i)-1.0) .lt. 0 ) nerr=nerr+1
|
||||
enddo
|
||||
nerrtot(nerr)=nerrtot(nerr)+1
|
||||
|
||||
! Correct signal normalization is important for this decoder.
|
||||
rxav=sum(rxdata)/N
|
||||
rx2av=sum(rxdata*rxdata)/N
|
||||
rxsig=sqrt(rx2av-rxav*rxav)
|
||||
rxdata=rxdata/rxsig
|
||||
! To match the metric to the channel, s should be set to the noise standard deviation.
|
||||
! For now, set s to the value that optimizes decode probability near threshold.
|
||||
! The s parameter can be tuned to trade a few tenth's dB of threshold for an order of
|
||||
! magnitude in UER
|
||||
if( s .lt. 0 ) then
|
||||
ss=sigma
|
||||
else
|
||||
ss=s
|
||||
endif
|
||||
|
||||
llr=2.0*rxdata/(ss*ss)
|
||||
lratio=exp(llr)
|
||||
yy=rxdata
|
||||
|
||||
! max_iterations is max number of belief propagation iterations
|
||||
! call ldpc_decode(lratio, decoded, max_iterations, niterations, max_dither, ndither)
|
||||
! call amsdecode(yy, max_iterations, decoded, niterations)
|
||||
! call bitflipmsk144(rxdata, decoded, niterations)
|
||||
call bpdecode144(llr, max_iterations, decoded, niterations)
|
||||
|
||||
! If the decoder finds a valid codeword, niterations will be .ge. 0.
|
||||
if( niterations .ge. 0 ) then
|
||||
call extractmessage144(decoded,msgreceived,nhashflag,recent_calls,nrecent)
|
||||
if( nhashflag .ne. 1 ) then
|
||||
nbadhash=nbadhash+1
|
||||
endif
|
||||
nueflag=0
|
||||
|
||||
! Check the message plus hash against what was sent.
|
||||
do i=1,K
|
||||
if( msgbits(i) .ne. decoded(i) ) then
|
||||
nueflag=1
|
||||
endif
|
||||
enddo
|
||||
if( nhashflag .eq. 1 .and. nueflag .eq. 0 ) then
|
||||
ngood=ngood+1
|
||||
nerrdec(nerr)=nerrdec(nerr)+1
|
||||
else if( nhashflag .eq. 1 .and. nueflag .eq. 1 ) then
|
||||
nue=nue+1;
|
||||
endif
|
||||
endif
|
||||
enddo
|
||||
snr2500=db-3.5
|
||||
write(*,"(f4.1,4x,f5.1,1x,i8,1x,i8,1x,i8,8x,f5.2)") db,snr2500,ngood,nue,nbadhash,ss
|
||||
|
||||
enddo
|
||||
|
||||
open(unit=23,file='nerrhisto.dat',status='unknown')
|
||||
do i=1,128
|
||||
write(23,'(i4,2x,i10,i10,f10.2)') i,nerrdec(i),nerrtot(i),real(nerrdec(i))/real(nerrtot(i)+1e-10)
|
||||
enddo
|
||||
close(23)
|
||||
|
||||
end program ldpcsim
|
Loading…
Reference in New Issue
Block a user