mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-04-21 02:38:34 -04:00
SuperFox Tx now works with sftx[.exe] built as part of the wsjtx package.
This commit is contained in:
parent
4400f7464c
commit
dcb8c6ce6b
@ -602,17 +602,21 @@ set (wsjt_FSRCS
|
||||
lib/fst4/fst4_baseline.f90
|
||||
lib/77bit/hash22calc.f90
|
||||
|
||||
lib/superfox/foxgen2.f90
|
||||
lib/superfox/qpc_decode2.f90
|
||||
lib/superfox/qpc_likelihoods2.f90
|
||||
lib/superfox/qpc_snr.f90
|
||||
lib/superfox/qpc_sync.f90
|
||||
lib/superfox/sfox_ana.f90
|
||||
lib/superfox/sfox_assemble.f90
|
||||
lib/superfox/sfox_demod.f90
|
||||
lib/superfox/sfox_pack.f90
|
||||
lib/superfox/sfox_remove_ft8.f90
|
||||
lib/superfox/sfox_unpack.f90
|
||||
lib/superfox/sfox_wave.f90
|
||||
lib/superfox/sfox_wave_gfsk.f90
|
||||
lib/superfox/sfrx_sub.f90
|
||||
lib/superfox/sftx.f90
|
||||
lib/superfox/twkfreq2.f90
|
||||
)
|
||||
|
||||
@ -1253,6 +1257,9 @@ target_link_libraries (ft8sim wsjt_fort wsjt_cxx)
|
||||
#add_executable (sfrx lib/superfox/sfrx.f90)
|
||||
#target_link_libraries (sfrx wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (sftx lib/superfox/sftx.f90)
|
||||
target_link_libraries (sftx wsjt_fort wsjt_cxx)
|
||||
|
||||
add_executable (msk144sim lib/msk144sim.f90)
|
||||
target_link_libraries (msk144sim wsjt_fort wsjt_cxx)
|
||||
|
||||
|
75
lib/superfox/foxgen2.f90
Normal file
75
lib/superfox/foxgen2.f90
Normal file
@ -0,0 +1,75 @@
|
||||
subroutine foxgen2(nslots,cmsg,line,foxcall)
|
||||
|
||||
! Parse old-style Fox messages to extract the necessary pieces for a SuperFox
|
||||
! transmission.
|
||||
|
||||
use packjt77
|
||||
character*120 line
|
||||
character*40 cmsg(5) !Old-style Fox messages are here
|
||||
character*37 msg
|
||||
character*26 sfmsg
|
||||
character*13 mycall
|
||||
character*11 foxcall
|
||||
character*4 mygrid
|
||||
character*6 hiscall_1,hiscall_2
|
||||
character*4 rpt1,rpt2
|
||||
character*13 w(19)
|
||||
integer nw(19)
|
||||
integer ntype !Message type: 0 Free Text
|
||||
! 1 CQ MyCall MyGrid
|
||||
! 2 Call_1 MyCall RR73
|
||||
! 3 Call_1 MyCall rpt1
|
||||
! 4 Call_1 RR73; Call_2 <MyCall> rpt2
|
||||
|
||||
if(nslots.lt.1 .or. nslots.gt.5) return
|
||||
k=0
|
||||
do i=1,nslots
|
||||
hiscall_1=''
|
||||
hiscall_2=''
|
||||
mycall=''
|
||||
mygrid=''
|
||||
rpt1=''
|
||||
rpt2=''
|
||||
msg=cmsg(i)(1:37)
|
||||
call split77(msg,nwords,nw,w)
|
||||
ntype=0
|
||||
if(msg(1:3).eq.'CQ ') then
|
||||
ntype=1
|
||||
mycall=w(2)(1:12)
|
||||
mygrid=w(3)(1:4)
|
||||
else if(index(msg,';').gt.0) then
|
||||
ntype=4
|
||||
hiscall_1=w(1)(1:6)
|
||||
hiscall_2=w(3)(1:6)
|
||||
rpt1='RR73'
|
||||
rpt2=w(5)(1:4)
|
||||
mycall=w(4)(2:nw(4)-1)
|
||||
else if(index(msg,' RR73').gt.0) then
|
||||
ntype=2
|
||||
hiscall_1=w(1)(1:6)
|
||||
mycall=w(2)(1:12)
|
||||
rpt1='RR73'
|
||||
else if(nwords.eq.3 .and. nw(3).eq.3 .and. &
|
||||
(w(3)(1:1).eq.'-' .or. w(3)(1:1).eq.'+')) then
|
||||
ntype=3
|
||||
hiscall_1=w(1)(1:6)
|
||||
mycall=w(2)(1:12)
|
||||
rpt1=w(3)(1:4)
|
||||
endif
|
||||
|
||||
k=k+1
|
||||
if(ntype.le.3) call sfox_assemble(ntype,k,msg(1:26),mycall,mygrid,line)
|
||||
if(ntype.eq.4) then
|
||||
sfmsg=w(1)(1:nw(1))//' '//mycall(1:len(trim(mycall))+1)//'RR73'
|
||||
call sfox_assemble(2,k,sfmsg,mycall,mygrid,line)
|
||||
sfmsg=w(3)(1:nw(3))//' '//mycall(1:len(trim(mycall))+1)//w(5)(1:3)
|
||||
k=k+1
|
||||
call sfox_assemble(3,k,sfmsg,mycall,mygrid,line)
|
||||
endif
|
||||
enddo
|
||||
|
||||
call sfox_assemble(ntype,11,msg(1:26),mycall,mygrid,line) !k=11 to finish up
|
||||
foxcall=mycall(1:11)
|
||||
|
||||
return
|
||||
end subroutine foxgen2
|
92
lib/superfox/sfox_assemble.f90
Normal file
92
lib/superfox/sfox_assemble.f90
Normal file
@ -0,0 +1,92 @@
|
||||
subroutine sfox_assemble(ntype,k,msg,mycall0,mygrid0,line)
|
||||
|
||||
! In subsequent calls, assemble all necessary information for a SuperFox
|
||||
! transmission.
|
||||
|
||||
character*120 line
|
||||
character*26 msg
|
||||
character*26 msg0,msg1,msg2(5),msg3(5)
|
||||
character*4 rpt2(5)
|
||||
character*6 hiscall(10)
|
||||
character*13 mycall0,mycall
|
||||
character*4 mygrid0,mygrid
|
||||
integer ntype !Message type: 0 Free Text
|
||||
! 1 CQ MyCall MyGrid
|
||||
! 2 Call_1 MyCall RR73
|
||||
! 3 Call_1 MyCall rpt
|
||||
integer nmsg(0:3) !Number of messages of type ntype
|
||||
data nmsg/0,0,0,0/,nbits/0/,ntx/0/,nb_mycall/0/
|
||||
save
|
||||
|
||||
if(mycall0(1:1).ne.' ') mycall=mycall0
|
||||
if(mygrid0(1:1).ne.' ') mygrid=mygrid0
|
||||
if(ntype.ge.1) nb_mycall=28 !### Allow for nonstandard MyCall ###
|
||||
if(sum(nmsg).eq.0) then
|
||||
hiscall=' '
|
||||
rpt2=' '
|
||||
endif
|
||||
|
||||
if(k.le.10) then
|
||||
if(ntype.eq.0) then
|
||||
if(nbits+nb_mycall.le.191) then !Enough room for a free text message?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+142
|
||||
msg0=msg
|
||||
endif
|
||||
else if(ntype.eq.1) then
|
||||
if(nbits+nb_mycall.le.318) then !Enough room for a CQ ?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+15
|
||||
msg1=msg
|
||||
endif
|
||||
else if(ntype.eq.2) then
|
||||
if(nbits+nb_mycall.le.305) then !Enough room for a RR73 message?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+28
|
||||
j=nmsg(ntype)
|
||||
msg2(j)=msg
|
||||
i1=index(msg,' ')
|
||||
hiscall(j+5)=msg(1:i1-1)
|
||||
endif
|
||||
else if(ntype.eq.3) then
|
||||
if(nbits+nb_mycall.le.300) then !Enough room for a message with report?
|
||||
nmsg(ntype)=nmsg(ntype)+1
|
||||
nbits=nbits+33
|
||||
j=nmsg(ntype)
|
||||
msg3(j)=msg
|
||||
i1=index(msg,' ')
|
||||
hiscall(j)=msg(1:i1-1)
|
||||
i1=max(index(msg,'-'),index(msg,'+'))
|
||||
rpt2(j)=msg(i1:i1+3)
|
||||
endif
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
if(k.ge.11) then
|
||||
! All pieces are now available. Put them into a command line for external
|
||||
! program sfox_tx.
|
||||
ntx=ntx+1 !Transmission number
|
||||
nbits=nbits+nb_mycall !Add bits for MyCall
|
||||
|
||||
if(nmsg(1).ge.1) then
|
||||
line=msg1
|
||||
else
|
||||
line=trim(mycall)
|
||||
do i=1,nmsg(3)
|
||||
line=trim(line)//' '//trim(hiscall(i))//' '//rpt2(i)
|
||||
enddo
|
||||
do i=1,nmsg(2)
|
||||
line=trim(line)//' '//trim(hiscall(i+5))
|
||||
enddo
|
||||
endif
|
||||
|
||||
nmsg=0
|
||||
nbits=0
|
||||
nb_mycall=0
|
||||
hiscall=' '
|
||||
rpt2=' '
|
||||
endif
|
||||
|
||||
return
|
||||
end subroutine sfox_assemble
|
158
lib/superfox/sfox_pack.f90
Normal file
158
lib/superfox/sfox_pack.f90
Normal file
@ -0,0 +1,158 @@
|
||||
subroutine sfox_pack(line,ckey,bMoreCQs,bSendMsg,freeTextMsg,xin)
|
||||
|
||||
use qpc_mod
|
||||
use packjt
|
||||
use packjt77
|
||||
use julian
|
||||
integer stat
|
||||
integer*8 n47,n58,now
|
||||
integer*1 xin(0:49) !Packed message as 7-bit symbols
|
||||
logical*1 bMoreCQs,bSendMsg
|
||||
logical text
|
||||
character*120 line !SuperFox message pieces
|
||||
character*10 ckey
|
||||
character*26 freeTextMsg
|
||||
character*13 w(16)
|
||||
character*11 c11
|
||||
character*329 msgbits !Packed message as bits
|
||||
character*38 c
|
||||
data c/' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/'/
|
||||
|
||||
i0=index(line,'/')
|
||||
i3=0 !Default to i3=0, standard message
|
||||
|
||||
! Split the command line into words
|
||||
w=' '
|
||||
i1=1
|
||||
do j=1,16
|
||||
do i=i1,min(i1+12,120)
|
||||
if(line(i:i).eq.' ') exit
|
||||
enddo
|
||||
i2=i-1
|
||||
w(j)=line(i1:i2)
|
||||
do i=i2+1,120
|
||||
if(line(i:i).ne.' ') exit
|
||||
enddo
|
||||
i1=i
|
||||
if(i1.ge.120) exit
|
||||
enddo
|
||||
nwords=j
|
||||
|
||||
do i=1,nwords
|
||||
if(w(i)(1:1).eq.' ') then
|
||||
nwords=i-1
|
||||
exit
|
||||
endif
|
||||
enddo
|
||||
|
||||
do i=1,329 !Set all msgbits to '0'
|
||||
msgbits(i:i)='0'
|
||||
enddo
|
||||
|
||||
now=itime8()/30
|
||||
now=30*now
|
||||
read(ckey(5:10),*) nsignature
|
||||
|
||||
write(msgbits(307:326),'(b20.20)') nsignature !Insert the digital signature
|
||||
|
||||
if(w(1)(1:3).eq.'CQ ') then
|
||||
i3=3
|
||||
c11=w(2)(1:11)
|
||||
n58=0
|
||||
do i=1,11
|
||||
n58=n58*38 + index(c,c11(i:i)) - 1
|
||||
enddo
|
||||
write(msgbits(1:58),'(b58.58)') n58
|
||||
call packgrid(w(3)(1:4),n15,text)
|
||||
write(msgbits(59:73),'(b15.15)') n15
|
||||
write(msgbits(327:329),'(b3.3)') i3 !Message type i3=3
|
||||
go to 800
|
||||
endif
|
||||
|
||||
call pack28(w(1),n28) !Fox call
|
||||
write(msgbits(1:28),'(b28.28)') n28
|
||||
nh1=0 !Number of Hound calls with RR73
|
||||
nh2=0 !Number of Hound calls with report
|
||||
|
||||
! Default report is RR73 if we're also sending a free text message.
|
||||
if(bSendMsg) msgbits(141:160)='11111111111111111111'
|
||||
|
||||
j=29
|
||||
|
||||
! Process callsigns with RR73
|
||||
do i=2,nwords
|
||||
if(w(i)(1:1).eq.'+' .or. w(i)(1:1).eq.'-') cycle !Skip report words
|
||||
i1=min(i+1,nwords)
|
||||
if(w(i1)(1:1) .eq.'+' .or. w(i1)(1:1).eq.'-') cycle !Skip if i+1 is report
|
||||
call pack28(w(i),n28)
|
||||
write(msgbits(j:j+27),1002) n28 !Insert this call for RR73 message
|
||||
1002 format(b28.28)
|
||||
j=j+28
|
||||
nh1=nh1+1
|
||||
if( nht.ge.5 ) exit !At most 5 RR73 callsigns
|
||||
enddo
|
||||
|
||||
! Process callsigns with a report
|
||||
j=169
|
||||
j2=281
|
||||
if(bSendMsg) then
|
||||
i3=2
|
||||
j=29 + 28*nh1
|
||||
j2=141 + 5*nh1
|
||||
endif
|
||||
|
||||
do i=2,nwords
|
||||
i1=min(i+1,nwords)
|
||||
if(w(i1)(1:1).eq.'+' .or. w(i1)(1:1).eq.'-') then
|
||||
call pack28(w(i),n28)
|
||||
write(msgbits(j:j+27),1002) n28 !Insert this call
|
||||
read(w(i1),*) n !Valid reports are -18 to +12, plus RR73
|
||||
if(n.lt.-18) n=-18 !... Even numbers only ...
|
||||
if(n.gt.12) n=12
|
||||
write(msgbits(j2:j2+4),1000) n+18
|
||||
1000 format(b5.5)
|
||||
w(i1)=""
|
||||
nh2=nh2+1
|
||||
! print*,'C',i3,i,j,n,w(i)
|
||||
if( nh2.ge.4 .or. (nh1+nh2).ge.9 ) exit ! At most 4 callsigns w/reports
|
||||
j=j+28
|
||||
j2=j2+5
|
||||
endif
|
||||
enddo
|
||||
|
||||
800 if(bSendMsg) then
|
||||
i1=26
|
||||
do i=1,26
|
||||
if(freeTextMsg(i:i).ne.' ') i1=i
|
||||
enddo
|
||||
do i=i1+1,26
|
||||
freeTextMsg(i:i)='.'
|
||||
enddo
|
||||
if(i3.eq.3) then
|
||||
call packtext77(freeTextMsg(1:13),msgbits(74:144))
|
||||
call packtext77(freeTextMsg(14:26),msgbits(145:215))
|
||||
elseif(i3.eq.2) then
|
||||
call packtext77(freeTextMsg(1:13),msgbits(161:231))
|
||||
call packtext77(freeTextMsg(14:26),msgbits(232:302))
|
||||
endif
|
||||
write(msgbits(327:329),'(b3.3)') i3 !Message type i3=2
|
||||
endif
|
||||
if(bMoreCQs) msgbits(306:306)='1'
|
||||
|
||||
read(msgbits,1004) xin(0:46)
|
||||
1004 format(47b7)
|
||||
|
||||
mask21=2**21 - 1
|
||||
n47=47
|
||||
ncrc21=iand(nhash2(xin,n47,571),mask21) !Compute 21-bit CRC
|
||||
xin(47)=ncrc21/16384 !First 7 of 21 bits
|
||||
xin(48)=iand(ncrc21/128,127) !Next 7 bits
|
||||
xin(49)=iand(ncrc21,127) !Last 7 bits
|
||||
|
||||
xin=xin(49:0:-1) !Reverse the symbol order
|
||||
! NB: CRC is now in first three symbols, fox call in the last four.
|
||||
|
||||
read(msgbits(327:329),'(b3)') i3
|
||||
|
||||
return
|
||||
end subroutine sfox_pack
|
107
lib/superfox/sftx.f90
Normal file
107
lib/superfox/sftx.f90
Normal file
@ -0,0 +1,107 @@
|
||||
program sftx
|
||||
|
||||
! This program is required in order to create a SuperFox transmission.
|
||||
|
||||
! The present version goes through the following steps:
|
||||
! 1. Read old-style Fox messages from file 'sfox_1.dat' in the WSJT-X
|
||||
! writable data directory.
|
||||
! 2. Parse up to NSlots=5 messages to extract MyCall, up to 9 Hound
|
||||
! calls, and the report or RR73 to be sent to each Hound.
|
||||
! 3. Assemble and encode a single SuperFox message to produce itone(1:151),
|
||||
! the array of channel symbol values.
|
||||
! 4. Write the contents of array itone to file 'sfox_2.dat'.
|
||||
|
||||
use qpc_mod
|
||||
use sfox_mod
|
||||
character*120 fname !Corrected path for sfox_1.dat
|
||||
character*120 line !List of SuperFox message pieces
|
||||
character*40 cmsg(5) !Old-style Fox messages
|
||||
character*26 freeTextMsg
|
||||
character*2 arg
|
||||
character*10 ckey
|
||||
! character*9 foxkey
|
||||
character*11 foxcall0,foxcall
|
||||
logical*1 bMoreCQs,bSendMsg
|
||||
logical crc_ok
|
||||
real py(0:127,0:127) !Probabilities for received synbol values
|
||||
integer*8 n47
|
||||
integer itone(151) !SuperFox channel-symbol values
|
||||
integer*1 xin(0:49) !Packed message as 7-bit symbols
|
||||
integer*1 xdec(0:49) !Decoded message
|
||||
integer*1 y(0:127) !Encoded symbols as i*1 integers
|
||||
integer*1 ydec(0:127) !Decoded codeword
|
||||
integer*1 yy(0:10)
|
||||
integer chansym0(127) !Transmitted symbols, data only
|
||||
integer chansym(127) !Received symbols, data only
|
||||
integer isync(24) !Symbol numbers for sync tones
|
||||
data isync/1,2,4,7,11,16,22,29,37,39,42,43,45,48,52,57,63,70,78,80, &
|
||||
83,84,86,89/
|
||||
include 'gtag.f90'
|
||||
|
||||
narg=iargc()
|
||||
if(narg.ne.3) then
|
||||
print '(" Git tag: ",z9)',ntag
|
||||
go to 999
|
||||
endif
|
||||
|
||||
! sftx <message_file_name> <foxcall> <ckey>
|
||||
call getarg(1,fname)
|
||||
do i=1,len(trim(fname))
|
||||
if(fname(i:i).eq.'\\') fname(i:i)='/'
|
||||
enddo
|
||||
call getarg(2,foxcall0)
|
||||
call getarg(3,ckey)
|
||||
|
||||
! if((foxkey(foxcall0).ne.ckey).and.(INDEX(ckey,'OTP:').eq.0)) then ! neither kind
|
||||
! itone=-99
|
||||
! go to 100
|
||||
! endif
|
||||
|
||||
fsample=12000.0
|
||||
call sfox_init(7,127,50,'no',fspread,delay,fsample,24)
|
||||
open(25,file=trim(fname),status='unknown')
|
||||
do i=1,5
|
||||
read(25,1000,end=10) cmsg(i)
|
||||
1000 format(a40)
|
||||
enddo
|
||||
i=6
|
||||
10 close(25)
|
||||
nslots=i-1
|
||||
freeTextMsg=' '
|
||||
bMoreCQs=cmsg(1)(40:40).eq.'1'
|
||||
bSendMsg=cmsg(nslots)(39:39).eq.'1'
|
||||
if(bSendMsg) then
|
||||
freeTextMsg=cmsg(nslots)(1:26)
|
||||
if(nslots.gt.2) nslots=2
|
||||
endif
|
||||
|
||||
call foxgen2(nslots,cmsg,line,foxcall) !Parse old-style Fox messages
|
||||
|
||||
! Pack message information and CRC into xin(0:49)
|
||||
call sfox_pack(line,ckey,bMoreCQs,bSendMsg,freeTextMsg,xin)
|
||||
call qpc_encode(y,xin) !Encode the message to 128 symbols
|
||||
y=cshift(y,1) !Puncture the code by removing y(0)
|
||||
y(127)=0
|
||||
chansym0=y(0:126)
|
||||
|
||||
! Create the full itone sequence containing both data and sync symbols
|
||||
j=1
|
||||
k=0
|
||||
do i=1,NDS
|
||||
if(j.le.NS .and. i.eq.isync(j)) then
|
||||
if(j.lt.NS) j=j+1 !Index for next sync symbol
|
||||
itone(i)=0 !Insert sync symbol at tone 0
|
||||
else
|
||||
k=k+1
|
||||
itone(i)=chansym0(k) + 1 !Symbol value 0 transmitted as tone 1, etc.
|
||||
endif
|
||||
enddo
|
||||
|
||||
100 i1=max(index(fname,'sfox_1'),1)
|
||||
fname(i1:i1+9)='sfox_2.dat'
|
||||
open(25,file=trim(fname),status='unknown')
|
||||
write(25,1100) itone
|
||||
1100 format(20i4)
|
||||
close(25)
|
||||
|
||||
999 end program sftx
|
Loading…
Reference in New Issue
Block a user