Add LF/MF noise blanker capability for FST240 and FST240W.

This commit is contained in:
Joe Taylor 2020-07-14 11:27:41 -04:00
parent 4cb902a4cc
commit cbeb81b499
6 changed files with 599 additions and 491 deletions

View File

@ -396,6 +396,7 @@ set (wsjt_FSRCS
lib/badmsg.f90 lib/badmsg.f90
lib/ft8/baseline.f90 lib/ft8/baseline.f90
lib/ft4/ft4_baseline.f90 lib/ft4/ft4_baseline.f90
lib/blanker.f90
lib/bpdecode40.f90 lib/bpdecode40.f90
lib/bpdecode128_90.f90 lib/bpdecode128_90.f90
lib/ft8/bpdecode174_91.f90 lib/ft8/bpdecode174_91.f90

52
lib/blanker.f90 Normal file
View File

@ -0,0 +1,52 @@
subroutine blanker(iwave,nz,dwell_time,fblank,npct)
integer*2 iwave(nz)
integer hist(0:32768)
real dwell_time !Blanking dwell time (s)
real fblank !Fraction of points to be blanked
data ncall/0/,thresh/0.0/,fblanked/0.0/
save ncall,thresh,fblanked
ncall=ncall+1
ndropmax=nint(1.0 + dwell_time*12000.0)
hist=0
do i=1,nz
n=abs(iwave(i))
hist(n)=hist(n)+1
enddo
n=0
do i=32768,0,-1
n=n+hist(i)
if(n.ge.nint(nz*fblank/ndropmax)) exit
enddo
thresh=thresh + 0.01*(i-thresh)
if(ncall.eq.1) thresh=i
nthresh=nint(thresh)
ndrop=0
ndropped=0
do i=1,nz
i0=iwave(i)
if(ndrop.gt.0) then
iwave(i)=0
ndropped=ndropped+1
ndrop=ndrop-1
cycle
endif
! Start to apply blanking
if(abs(iwave(i)).gt.nthresh) then
iwave(i)=0
ndropped=ndropped+1
ndrop=ndropmax
endif
enddo
fblanked=fblanked + 0.1*(float(ndropped)/nz - fblanked)
if(ncall.eq.1) fblanked=float(ndropped)/nz
npct=nint(100.0*fblanked)
! if(mod(ncall,4).eq.0) write(*,3001) thresh,dwell_time,fblank,fblanked,npct
!3001 format(f8.1,f8.4,f6.2,f7.3,i6)
return
end subroutine blanker

View File

@ -78,6 +78,8 @@ contains
data first/.true./ data first/.true./
save first,apbits,nappasses,naptypes,mycall0,hiscall0 save first,apbits,nappasses,naptypes,mycall0,hiscall0
! call blanker(iwave,ntrperiod*12000,0.0,0.2)
this%callback => callback this%callback => callback
dxcall13=hiscall ! initialize for use in packjt77 dxcall13=hiscall ! initialize for use in packjt77
@ -788,7 +790,7 @@ contains
iploc=ia+im(1)-1 !Index of CCF peak iploc=ia+im(1)-1 !Index of CCF peak
pval=s2(iploc) !Peak value pval=s2(iploc) !Peak value
if(pval.lt.minsync) exit if(pval.lt.minsync) exit
if(s2(iploc).gt.thresh) then !Is this a possible candidate? if(s2(iploc).gt.minsync) then !Is this a possible candidate?
do i=-3,+3 !Remove 0.9 of a model CCF at do i=-3,+3 !Remove 0.9 of a model CCF at
k=iploc+2*hmod*i !this frequency from s2() k=iploc+2*hmod*i !this frequency from s2()
if(k.ge.ia .and. k.le.ib) then if(k.ge.ia .and. k.le.ib) then
@ -803,5 +805,5 @@ contains
return return
end subroutine get_candidates_fst240 end subroutine get_candidates_fst240
end module fst240_decode end module fst240_decode

View File

@ -1,5 +1,5 @@
subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, & subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
nminw,pxdb,s,df3,ihsym,npts8,pxdbmax) nminw,pxdb,s,df3,ihsym,npts8,pxdbmax,bblank,npct)
! Input: ! Input:
! k pointer to the most recent new data ! k pointer to the most recent new data
@ -7,8 +7,6 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
! nsps samples per symbol, at 12000 Hz ! nsps samples per symbol, at 12000 Hz
! bLowSidelobes true to use windowed FFTs ! bLowSidelobes true to use windowed FFTs
! ndiskdat 0/1 to indicate if data from disk ! ndiskdat 0/1 to indicate if data from disk
! nb 0/1 status of noise blanker (off/on)
! nbslider NB setting, 0-100
! Output: ! Output:
! pxdb raw power (0-90 dB) ! pxdb raw power (0-90 dB)
@ -31,7 +29,7 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
real*4 tmp(NSMAX) real*4 tmp(NSMAX)
complex cx(0:MAXFFT3/2) complex cx(0:MAXFFT3/2)
integer nch(7) integer nch(7)
logical*1 bLowSidelobes logical*1 bLowSidelobes,bblank
common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456) common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456)
data k0/99999999/,nfft3z/0/ data k0/99999999/,nfft3z/0/
@ -65,6 +63,12 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, &
gain=10.0**(0.1*ingain) gain=10.0**(0.1*ingain)
sq=0. sq=0.
pxmax=0.; pxmax=0.;
dwell_time=0.0001
fblank=0.15
if(k.gt.k0 .and. bblank) call blanker(shared_data%id2(k0+1:k), &
k-k0,dwell_time,fblank,npct)
do i=k0+1,k do i=k0+1,k
x1=shared_data%id2(i) x1=shared_data%id2(i)
if (abs(x1).gt.pxmax) pxmax = abs(x1); if (abs(x1).gt.pxmax) pxmax = abs(x1);

View File

@ -91,7 +91,7 @@ extern "C" {
//----------------------------------------------------- C and Fortran routines //----------------------------------------------------- C and Fortran routines
void symspec_(struct dec_data *, int* k, double* trperiod, int* nsps, int* ingain, void symspec_(struct dec_data *, int* k, double* trperiod, int* nsps, int* ingain,
bool* bLowSidelobes, int* minw, float* px, float s[], float* df3, bool* bLowSidelobes, int* minw, float* px, float s[], float* df3,
int* nhsym, int* npts8, float *m_pxmax); int* nhsym, int* npts8, float *m_pxmax, bool *bblank, int* npct);
void hspec_(short int d2[], int* k, int* nutc0, int* ntrperiod, int* nrxfreq, int* ntol, void hspec_(short int d2[], int* k, int* nutc0, int* ntrperiod, int* nrxfreq, int* ntol,
bool* bmsk144, bool* btrain, double const pcoeffs[], int* ingain, bool* bmsk144, bool* btrain, double const pcoeffs[], int* ingain,
@ -1132,6 +1132,8 @@ void MainWindow::writeSettings()
m_settings->setValue ("FT8AP", ui->actionEnable_AP_FT8->isChecked ()); m_settings->setValue ("FT8AP", ui->actionEnable_AP_FT8->isChecked ());
m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ()); m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ());
m_settings->setValue("SplitterState",ui->splitter->saveState()); m_settings->setValue("SplitterState",ui->splitter->saveState());
m_settings->setValue("Blanker",ui->cbNB->isChecked());
{ {
QList<QVariant> coeffs; // suitable for QSettings QList<QVariant> coeffs; // suitable for QSettings
for (auto const& coeff : m_phaseEqCoefficients) for (auto const& coeff : m_phaseEqCoefficients)
@ -1231,6 +1233,7 @@ void MainWindow::readSettings()
ui->actionEnable_AP_FT8->setChecked (m_settings->value ("FT8AP", false).toBool()); ui->actionEnable_AP_FT8->setChecked (m_settings->value ("FT8AP", false).toBool());
ui->actionEnable_AP_JT65->setChecked (m_settings->value ("JT65AP", false).toBool()); ui->actionEnable_AP_JT65->setChecked (m_settings->value ("JT65AP", false).toBool());
ui->splitter->restoreState(m_settings->value("SplitterState").toByteArray()); ui->splitter->restoreState(m_settings->value("SplitterState").toByteArray());
ui->cbNB->setChecked(m_settings->value("Blanker",false).toBool());
{ {
auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients" auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients"
, QList<QVariant> {0., 0., 0., 0., 0.}).toList (); , QList<QVariant> {0., 0., 0., 0., 0.}).toList ();
@ -1389,8 +1392,13 @@ void MainWindow::dataSink(qint64 frames)
if(m_bFastMode) nsps=6912; if(m_bFastMode) nsps=6912;
int nsmo=m_wideGraph->smoothYellow()-1; int nsmo=m_wideGraph->smoothYellow()-1;
bool bLowSidelobes=m_config.lowSidelobes(); bool bLowSidelobes=m_config.lowSidelobes();
bool bblank=ui->cbNB->isChecked() and m_mode.startsWith("FST240");
int npct=0;
symspec_(&dec_data,&k,&m_TRperiod,&nsps,&m_inGain,&bLowSidelobes,&nsmo,&m_px,s, symspec_(&dec_data,&k,&m_TRperiod,&nsps,&m_inGain,&bLowSidelobes,&nsmo,&m_px,s,
&m_df3,&m_ihsym,&m_npts8,&m_pxmax); &m_df3,&m_ihsym,&m_npts8,&m_pxmax,&bblank,&npct);
QString t=" ";
if(bblank) t=QString::number(npct);
ui->labNpct->setText(t);
if(m_mode=="WSPR" or m_mode=="FST240W") wspr_downsample_(dec_data.d2,&k); if(m_mode=="WSPR" or m_mode=="FST240W") wspr_downsample_(dec_data.d2,&k);
if(m_ihsym <=0) return; if(m_ihsym <=0) return;
if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer
@ -4079,7 +4087,6 @@ void MainWindow::guiUpdate()
//Once per second: //Once per second:
if(nsec != m_sec0) { if(nsec != m_sec0) {
// qDebug() << "onesec" << ui->RoundRobin->currentText();
m_currentBand=m_config.bands()->find(m_freqNominal); m_currentBand=m_config.bands()->find(m_freqNominal);
if( SpecOp::HOUND == m_config.special_op_id() ) { if( SpecOp::HOUND == m_config.special_op_id() ) {
qint32 tHound=QDateTime::currentMSecsSinceEpoch()/1000 - m_tAutoOn; qint32 tHound=QDateTime::currentMSecsSinceEpoch()/1000 - m_tAutoOn;
@ -5806,6 +5813,10 @@ void MainWindow::displayWidgets(qint64 n)
if(m_mode=="MSK144") b=SpecOp::EU_VHF==m_config.special_op_id(); if(m_mode=="MSK144") b=SpecOp::EU_VHF==m_config.special_op_id();
ui->sbSerialNumber->setVisible(b); ui->sbSerialNumber->setVisible(b);
m_lastCallsign.clear (); // ensures Tx5 is updated for new modes m_lastCallsign.clear (); // ensures Tx5 is updated for new modes
b=m_mode.startsWith("FST240");
ui->labNpct->setVisible(b);
ui->labNB->setVisible(b);
ui->cbNB->setVisible(b);
genStdMsgs (m_rpt, true); genStdMsgs (m_rpt, true);
} }

File diff suppressed because it is too large Load Diff