mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-18 18:12:12 -05:00
5f9ed5a5ac
Build script now builds jt65. The tools jt65 and jt65sim usilize the options module for all comamnd line parsing. The tool jt65sim now has conventinal command line options and switchs. Default values have been added where appropriate and options documentation updated. An option to disable PRNG seeding has been added. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6276 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
262 lines
9.0 KiB
Fortran
262 lines
9.0 KiB
Fortran
program jt9
|
|
|
|
! Decoder for JT9. Can run stand-alone, reading data from *.wav files;
|
|
! or as the back end of wsjt-x, with data placed in a shared memory region.
|
|
|
|
use options
|
|
use prog_args
|
|
use, intrinsic :: iso_c_binding
|
|
use FFTW3
|
|
|
|
include 'constants.f90'
|
|
integer(C_INT) iret
|
|
integer*4 ihdr(11)
|
|
real*4 s(NSMAX)
|
|
integer*2 id2
|
|
character c
|
|
character(len=500) optarg, infile
|
|
character wisfile*80
|
|
integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700, &
|
|
fhigh=4000,nrxfreq=1500,ntrperiod=1,ndepth=60001
|
|
logical :: shmem = .false., read_files = .false., &
|
|
tx9 = .false., display_help = .false.
|
|
type (option) :: long_options(17) = [ &
|
|
option ('help', .false., 'h', 'Display this help message', ''), &
|
|
option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), &
|
|
option ('tr-period', .true., 'p', 'Tx/Rx period, default MINUTES=1', &
|
|
'MINUTES'), &
|
|
option ('executable-path', .true., 'e', &
|
|
'Location of subordinate executables (KVASD) default PATH="."', &
|
|
'PATH'), &
|
|
option ('data-path', .true., 'a', &
|
|
'Location of writeable data files, default PATH="."', 'PATH'), &
|
|
option ('temp-path', .true., 't', &
|
|
'Temporary files path, default PATH="."', 'PATH'), &
|
|
option ('lowest', .true., 'L', &
|
|
'Lowest frequency decoded (JT65), default HERTZ=200', 'HERTZ'), &
|
|
option ('highest', .true., 'H', &
|
|
'Highest frequency decoded, default HERTZ=4007', 'HERTZ'), &
|
|
option ('split', .true., 'S', &
|
|
'Lowest JT9 frequency decoded, default HERTZ=2700', 'HERTZ'), &
|
|
option ('rx-frequency', .true., 'f', &
|
|
'Receive frequency offset, default HERTZ=1500', 'HERTZ'), &
|
|
option ('patience', .true., 'w', &
|
|
'FFTW3 planing patience (0-4), default PATIENCE=1', 'PATIENCE'), &
|
|
option ('fft-threads', .true., 'm', &
|
|
'Number of threads to process large FFTs, default THREADS=1', &
|
|
'THREADS'), &
|
|
option ('jt65', .false., '6', 'JT65 mode', ''), &
|
|
option ('jt9', .false., '9', 'JT9 mode', ''), &
|
|
option ('jt4', .false., '4', 'JT4 mode', ''), &
|
|
option ('depth', .true., 'd', &
|
|
'JT9 decoding depth (1-3), default DEPTH=1', 'DEPTH'), &
|
|
option ('tx-jt9', .false., 'T', 'Tx mode is JT9', '') ]
|
|
|
|
character datetime*20,mycall*12,mygrid*6,hiscall*12,hisgrid*6
|
|
common/jt9com/ss(184,NSMAX),savg(NSMAX),id2(NMAX),nutc,ndiskdat, &
|
|
ntr,mousefqso,newdat,npts8a,nfa,nfsplit,nfb,ntol,kin,nzhsym, &
|
|
nsubmode,nagain,ndepth,ntxmode,nmode,minw,nclearave,minsync, &
|
|
emedelay,dttol,nlist,listutc(10),n2pass,nranera,naggressive, &
|
|
nrobust,nexp_decode,nspare(9),datetime,mycall,mygrid,hiscall,hisgrid
|
|
|
|
common/tracer/limtrace,lu
|
|
common/patience/npatience,nthreads
|
|
common/decstats/ntry65a,ntry65b,n65a,n65b,num9,numfano
|
|
data npatience/1/,nthreads/1/
|
|
|
|
do
|
|
call getopt('hs:e:a:r:m:p:d:f:w:t:964TL:S:H:',long_options,c, &
|
|
optarg,arglen,stat,offset,remain,.true.)
|
|
if (stat .ne. 0) then
|
|
exit
|
|
end if
|
|
select case (c)
|
|
case ('h')
|
|
display_help = .true.
|
|
case ('s')
|
|
shmem = .true.
|
|
shm_key = optarg(:arglen)
|
|
case ('e')
|
|
exe_dir = optarg(:arglen)
|
|
case ('a')
|
|
data_dir = optarg(:arglen)
|
|
case ('t')
|
|
temp_dir = optarg(:arglen)
|
|
case ('m')
|
|
read (optarg(:arglen), *) nthreads
|
|
case ('p')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) ntrperiod
|
|
case ('d')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) ndepth
|
|
case ('f')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) nrxfreq
|
|
case ('L')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) flow
|
|
case ('S')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) fsplit
|
|
case ('H')
|
|
read_files = .true.
|
|
read (optarg(:arglen), *) fhigh
|
|
case ('4')
|
|
read_files = .true.
|
|
mode = 4
|
|
case ('6')
|
|
read_files = .true.
|
|
if (mode.lt.65) mode = mode + 65
|
|
case ('9')
|
|
read_files = .true.
|
|
if (mode.lt.9.or.mode.eq.65) mode = mode + 9
|
|
case ('T')
|
|
read_files = .true.
|
|
tx9 = .true.
|
|
case ('w')
|
|
read (optarg(:arglen), *) npatience
|
|
end select
|
|
end do
|
|
|
|
if (display_help .or. stat .lt. 0 &
|
|
.or. (shmem .and. remain .gt. 0) &
|
|
.or. (read_files .and. remain .lt. 1) &
|
|
.or. (shmem .and. read_files)) then
|
|
|
|
print *, 'Usage: jt9 [OPTIONS] file1 [file2 ...]'
|
|
print *, ' Reads data from *.wav files.'
|
|
print *, ''
|
|
print *, ' jt9 -s <key> [-w patience] [-m threads] [-e path] [-a path] [-t path]'
|
|
print *, ' Gets data from shared memory region with key==<key>'
|
|
print *, ''
|
|
print *, 'OPTIONS:'
|
|
print *, ''
|
|
do i = 1, size (long_options)
|
|
call long_options(i) % print (6)
|
|
end do
|
|
go to 999
|
|
endif
|
|
|
|
iret=fftwf_init_threads() !Initialize FFTW threading
|
|
|
|
! Default to 1 thread, but use nthreads for the big ones
|
|
call fftwf_plan_with_nthreads(1)
|
|
|
|
! Import FFTW wisdom, if available
|
|
wisfile=trim(data_dir)//'/jt9_wisdom.dat'// C_NULL_CHAR
|
|
iret=fftwf_import_wisdom_from_filename(wisfile)
|
|
|
|
ntry65a=0
|
|
ntry65b=0
|
|
n65a=0
|
|
n65b=0
|
|
num9=0
|
|
numfano=0
|
|
|
|
if (shmem) then
|
|
call jt9a() !We're running under control of WSJT-X
|
|
go to 999
|
|
endif
|
|
|
|
limtrace=0 !We're running jt9 in stand-alone mode
|
|
lu=12
|
|
nflatten=0
|
|
|
|
do iarg = offset + 1, offset + remain
|
|
call get_command_argument (iarg, optarg, arglen)
|
|
infile = optarg(:arglen)
|
|
open(10,file=infile,access='stream',status='old',err=998)
|
|
read(10) ihdr
|
|
nfsample=ihdr(7)
|
|
nutc0=ihdr(1) !Silence compiler warning
|
|
i1=index(infile,'.wav')
|
|
if(i1.lt.1) i1=index(infile,'.WAV')
|
|
if(infile(i1-5:i1-5).eq.'_') then
|
|
read(infile(i1-4:i1-1),*,err=1) nutc0
|
|
else
|
|
read(infile(i1-6:i1-3),*,err=1) nutc0
|
|
endif
|
|
go to 2
|
|
1 nutc0=0
|
|
2 nsps=0
|
|
if(ntrperiod.eq.1) then
|
|
nsps=6912
|
|
nzhsym=181
|
|
else if(ntrperiod.eq.2) then
|
|
nsps=15360
|
|
nzhsym=178
|
|
else if(ntrperiod.eq.5) then
|
|
nsps=40960
|
|
nzhsym=172
|
|
else if(ntrperiod.eq.10) then
|
|
nsps=82944
|
|
nzhsym=171
|
|
else if(ntrperiod.eq.30) then
|
|
nsps=252000
|
|
nzhsym=167
|
|
endif
|
|
if(nsps.eq.0) stop 'Error: bad TRperiod'
|
|
|
|
kstep=nsps/2
|
|
k=0
|
|
nhsym0=-999
|
|
npts=(60*ntrperiod-6)*12000
|
|
if(iarg .eq. offset + 1) then
|
|
open(12,file=trim(data_dir)//'/timer.out',status='unknown')
|
|
call timer('jt9 ',0)
|
|
endif
|
|
|
|
id2=0 !??? Why is this necessary ???
|
|
|
|
do iblk=1,npts/kstep
|
|
k=iblk*kstep
|
|
call timer('read_wav',0)
|
|
read(10,end=3) id2(k-kstep+1:k)
|
|
go to 4
|
|
3 call timer('read_wav',1)
|
|
print*,'EOF on input file ',infile
|
|
exit
|
|
4 call timer('read_wav',1)
|
|
nhsym=(k-2048)/kstep
|
|
if(nhsym.ge.1 .and. nhsym.ne.nhsym0) then
|
|
if(mode.eq.9 .or. mode.eq.74) then
|
|
! Compute rough symbol spectra for the JT9 decoder
|
|
ingain=0
|
|
call timer('symspec ',0)
|
|
nminw=1
|
|
call symspec(k,ntrperiod,nsps,ingain,nminw,pxdb,s,df3, &
|
|
ihsym,npts8)
|
|
call timer('symspec ',1)
|
|
endif
|
|
nhsym0=nhsym
|
|
if(nhsym.ge.181) exit
|
|
endif
|
|
enddo
|
|
close(10)
|
|
call fillcom(nutc0,ndepth,nrxfreq,mode,tx9,flow,fsplit,fhigh)
|
|
call decoder(ss,id2,nfsample)
|
|
enddo
|
|
|
|
call timer('jt9 ',1)
|
|
call timer('jt9 ',101)
|
|
go to 999
|
|
|
|
998 print*,'Cannot open file:'
|
|
print*,infile
|
|
|
|
999 continue
|
|
! Output decoder statistics
|
|
write(12,1100) n65a,ntry65a,n65b,ntry65b,numfano,num9
|
|
1100 format(58('-')/' JT65_1 Tries_1 JT65_2 Tries_2 JT9 Tries'/ &
|
|
58('-')/6i8)
|
|
|
|
! Save wisdom and free memory
|
|
iret=fftwf_export_wisdom_to_filename(wisfile)
|
|
call four2a(a,-1,1,1,1)
|
|
call filbig(a,-1,1,0.0,0,0,0,0,0) !used for FFT plans
|
|
call fftwf_cleanup_threads()
|
|
call fftwf_cleanup()
|
|
|
|
end program jt9
|