From cbeb81b49955500c1a4160ad1c351fe08c90376f Mon Sep 17 00:00:00 2001 From: Joe Taylor Date: Tue, 14 Jul 2020 11:27:41 -0400 Subject: [PATCH] Add LF/MF noise blanker capability for FST240 and FST240W. --- CMakeLists.txt | 1 + lib/blanker.f90 | 52 +++ lib/fst240_decode.f90 | 6 +- lib/symspec.f90 | 12 +- widgets/mainwindow.cpp | 17 +- widgets/mainwindow.ui | 1002 +++++++++++++++++++++------------------- 6 files changed, 599 insertions(+), 491 deletions(-) create mode 100644 lib/blanker.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index 15cf9aed0..80199358d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -396,6 +396,7 @@ set (wsjt_FSRCS lib/badmsg.f90 lib/ft8/baseline.f90 lib/ft4/ft4_baseline.f90 + lib/blanker.f90 lib/bpdecode40.f90 lib/bpdecode128_90.f90 lib/ft8/bpdecode174_91.f90 diff --git a/lib/blanker.f90 b/lib/blanker.f90 new file mode 100644 index 000000000..a5c334e3f --- /dev/null +++ b/lib/blanker.f90 @@ -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 diff --git a/lib/fst240_decode.f90 b/lib/fst240_decode.f90 index b57cc401d..0fffd9f74 100644 --- a/lib/fst240_decode.f90 +++ b/lib/fst240_decode.f90 @@ -78,6 +78,8 @@ contains data first/.true./ save first,apbits,nappasses,naptypes,mycall0,hiscall0 +! call blanker(iwave,ntrperiod*12000,0.0,0.2) + this%callback => callback dxcall13=hiscall ! initialize for use in packjt77 @@ -788,7 +790,7 @@ contains iploc=ia+im(1)-1 !Index of CCF peak pval=s2(iploc) !Peak value 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 k=iploc+2*hmod*i !this frequency from s2() if(k.ge.ia .and. k.le.ib) then @@ -803,5 +805,5 @@ contains return end subroutine get_candidates_fst240 - + end module fst240_decode diff --git a/lib/symspec.f90 b/lib/symspec.f90 index f97757778..5bd0fd902 100644 --- a/lib/symspec.f90 +++ b/lib/symspec.f90 @@ -1,5 +1,5 @@ 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: ! 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 ! bLowSidelobes true to use windowed FFTs ! ndiskdat 0/1 to indicate if data from disk -! nb 0/1 status of noise blanker (off/on) -! nbslider NB setting, 0-100 ! Output: ! pxdb raw power (0-90 dB) @@ -31,7 +29,7 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, & real*4 tmp(NSMAX) complex cx(0:MAXFFT3/2) integer nch(7) - logical*1 bLowSidelobes + logical*1 bLowSidelobes,bblank common/spectra/syellow(NSMAX),ref(0:3456),filter(0:3456) data k0/99999999/,nfft3z/0/ @@ -65,6 +63,12 @@ subroutine symspec(shared_data,k,TRperiod,nsps,ingain,bLowSidelobes, & gain=10.0**(0.1*ingain) sq=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 x1=shared_data%id2(i) if (abs(x1).gt.pxmax) pxmax = abs(x1); diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 9c5e9c6bb..7f6948ea3 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -91,7 +91,7 @@ extern "C" { //----------------------------------------------------- C and Fortran routines void symspec_(struct dec_data *, int* k, double* trperiod, int* nsps, int* ingain, 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, 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 ("JT65AP", ui->actionEnable_AP_JT65->isChecked ()); m_settings->setValue("SplitterState",ui->splitter->saveState()); + m_settings->setValue("Blanker",ui->cbNB->isChecked()); + { QList coeffs; // suitable for QSettings 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_JT65->setChecked (m_settings->value ("JT65AP", false).toBool()); ui->splitter->restoreState(m_settings->value("SplitterState").toByteArray()); + ui->cbNB->setChecked(m_settings->value("Blanker",false).toBool()); { auto const& coeffs = m_settings->value ("PhaseEqualizationCoefficients" , QList {0., 0., 0., 0., 0.}).toList (); @@ -1389,8 +1392,13 @@ void MainWindow::dataSink(qint64 frames) if(m_bFastMode) nsps=6912; int nsmo=m_wideGraph->smoothYellow()-1; 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, - &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_ihsym <=0) return; if(ui) ui->signal_meter_widget->setValue(m_px,m_pxmax); // Update thermometer @@ -4079,7 +4087,6 @@ void MainWindow::guiUpdate() //Once per second: if(nsec != m_sec0) { -// qDebug() << "onesec" << ui->RoundRobin->currentText(); m_currentBand=m_config.bands()->find(m_freqNominal); if( SpecOp::HOUND == m_config.special_op_id() ) { 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(); ui->sbSerialNumber->setVisible(b); 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); } diff --git a/widgets/mainwindow.ui b/widgets/mainwindow.ui index 91d8e95ba..ef5a882b1 100644 --- a/widgets/mainwindow.ui +++ b/widgets/mainwindow.ui @@ -554,488 +554,6 @@ - - - - - 0 - 0 - - - - USB dial frequency - - - QLabel { - font-family: MS Shell Dlg 2; - font-size: 16pt; - color : yellow; - background-color : black; -} -QLabel[oob="true"] { - background-color: red; -} - - - - 14.078 000 - - - Qt::AlignCenter - - - 5 - - - - - - - - 0 - 0 - - - - - 100 - 16777215 - - - - <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> - - - Rx Signal - - - 30dB recommended when only noise present -Green when good -Red when clipping may occur -Yellow when too low - - - QFrame::Panel - - - QFrame::Sunken - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 159 - 175 - 213 - - - - - - - 159 - 175 - 213 - - - - - - - - true - - - DX Call - - - Qt::AlignCenter - - - 5 - - - 2 - - - dxCallEntry - - - - - - - - 0 - 0 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 252 - 252 - 252 - - - - - - - 159 - 175 - 213 - - - - - - - - - 159 - 175 - 213 - - - - - - - 159 - 175 - 213 - - - - - - - - true - - - DX Grid - - - Qt::AlignCenter - - - 5 - - - 2 - - - dxGridEntry - - - - - - - Callsign of station to be worked - - - - - - Qt::AlignCenter - - - - - - - Search for callsign in database - - - &Lookup - - - - - - - Locator of station to be worked - - - - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - true - - - Az: 251 16553 km - - - Qt::AlignCenter - - - 4 - - - - - - - Add callsign and locator to database - - - Add - - - - - - - - - - Pwr - - - - - - - false - - - <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> - - - If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. - - - QPushButton { - font-family: helvetica; - font-size: 9pt; - font-weight: bold; - background-color: white; - color: black; - border-style: solid; - border-width:1px; - border-radius:10px; - border-color: gray; - max-width:20px; - max-height:20px; - min-width:20px; - min-height:20px; -} -QPushButton[state="error"] { - background-color: red; -} -QPushButton[state="warning"] { - background-color: orange; -} -QPushButton[state="ok"] { - background-color: #00ff00; -} - - - ? - - - - - - - Adjust Tx audio level - - - 450 - - - 0 - - - Qt::Vertical - - - true - - - true - - - QSlider::TicksBelow - - - 50 - - - - - - - <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> - - - Frequency entry - - - Select operating band or enter frequency in MHz or enter kHz increment followed by k. - - - true - - - QComboBox::NoInsert - - - QComboBox::AdjustToMinimumContentsLength - - - - - - - - 0 - 0 - - - - QLabel { - font-family: MS Shell Dlg 2; - font-size: 16pt; - background-color : black; - color : yellow; -} - - - QFrame::StyledPanel - - - QFrame::Sunken - - - 2 - - - 0 - - - <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - - - Qt::AlignCenter - - - 5 - - - @@ -2808,6 +2326,526 @@ list. The list can be maintained in Settings (F2). + + + + + 0 + 0 + + + + QLabel { + font-family: MS Shell Dlg 2; + font-size: 16pt; + background-color : black; + color : yellow; +} + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 2 + + + 0 + + + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> + + + Qt::AlignCenter + + + 5 + + + + + + + Pwr + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 159 + 175 + 213 + + + + + + + 159 + 175 + 213 + + + + + + + + true + + + DX Call + + + Qt::AlignCenter + + + 5 + + + 2 + + + dxCallEntry + + + + + + + + 0 + 0 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 252 + 252 + 252 + + + + + + + 159 + 175 + 213 + + + + + + + + + 159 + 175 + 213 + + + + + + + 159 + 175 + 213 + + + + + + + + true + + + DX Grid + + + Qt::AlignCenter + + + 5 + + + 2 + + + dxGridEntry + + + + + + + Callsign of station to be worked + + + + + + Qt::AlignCenter + + + + + + + Search for callsign in database + + + &Lookup + + + + + + + Locator of station to be worked + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + true + + + Az: 251 16553 km + + + Qt::AlignCenter + + + 4 + + + + + + + Add callsign and locator to database + + + Add + + + + + + + + + + false + + + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> + + + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. + + + QPushButton { + font-family: helvetica; + font-size: 9pt; + font-weight: bold; + background-color: white; + color: black; + border-style: solid; + border-width:1px; + border-radius:10px; + border-color: gray; + max-width:20px; + max-height:20px; + min-width:20px; + min-height:20px; +} +QPushButton[state="error"] { + background-color: red; +} +QPushButton[state="warning"] { + background-color: orange; +} +QPushButton[state="ok"] { + background-color: #00ff00; +} + + + ? + + + + + + + Adjust Tx audio level + + + 450 + + + 0 + + + Qt::Vertical + + + true + + + true + + + QSlider::TicksBelow + + + 50 + + + + + + + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> + + + Frequency entry + + + Select operating band or enter frequency in MHz or enter kHz increment followed by k. + + + true + + + QComboBox::NoInsert + + + QComboBox::AdjustToMinimumContentsLength + + + + + + + + 0 + 0 + + + + USB dial frequency + + + QLabel { + font-family: MS Shell Dlg 2; + font-size: 16pt; + color : yellow; + background-color : black; +} +QLabel[oob="true"] { + background-color: red; +} + + + + 14.078 000 + + + Qt::AlignCenter + + + 5 + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> + + + Rx Signal + + + 30dB recommended when only noise present +Green when good +Red when clipping may occur +Yellow when too low + + + QFrame::Panel + + + QFrame::Sunken + + + + + + + + + NB + + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + +