Many improvements to ft2, including:

- SNR displayed on decode line
 - Separate transmit() subroutine
 - Output sent to all_ft2.txt
 - Display Rx level (hit L to toggle On/Off)
 - Auto-sequencing  (hit A to toggle On/Off)
This commit is contained in:
Joe Taylor 2019-01-16 13:10:36 -05:00
parent 60fb12dcd4
commit f194621695
4 changed files with 172 additions and 86 deletions

View File

@ -26,12 +26,13 @@ program ft2
call padevsub(idevin,idevout) call padevsub(idevin,idevout)
if(idevin.ne.ndevin .or. idevout.ne.ndevout) allok=.false. if(idevin.ne.ndevin .or. idevout.ne.ndevout) allok=.false.
i1=0 i1=0
! i1=ptt(nport,1,1,iptt) i1=ptt(nport,1,0,iptt)
if(i1.lt.0 .and. nport.ne.0) allok=.false. if(i1.lt.0 .and. nport.ne.0) allok=.false.
if(.not.allok) then if(.not.allok) then
write(*,"('Please fix setup error(s) and restart.')") write(*,"('Please fix setup error(s) and restart.')")
go to 999 go to 999
endif endif
open(12,file='all_ft2.txt',status='unknown',position='append')
nright=1 nright=1
iwrite=0 iwrite=0
@ -45,6 +46,11 @@ program ft2
tx_once=.false. tx_once=.false.
snrdb=99.0 snrdb=99.0
txmsg='CQ K1JT FN20' txmsg='CQ K1JT FN20'
ltx=.false.
lrx=.false.
autoseq=.false.
QSO_in_progress=.false.
ntxed=0
nargs=iargc() nargs=iargc()
if(nargs.eq.3) then if(nargs.eq.3) then
@ -54,8 +60,8 @@ program ft2
call getarg(3,arg) call getarg(3,arg)
read(arg,*) snrdb read(arg,*) snrdb
tx_once=.true. tx_once=.true.
call ft2_iwave(txmsg,f0,snrdb,iwave) ftx=1500.0
nTxOK=1 call transmit(-1,ftx,iptt)
endif endif
! Start the audio streams ! Start the audio streams
@ -70,38 +76,34 @@ program ft2
subroutine update(total_time,ic1,ic2) subroutine update(total_time,ic1,ic2)
real*8 total_time real*8 total_time
integer*8 count00,count0,count1,clkfreq integer*8 count0,count1,clkfreq
integer ptt integer ptt
integer*2 id(30000) integer*2 id(30000)
logical transmitted logical transmitted,level
character*30 line character*70 line
character cdate*8,ctime*10,cdatetime*17 character cdatetime*17
include 'gcom1.f90' include 'gcom1.f90'
data nt0/-1/,transmitted/.false./,snr/-99.0/,count00/-1/ data nt0/-1/,transmitted/.false./,snr/-99.0/
save nt0,transmitted,snr,count00,iptt data level/.false./
save nt0,transmitted,level,snr,iptt
if(ic1.ne.0 .or. ic2.ne.0) then if(ic1.ne.0 .or. ic2.ne.0) then
if(ic1.eq.27 .and. ic2.eq.0) ngo=0 !ESC if(ic1.eq.27 .and. ic2.eq.0) ngo=0 !ESC
if(nTxOK.eq.0 .and. ntransmitting.eq.0) then if(nTxOK.eq.0 .and. ntransmitting.eq.0) then
nd=0 nfunc=0
if(ic1.eq.0 .and. ic2.eq.59) nd=1 !F1 if(ic1.eq.0 .and. ic2.eq.59) nfunc=1 !F1
if(ic1.eq.0 .and. ic2.eq.60) nd=2 !F2 if(ic1.eq.0 .and. ic2.eq.60) nfunc=2 !F2
if(ic1.eq.0 .and. ic2.eq.61) nd=3 !F3 if(ic1.eq.0 .and. ic2.eq.61) nfunc=3 !F3
if(ic1.eq.0 .and. ic2.eq.62) nd=4 !F4 if(ic1.eq.0 .and. ic2.eq.62) nfunc=4 !F4
if(ic1.eq.0 .and. ic2.eq.63) nd=5 !F5 if(ic1.eq.0 .and. ic2.eq.63) nfunc=5 !F5
if(nd.gt.0) then if(nfunc.eq.1 .or. (nfunc.ge.2 .and. hiscall.ne.' ')) then
i1=ptt(nport,1,1,iptt) ftx=1500.0
ntxok=1 call transmit(nfunc,ftx,iptt)
if(nd.eq.1) txmsg='CQ K1JT FN20'
if(nd.eq.2) txmsg='K9AN K1JT 559 NJ'
if(nd.eq.3) txmsg='K9AN K1JT R 559 NJ'
if(nd.eq.4) txmsg='K9AN K1JT RR73'
if(nd.eq.5) txmsg='TNX STEVE 73'
call ft2_iwave(txmsg,1500.0,99.0,iwave)
print*,'Tx: ',txmsg
endif endif
endif endif
if(ic1.eq.13 .and. ic2.eq.0) hiscall=hiscall_next if(ic1.eq.13 .and. ic2.eq.0) hiscall=hiscall_next
if(ic1.eq.97 .and. ic2.eq.0) autoseq=.not.autoseq
if(ic1.eq.108 .and. ic2.eq.0) level=.not.level
endif endif
if(ntransmitting.eq.1) transmitted=.true. if(ntransmitting.eq.1) transmitted=.true.
@ -114,17 +116,30 @@ subroutine update(total_time,ic1,ic2)
nt=2*total_time nt=2*total_time
if(nt.gt.nt0 .or. ic1.ne.0 .or. ic2.ne.0) then if(nt.gt.nt0 .or. ic1.ne.0 .or. ic2.ne.0) then
k=iwrite-6000 if(level) then
if(k.lt.1) k=k+NRING ! Measure and display the average level of signal plus noise in past 0.5 s
sq=0. k=iwrite-6000
do i=1,6000 if(k.lt.1) k=k+NRING
k=k+1 sq=0.
if(k.gt.NRING) k=k-NRING do i=1,6000
x=y1(k) k=k+1
sq=sq + x*x if(k.gt.NRING) k=k-NRING
enddo x=y1(k)
sigdb=0. sq=sq + x*x
if(sq.gt.0.0) sigdb=db(sq/6000.0) enddo
sigdb=0.
if(sq.gt.0.0) sigdb=db(sq/6000.0)
n=sigdb
if(n.lt.1) n=1
if(n.gt.70) n=70
line=' '
line(n:n)='*'
write(*,1030) sigdb,ntxed,autoseq,QSO_in_progress,(line(i:i),i=1,n)
1030 format(f4.1,i3,2L2,1x,70a1)
! write(*,1020) nt,total_time,iwrite,itx,ntxok,ntransmitting,ndecodes, &
! snr,sigdb,line
!1020 format(i6,f9.3,i10,i6,3i3,f6.0,f6.1,1x,a30)
endif
k=iwrite-30000 k=iwrite-30000
if(k.lt.1) k=k+NRING if(k.lt.1) k=k+NRING
do i=1,30000 do i=1,30000
@ -136,27 +151,77 @@ subroutine update(total_time,ic1,ic2)
nfqso=1500 nfqso=1500
ndecodes=0 ndecodes=0
if(maxval(abs(id)).gt.0) then if(maxval(abs(id)).gt.0) then
call date_and_time(cdate,ctime)
cdatetime=cdate(3:8)//'_'//ctime
call system_clock(count0,clkfreq) call system_clock(count0,clkfreq)
call ft2_decode(cdatetime,nfqso,id,ndecodes) nrx=-1
call ft2_decode(cdatetime(),nfqso,id,ndecodes,mycall,hiscall,nrx)
call system_clock(count1,clkfreq) call system_clock(count1,clkfreq)
tdecode=float(count1-count0)/float(clkfreq) ! tdecode=float(count1-count0)/float(clkfreq)
if(count00.lt.0) count00=count0 ! write(*,3001) trun
trun=float(count1-count00)/float(clkfreq) !3001 format(f10.3)
if(autoseq .and.nrx.eq.2) QSO_in_progress=.true.
if(autoseq .and. QSO_in_progress .and. nrx.ge.1 .and. nrx.le.4) then
lrx(nrx)=.true.
ftx=1500.0
if(ntxed.eq.1) then
if(nrx.eq.2) then
call transmit(3,ftx,iptt)
else
call transmit(1,ftx,iptt)
endif
endif
if(ntxed.eq.2) then
if(nrx.eq.3) then
call transmit(4,ftx,iptt)
QSO_in_progress=.false.
else
call transmit(2,ftx,iptt)
endif
endif
if(ntxed.eq.3) then
if(nrx.eq.4) then
QSO_in_progress=.false.
else
call transmit(3,ftx,iptt)
endif
endif
endif
endif endif
n=2*sigdb-30.0
if(n.lt.1) n=1
if(n.gt.30) n=30
line=' '
line(n:n)='*'
! write(*,1010) nt,total_time,iwrite,itx,ntxok,ntransmitting,ndecodes, &
! snr,sigdb,line
!1010 format(i6,f9.3,i10,i6,3i3,f6.0,f6.1,1x,a30)
nt0=nt nt0=nt
max1=0
max2=0
endif endif
return return
end subroutine update end subroutine update
character*17 function cdatetime()
character cdate*8,ctime*10
call date_and_time(cdate,ctime)
cdatetime=cdate(3:8)//'_'//ctime
return
end function cdatetime
subroutine transmit(nfunc,ftx,iptt)
include 'gcom1.f90'
character*17 cdatetime
integer ptt
if(nfunc.eq.1) txmsg='CQ '//trim(mycall)//' '//mygrid
if(nfunc.eq.2) txmsg=trim(hiscall)//' '//trim(mycall)// &
' 559 '//trim(exch)
if(nfunc.eq.3) txmsg=trim(hiscall)//' '//trim(mycall)// &
' R 559 '//trim(exch)
if(nfunc.eq.4) txmsg=trim(hiscall)//' '//trim(mycall)//' RR73'
if(nfunc.eq.5) txmsg='TNX 73 GL'
call ft2_iwave(txmsg,ftx,99.0,iwave)
i1=ptt(nport,1,1,iptt)
ntxok=1
n=len(trim(txmsg))
write(*,1010) cdatetime(),0,0.0,nint(ftx),(txmsg(i:i),i=1,n)
write(12,1010) cdatetime(),0,0.0,nint(ftx),(txmsg(i:i),i=1,n)
1010 format(a17,' Tx',i4,f6.2,i6,2x,37a1)
if(nfunc.ge.1 .and. nfunc.le.4) ntxed=nfunc
if(nfunc.ge.1 .and. nfunc.le.5) ltx(nfunc)=.true.
if(nfunc.eq.2 .or. nfunc.eq.3) QSO_in_progress=.true.
return
end subroutine transmit

View File

@ -1,4 +1,4 @@
subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes) subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes,mycall,hiscall,nrx)
use crc use crc
use packjt77 use packjt77
@ -7,6 +7,7 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes)
character*37 decodes(100) character*37 decodes(100)
character*120 data_dir character*120 data_dir
character*17 cdatetime character*17 cdatetime
character*6 mycall,hiscall
complex c2(0:NMAX/16-1) !Complex waveform complex c2(0:NMAX/16-1) !Complex waveform
complex cb(0:NMAX/16-1) complex cb(0:NMAX/16-1)
complex cd(0:144*10-1) !Complex waveform complex cd(0:144*10-1) !Complex waveform
@ -66,7 +67,6 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes)
ndecodes=0 ndecodes=0
do icand=1,ncand do icand=1,ncand
f0=candidate(1,icand) f0=candidate(1,icand)
xsnr=1.0
if( f0.le.375.0 .or. f0.ge.(5000.0-375.0) ) cycle if( f0.le.375.0 .or. f0.ge.(5000.0-375.0) ) cycle
call ft2_downsample(iwave,f0,c2) ! downsample from 160s/Symbol to 10s/Symbol call ft2_downsample(iwave,f0,c2) ! downsample from 160s/Symbol to 10s/Symbol
! 750 samples/second here ! 750 samples/second here
@ -93,8 +93,6 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes)
cterm=cterm*cc0 cterm=cterm*cc0
endif endif
enddo enddo
! write(60,3001) if,is,abs(csync1)
!3001 format(2i6,f10.3)
if(abs(csync1).gt.sybest) then if(abs(csync1).gt.sybest) then
ibest=is ibest=is
sybest=abs(csync1) sybest=abs(csync1)
@ -103,8 +101,6 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes)
enddo enddo
enddo enddo
!dfbest=0.0
!ibest=187
a=0. a=0.
a(1)=-dfbest a(1)=-dfbest
call twkfreq1(c2,NMAX/16,fs,a,cb) call twkfreq1(c2,NMAX/16,fs,a,cb)
@ -189,18 +185,37 @@ subroutine ft2_decode(cdatetime,nfqso,iwave,ndecodes)
do i=1,ndecodes do i=1,ndecodes
if(decodes(i).eq.message) idupe=1 if(decodes(i).eq.message) idupe=1
enddo enddo
if(idupe.eq.1) goto 888 if(idupe.eq.1) exit
ndecodes=ndecodes+1 ndecodes=ndecodes+1
decodes(ndecodes)=message decodes(ndecodes)=message
xsnr=db(sybest*sybest) - 115.0 !### Rough estimate of S/N ###
nsnr=nint(xsnr) nsnr=nint(xsnr)
freq=f0+dfbest freq=f0+dfbest
write(*,1212) cdatetime,nsnr,ibest/750.0,nint(freq),message, & write(*,1000) cdatetime,nsnr,ibest/750.0,nint(freq),message, &
nseq,nharderror,nhardmin nseq,nharderror,nhardmin
1212 format(a17,i4,f6.2,i6,2x,a37,3i5) write(12,1000) cdatetime,nsnr,ibest/750.0,nint(freq),message, &
goto 888 nseq,nharderror,nhardmin
1000 format(a17,' Rx',i4,f6.2,i6,3x,a37,3i5)
!### Temporary: assume most recent decoded message conveys "hiscall".
i0=index(message,' ')
if(i0.ge.3 .and. i0.le.7) then
hiscall=message(i0+1:i0+6)
i1=index(hiscall,' ')
if(i1.gt.0) hiscall=hiscall(1:i1)
endif
nrx=-1
if(index(message,'CQ ').eq.1) nrx=1
if((index(message,trim(mycall)//' ').eq.1) .and. &
(index(message,' '//trim(hiscall)//' ').ge.4)) then
if(index(message,' 559 ').gt.8) nrx=2
if(index(message,' R 559 ').gt.8) nrx=3
if(index(message,' RR73 ').gt.8) nrx=4
endif
!###
exit
endif endif
enddo ! nseq enddo ! nseq
888 continue
enddo !candidate list enddo !candidate list
return return

View File

@ -59,7 +59,7 @@ SoundIn( void *inputBuffer, void *outputBuffer,
} }
if(ia >= data->nring) ia=0; //Wrap buffer pointer if necessary if(ia >= data->nring) ia=0; //Wrap buffer pointer if necessary
*data->iwrite = ia; //Save buffer pointer *data->iwrite = ia; //Save buffer pointer
iaa=ia; iaa=ia;
total_time += (double)framesPerBuffer/12000.0; total_time += (double)framesPerBuffer/12000.0;
// printf("iwrite: %d\n",*data->iwrite); // printf("iwrite: %d\n",*data->iwrite);
@ -165,7 +165,8 @@ int ft2audio_(int *ndevin, int *ndevout, int *npabuf, int *nright,
return(-1); return(-1);
} }
// printf("Opening device %d for input, %d for output...\n",ndevice_in,ndevice_out); // printf("Opening device %d for input, %d for output...\n",
// ndevice_in,ndevice_out);
inputParameters.device = ndevice_in; inputParameters.device = ndevice_in;
inputParameters.channelCount = 2; inputParameters.channelCount = 2;
@ -173,7 +174,8 @@ int ft2audio_(int *ndevin, int *ndevout, int *npabuf, int *nright,
inputParameters.suggestedLatency = 0.2; inputParameters.suggestedLatency = 0.2;
inputParameters.hostApiSpecificStreamInfo = NULL; inputParameters.hostApiSpecificStreamInfo = NULL;
// Test if this configuration actually works, so we do not run into an ugly assertion // Test if this configuration actually works, so we do not run into an
// ugly assertion
err_open_in = Pa_IsFormatSupported(&inputParameters, NULL, dSampleRate); err_open_in = Pa_IsFormatSupported(&inputParameters, NULL, dSampleRate);
if (err_open_in == 0) { if (err_open_in == 0) {
@ -189,16 +191,16 @@ int ft2audio_(int *ndevin, int *ndevout, int *npabuf, int *nright,
if(err_open_in) { // We should have no error here usually if(err_open_in) { // We should have no error here usually
printf("Error opening input audio stream:\n"); printf("Error opening input audio stream:\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_in), err_open_in); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_in),
err_open_in);
err = 1; err = 1;
} else { } else {
// printf("Successfully opened audio input.\n"); // printf("Successfully opened audio input.\n");
} }
} else { } else {
printf("Error opening input audio stream.\n"); printf("Error opening input audio stream.\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_in), err_open_in); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_in),
err_open_in);
err = 1; err = 1;
} }
@ -208,7 +210,8 @@ int ft2audio_(int *ndevin, int *ndevout, int *npabuf, int *nright,
outputParameters.suggestedLatency = 0.2; outputParameters.suggestedLatency = 0.2;
outputParameters.hostApiSpecificStreamInfo = NULL; outputParameters.hostApiSpecificStreamInfo = NULL;
// Test if this configuration actually works, so we do not run into an ugly assertion // Test if this configuration actually works, so we do not run into an
// ugly assertion.
err_open_out = Pa_IsFormatSupported(NULL, &outputParameters, dSampleRate); err_open_out = Pa_IsFormatSupported(NULL, &outputParameters, dSampleRate);
if (err_open_out == 0) { if (err_open_out == 0) {
@ -224,36 +227,34 @@ int ft2audio_(int *ndevin, int *ndevout, int *npabuf, int *nright,
if(err_open_out) { // We should have no error here usually if(err_open_out) { // We should have no error here usually
printf("Error opening output audio stream!\n"); printf("Error opening output audio stream!\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_out), err_open_out); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_out),
err_open_out);
err += 2; err += 2;
} else { } else {
// printf("Successfully opened audio output.\n"); // printf("Successfully opened audio output.\n");
} }
} else { } else {
printf("Error opening output audio stream.\n"); printf("Error opening output audio stream.\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_out), err_open_out); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_open_out),
err_open_out);
err += 2; err += 2;
} }
// if there was no error in opening both streams start them // if there was no error in opening both streams start them
if (err == 0) { if (err == 0) {
err_start_in = Pa_StartStream(instream); //Start input stream err_start_in = Pa_StartStream(instream); //Start input stream
if(err_start_in) { if(err_start_in) {
printf("Error starting input audio stream!\n"); printf("Error starting input audio stream!\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_start_in), err_start_in); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_start_in),
err_start_in);
err += 4; err += 4;
} }
err_start_out = Pa_StartStream(outstream); //Start output stream err_start_out = Pa_StartStream(outstream); //Start output stream
if(err_start_out) { if(err_start_out) {
printf("Error starting output audio stream!\n"); printf("Error starting output audio stream!\n");
printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_start_out), err_start_out); printf("\tErrortext: %s\n\tNumber: %d\n",Pa_GetErrorText(err_start_out),
err_start_out);
err += 8; err += 8;
} }
} }
@ -322,7 +323,8 @@ int padevsub_(int *idevin, int *idevout)
// if(i == Pa_GetDefaultOutputDevice()) ndefout = i; // if(i == Pa_GetDefaultOutputDevice()) ndefout = i;
nchin[i]=pdi->maxInputChannels; nchin[i]=pdi->maxInputChannels;
nchout[i]=pdi->maxOutputChannels; nchout[i]=pdi->maxOutputChannels;
printf(" %2d %2d %2d %s\n",i,nchin[i],nchout[i],pdi->name); printf(" %2d %2d %2d %s\n",i,nchin[i],nchout[i],
pdi->name);
} }
printf("\nUser requested devices: Input = %2d Output = %2d\n", printf("\nUser requested devices: Input = %2d Output = %2d\n",

View File

@ -15,6 +15,10 @@ integer nTransmitting !Actually transmitting?
integer nTxOK !OK to transmit? integer nTxOK !OK to transmit?
integer nport !COM port for PTT integer nport !COM port for PTT
logical tx_once !Transmit one message, then exit logical tx_once !Transmit one message, then exit
logical ltx !True if msg i has been transmitted
logical lrx !True if msg i has been received
logical autoseq
logical QSO_in_progress
integer*2 y1 !Ring buffer for audio channel 0 integer*2 y1 !Ring buffer for audio channel 0
integer*2 y2 !Ring buffer for audio channel 1 integer*2 y2 !Ring buffer for audio channel 1
integer*2 iwave !Data for Tx audio integer*2 iwave !Data for Tx audio
@ -26,5 +30,5 @@ character*3 exch
character*37 txmsg character*37 txmsg
common/gcom1/snrdb,ndevin,ndevout,iwrite,itx,ngo,nTransmitting,nTxOK,nport, & common/gcom1/snrdb,ndevin,ndevout,iwrite,itx,ngo,nTransmitting,nTxOK,nport, &
tx_once, y1(NRING),y2(NRING),iwave(NTZ),mycall,hiscall, & ntxed,tx_once, y1(NRING),y2(NRING),iwave(NTZ),ltx(5),lrx(5),autoseq, &
hiscall_next,mygrid,exch,txmsg QSO_in_progress,mycall,hiscall,hiscall_next,mygrid,exch,txmsg