Basic functionality of Echo spectrum is in place.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5557 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2015-06-08 19:42:20 +00:00
parent 477d45a72c
commit be5eb31884
10 changed files with 215 additions and 30 deletions

View File

@ -262,6 +262,7 @@ set (wsjt_FSRCS
lib/astro.f90 lib/astro.f90
lib/astrosub.f90 lib/astrosub.f90
lib/astro0.f90 lib/astro0.f90
lib/avecho.f90
lib/avg4.f90 lib/avg4.f90
lib/azdist.f90 lib/azdist.f90
lib/baddata.f90 lib/baddata.f90

View File

@ -44,6 +44,13 @@ extern "C" {
extern struct { extern struct {
float syellow[NSMAX]; float syellow[NSMAX];
} jt9w_; } jt9w_;
extern struct {
int nclearave;
int nsum;
float blue[2000];
float red[2000];
} echocom_;
} }
#endif // COMMONS_H #endif // COMMONS_H

View File

@ -1,4 +1,4 @@
//#include "commons.h" #include "commons.h"
#include <QSettings> #include <QSettings>
#include "echoplot.h" #include "echoplot.h"
#include "echograph.h" #include "echograph.h"
@ -27,6 +27,7 @@ EchoGraph::EchoGraph(QSettings * settings, QWidget *parent) :
ui->zeroSlider->setValue(ui->echoPlot->getPlotZero()); ui->zeroSlider->setValue(ui->echoPlot->getPlotZero());
ui->gainSlider->setValue(ui->echoPlot->getPlotGain()); ui->gainSlider->setValue(ui->echoPlot->getPlotGain());
ui->smoothSpinBox->setValue(m_settings->value("Smooth",0).toInt()); ui->smoothSpinBox->setValue(m_settings->value("Smooth",0).toInt());
ui->binsPerPixelSpinBox->setValue(m_settings->value("EchoBPP",0).toInt());
ui->echoPlot->m_blue=m_settings->value("BlueCurve",false).toBool(); ui->echoPlot->m_blue=m_settings->value("BlueCurve",false).toBool();
ui->cbBlue->setChecked(ui->echoPlot->m_blue); ui->cbBlue->setChecked(ui->echoPlot->m_blue);
m_settings->endGroup(); m_settings->endGroup();
@ -52,6 +53,7 @@ void EchoGraph::saveSettings()
m_settings->setValue("PlotZero",ui->echoPlot->m_plotZero); m_settings->setValue("PlotZero",ui->echoPlot->m_plotZero);
m_settings->setValue("PlotGain",ui->echoPlot->m_plotGain); m_settings->setValue("PlotGain",ui->echoPlot->m_plotGain);
m_settings->setValue("Smooth",ui->echoPlot->m_smooth); m_settings->setValue("Smooth",ui->echoPlot->m_smooth);
m_settings->setValue("EchoBPP",ui->echoPlot->m_binsPerPixel);
m_settings->setValue("BlueCurve",ui->echoPlot->m_blue); m_settings->setValue("BlueCurve",ui->echoPlot->m_blue);
m_settings->endGroup(); m_settings->endGroup();
} }
@ -84,3 +86,10 @@ void EchoGraph::on_zeroSlider_valueChanged(int value)
ui->echoPlot->setPlotZero(value); ui->echoPlot->setPlotZero(value);
ui->echoPlot->draw(); ui->echoPlot->draw();
} }
void EchoGraph::on_binsPerPixelSpinBox_valueChanged(int n)
{
ui->echoPlot->m_binsPerPixel=n;
ui->echoPlot->DrawOverlay();
ui->echoPlot->draw();
}

View File

@ -27,6 +27,7 @@ private slots:
void on_cbBlue_toggled(bool checked); void on_cbBlue_toggled(bool checked);
void on_gainSlider_valueChanged(int value); void on_gainSlider_valueChanged(int value);
void on_zeroSlider_valueChanged(int value); void on_zeroSlider_valueChanged(int value);
void on_binsPerPixelSpinBox_valueChanged(int n);
private: private:
QSettings * m_settings; QSettings * m_settings;

View File

@ -89,6 +89,25 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QSpinBox" name="binsPerPixelSpinBox">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="prefix">
<string>Bins/Pixel </string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
@ -161,15 +180,17 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Smooth</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QSpinBox" name="smoothSpinBox"> <widget class="QSpinBox" name="smoothSpinBox">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="prefix">
<string>Smooth </string>
</property>
<property name="maximum"> <property name="maximum">
<number>20</number> <number>20</number>
</property> </property>

View File

@ -1,5 +1,5 @@
#include "echoplot.h" #include "echoplot.h"
//#include "commons.h" #include "commons.h"
#include <math.h> #include <math.h>
#include <QDebug> #include <QDebug>
#include "moc_echoplot.cpp" #include "moc_echoplot.cpp"
@ -18,7 +18,7 @@ EPlotter::EPlotter(QWidget *parent) : //EPlotter Constructor
setAttribute(Qt::WA_NoSystemBackground, true); setAttribute(Qt::WA_NoSystemBackground, true);
m_StartFreq = -200; m_StartFreq = -200;
m_fftBinWidth=48000.0/131072.0; m_fftBinWidth=12000.0/32768.0;
m_fSpan=1000.0; m_fSpan=1000.0;
m_hdivs = HORZ_DIVS; m_hdivs = HORZ_DIVS;
m_Running = false; m_Running = false;
@ -91,16 +91,16 @@ void EPlotter::draw() //draw()
QPainter painter2D(&m_2DPixmap); QPainter painter2D(&m_2DPixmap);
QRect tmp(0,0,m_w,m_h2); QRect tmp(0,0,m_w,m_h2);
painter2D.fillRect(tmp,Qt::black); painter2D.fillRect(tmp,Qt::black);
/*
if(datcom_.nclearave==0) { if(echocom_.nclearave==0) {
QPoint LineBuf[MAX_SCREENSIZE]; QPoint LineBuf[MAX_SCREENSIZE];
QPen penBlue(QColor(0,255,255),1); QPen penBlue(QColor(0,255,255),1);
QPen penRed(Qt::red,1); QPen penRed(Qt::red,1);
j=0; j=0;
int i0=1000 + int(m_StartFreq/m_fftBinWidth); int i0=1000 + int(m_StartFreq/m_fftBinWidth);
for(i=0; i<2000; i++) { for(i=0; i<2000; i++) {
blue[i]=datcom_.blue[i]; blue[i]=echocom_.blue[i];
red[i]=datcom_.red[i]; red[i]=echocom_.red[i];
} }
if(m_smooth>0) { if(m_smooth>0) {
for(i=0; i<m_smooth; i++) { for(i=0; i<m_smooth; i++) {
@ -132,7 +132,7 @@ void EPlotter::draw() //draw()
} }
painter2D.drawPolyline(LineBuf,j); painter2D.drawPolyline(LineBuf,j);
} }
*/
update(); //trigger a new paintEvent update(); //trigger a new paintEvent
} }

View File

@ -31,9 +31,10 @@ public:
qint32 m_plotZero; qint32 m_plotZero;
qint32 m_plotGain; qint32 m_plotGain;
qint32 m_smooth; qint32 m_smooth;
qint32 m_binsPerPixel;
bool m_blue; bool m_blue;
void draw(); //Update the waterfall void draw(); //Update the Echo plot
void SetRunningState(bool running); void SetRunningState(bool running);
void setPlotZero(int plotZero); void setPlotZero(int plotZero);
int getPlotZero(); int getPlotZero();

119
lib/avecho.f90 Normal file
View File

@ -0,0 +1,119 @@
subroutine avecho(id2,ndop,nfrit,nqual,f1,rms0,sigdb,snr,dfreq,width)
integer TXLENGTH
parameter (TXLENGTH=27648) !27*1024
parameter (NFFT=32768,NH=NFFT/2)
integer*2 id2(34560) !Buffer for Rx data
real sa(2000) !Avg spectrum relative to initial Doppler echo freq
real sb(2000) !Avg spectrum with Dither and changing Doppler removed
integer nsum !Number of integrations
real dop0 !Doppler shift for initial integration (Hz)
real doppler !Doppler shift for current integration (Hz)
real s(8192)
real x(NFFT)
integer ipkv(1)
complex c(0:NH)
equivalence (x,c),(ipk,ipkv)
common/echocom/nclearave,nsum,blue(2000),red(2000)
save dop0,sa,sb
dop=ndop
doppler=dop
sq=0.
do i=1,TXLENGTH
x(i)=id2(i)
sq=sq + x(i)*x(i)
enddo
rms0=sqrt(sq/TXLENGTH)
if(nclearave.ne.0) nsum=0
nclearave=0
if(nsum.eq.0) then
dop0=doppler !Remember the initial Doppler
sa=0. !Clear the average arrays
sb=0.
endif
x(TXLENGTH+1:)=0.
x=x/TXLENGTH
call four2a(x,NFFT,1,-1,0)
df=12000.0/NFFT
do i=1,8192 !Get spectrum 0 - 3 kHz
s(i)=real(c(i))**2 + aimag(c(i))**2
enddo
fnominal=1500.0 !Nominal audio frequency w/o doppler or dither
ia=nint((fnominal+dop0-nfrit)/df)
ib=nint((f1+doppler-nfrit)/df)
if(ia.lt.600 .or. ib.lt.600) go to 900
if(ia.gt.7590 .or. ib.gt.7590) go to 900
nsum=nsum+1
do i=1,2000
sa(i)=sa(i) + s(ia+i-1000) !Center at initial doppler freq
sb(i)=sb(i) + s(ib+i-1000) !Center at expected echo freq
enddo
call pctile(sb,200,50,r0)
call pctile(sb(1800),200,50,r1)
sum=0.
sq=0.
do i=1,2000
y=r0 + (r1-r0)*(i-100.0)/1800.0
blue(i)=sa(i)/y
red(i)=sb(i)/y
if(i.le.500 .or. i.ge.1501) then
sum=sum+red(i)
sq=sq + (red(i)-1.0)**2
endif
enddo
ave=sum/1000.0
rms=sqrt(sq/1000.0)
redmax=maxval(red)
ipkv=maxloc(red)
fac=10.0/max(redmax,10.0)
dfreq=(ipk-1000)*df
snr=(redmax-ave)/rms
sigdb=-99.0
if(ave.gt.0.0) sigdb=10.0*log10(redmax/ave - 1.0) - 35.7
nqual=0
if(nsum.ge.2 .and. nsum.lt.4) nqual=(snr-4)/5
if(nsum.ge.4 .and. nsum.lt.8) nqual=(snr-3)/4
if(nsum.ge.8 .and. nsum.lt.12) nqual=(snr-3)/3
if(nsum.ge.12) nqual=(snr-2.5)/2.5
if(nqual.lt.0) nqual=0
if(nqual.gt.10) nqual=10
! Scale for plotting
blue=fac*blue
red=fac*red
sum=0.
do i=ipk,ipk+300
if(red(i).lt.1.0) exit
sum=sum+(red(i)-1.0)
enddo
do i=ipk-1,ipk-300,-1
if(red(i).lt.1.0) exit
sum=sum+(red(i)-1.0)
enddo
bins=sum/(red(ipk)-1.0)
width=df*bins
nsmo=max(0.0,0.25*bins)
do i=1,nsmo
call smo121(red,2000)
call smo121(blue,2000)
enddo
900 continue
write(*,3001) ia,ib,nclearave,nsum,width,snr,nqual
3001 format('avecho:',4i6,2f7.1,i5)
return
end subroutine avecho

View File

@ -437,6 +437,10 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
m_bHaveTransmitted=false; m_bHaveTransmitted=false;
m_bEchoTxOK=false; m_bEchoTxOK=false;
m_bTransmittedEcho=false; m_bTransmittedEcho=false;
m_nDop=0;
m_nDop00=0;
m_nDopr=0;
m_nclearave=1;
signalMeter = new SignalMeter(ui->meterFrame); signalMeter = new SignalMeter(ui->meterFrame);
signalMeter->resize(50, 160); signalMeter->resize(50, 160);
@ -820,8 +824,20 @@ void MainWindow::dataSink(qint64 frames)
if(ihsym == m_hsymStop) { if(ihsym == m_hsymStop) {
if(m_mode=="Echo") { if(m_mode=="Echo") {
qDebug() << "call plotSpec()" << m_s6; float snr=0;
int nfrit=0;
int nqual=0;
float f1=1500.0;
float rms=0.0;
float sigdb=0.0;
float dfreq=0.0;
float width=0.0;
echocom_.nclearave=m_nclearave;
avecho_(&jt9com_.d2[0],&m_nDop00,&nfrit,&nqual,&f1,&rms,&sigdb,
&snr,&dfreq,&width);
qDebug() << "A" << echocom_.nclearave << echocom_.nsum << rms << sigdb;
if(m_echoGraph->isVisible()) m_echoGraph->plotSpec(); if(m_echoGraph->isVisible()) m_echoGraph->plotSpec();
m_nclearave=0;
return; return;
} }
if( m_dialFreqRxWSPR==0) m_dialFreqRxWSPR=m_dialFreq; if( m_dialFreqRxWSPR==0) m_dialFreqRxWSPR=m_dialFreq;
@ -2145,9 +2161,8 @@ void MainWindow::guiUpdate()
QDateTime t = QDateTime::currentDateTimeUtc(); QDateTime t = QDateTime::currentDateTimeUtc();
if(m_astroWidget) { if(m_astroWidget) {
m_freqMoon=m_dialFreq + 1000*m_astroWidget->m_kHz + m_astroWidget->m_Hz; m_freqMoon=m_dialFreq + 1000*m_astroWidget->m_kHz + m_astroWidget->m_Hz;
int ndop,ndop00;
m_astroWidget->astroUpdate(t, m_config.my_grid (), m_hisGrid,m_freqMoon, m_astroWidget->astroUpdate(t, m_config.my_grid (), m_hisGrid,m_freqMoon,
&ndop, &ndop00, m_transmitting, &m_nDop, &m_nDop00, m_transmitting,
m_config.data_dir().absoluteFilePath("JPLEPH")); m_config.data_dir().absoluteFilePath("JPLEPH"));
//Apply Doppler corrections only for 50 MHz and above //Apply Doppler corrections only for 50 MHz and above
@ -2155,23 +2170,28 @@ void MainWindow::guiUpdate()
if(m_astroWidget->m_bDopplerTracking) { if(m_astroWidget->m_bDopplerTracking) {
int ndopr=0; // No Doppler Correction
if(m_DopplerMethod==1) { if(m_DopplerMethod==1) {
// All Doppler correction done here; DX station stays at nominal dial frequency. // All Doppler correction done here; DX station stays at nominal dial frequency.
ndopr=m_astroWidget->m_stepHz*qRound(double(ndop)/double(m_astroWidget->m_stepHz)); m_nDopr=m_astroWidget->m_stepHz*qRound(double(m_nDop)/double(
m_astroWidget->m_stepHz));
} }
if(m_DopplerMethod==2) { if(m_DopplerMethod==2) {
// Doppler correction to constant frequency on Moon // Doppler correction to constant frequency on Moon
ndopr=m_astroWidget->m_stepHz*qRound(double(ndop00/2.0)/double(m_astroWidget->m_stepHz)); m_nDopr=m_astroWidget->m_stepHz*qRound(double(m_nDop00/2.0)/double(
m_astroWidget->m_stepHz));
} }
if(m_transmitting) { if(m_transmitting) {
m_dialFreqTx=m_freqNominal + 1000*m_astroWidget->m_kHz + m_astroWidget->m_Hz - ndopr; m_dialFreqTx=m_freqNominal + 1000*m_astroWidget->m_kHz +
ui->labDialFreq->setText (Radio::pretty_frequency_MHz_string (m_dialFreqTx)); m_astroWidget->m_Hz - m_nDopr;
ui->labDialFreq->setText (Radio::pretty_frequency_MHz_string (
m_dialFreqTx));
Q_EMIT m_config.transceiver_tx_frequency (m_dialFreqTx); Q_EMIT m_config.transceiver_tx_frequency (m_dialFreqTx);
} else { } else {
m_dialFreq=m_freqNominal + 1000*m_astroWidget->m_kHz + m_astroWidget->m_Hz + ndopr; m_dialFreq=m_freqNominal + 1000*m_astroWidget->m_kHz +
ui->labDialFreq->setText (Radio::pretty_frequency_MHz_string (m_dialFreq)); m_astroWidget->m_Hz + m_nDopr;
ui->labDialFreq->setText (Radio::pretty_frequency_MHz_string (
m_dialFreq));
Q_EMIT m_config.transceiver_frequency(m_dialFreq); Q_EMIT m_config.transceiver_frequency(m_dialFreq);
} }
} }
@ -2216,7 +2236,6 @@ void MainWindow::guiUpdate()
if(!m_monitoring and !m_diskData) { if(!m_monitoring and !m_diskData) {
signalMeter->setValue(0); signalMeter->setValue(0);
} }
m_sec0=nsec; m_sec0=nsec;
} }

View File

@ -333,6 +333,9 @@ private:
qint32 m_dBm; qint32 m_dBm;
qint32 m_pctx; qint32 m_pctx;
qint32 m_nseq; qint32 m_nseq;
qint32 m_nDop; //Doppler shift of EME DX station
qint32 m_nDop00; //EME self-Doppler
qint32 m_nDopr; //Applied Doppler, rounded to nearest 1, 10 or 100 Hz
bool m_btxok; //True if OK to transmit bool m_btxok; //True if OK to transmit
bool m_diskData; bool m_diskData;
@ -555,6 +558,10 @@ extern "C" {
void wspr_downsample_(short int d2[], int* k); void wspr_downsample_(short int d2[], int* k);
void savec2_(char* fname, int* m_TRseconds, double* m_dialFreq, int len1); void savec2_(char* fname, int* m_TRseconds, double* m_dialFreq, int len1);
void avecho_( short id2[], int* dop, int* nfrit, int* nqual, float* f1,
float* rms, float* sigdb, float* snr, float* dfreq,
float* width);
} }
#endif // MAINWINDOW_H #endif // MAINWINDOW_H