Modified behavior of audio level meter and adjacent slider; Tx6 at program startup.

1. Level meter range increased to 0-90 dB.
2. Level meter reading is independent of slider setting.
3. For a trial period: thermometer bar goes red if a 16-bit sample
   is within 5 dB A/D limit.
4. Slider can be used to adjust levels sent to waterfall.
5. Tx6 message is selected on program startup.
Thanks to W9MDB for most of this code.



git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7596 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Joe Taylor 2017-03-06 14:34:25 +00:00
parent 220f03c7be
commit 0e87c974e9
10 changed files with 90 additions and 32 deletions

View File

@ -10,10 +10,7 @@ button to start normal receive operation.
controls to set the background noise level (scale at lower left of
main window) to around 30 dB when no signals are present. It is
usually best to turn AGC off or reduce the RF gain control to minimize
AGC action. If necessary you can also adjust the slider next to the
dB scale, but note that the overall dynamic range will be best when
the displayed level is near 30 dB with the slider close to its
mid-point.
AGC action.
.Bandwidth and Frequency Setting

View File

@ -1,5 +1,5 @@
subroutine hspec(id2,k,nutc0,ntrpdepth,nrxfreq,ntol,bmsk144,bcontest, &
btrain,pcoeffs,ingain,mycall,hiscall,bshmsg,bswl,datadir,green,s,jh,line1, &
btrain,pcoeffs,ingain,mycall,hiscall,bshmsg,bswl,datadir,green,s,jh,pxmax,rmsNoGain,line1, &
mygrid)
! Input:
@ -56,15 +56,24 @@ subroutine hspec(id2,k,nutc0,ntrpdepth,nrxfreq,ntol,bmsk144,bcontest, &
rms0=0.0
endif
pxmax = 0;
do iblk=1,nblks
if(jh.lt.JZ-1) jh=jh+1
ja=ja+nstep
jb=ja+nfft-1
x=id2(ja:jb)
sq=dot_product(x,x)
xmax = maxval(x);
xmin = abs(minval(x));
if (xmin > xmax) xmax = xmin;
if (xmax.gt.0.0) pxmax=20.0*log10(xmax);
rms=sqrt(gain*sq/nfft)
rms2=sqrt(sq/nfft);
green(jh)=0.
if(rms.gt.0.0) green(jh)=20.0*log10(rms)
if(rms.gt.0.0) then
green(jh)=20.0*log10(rms)
rmsNoGain=20.0*log10(rms2);
endif
call four2a(x,nfft,1,-1,0) !Real-to-complex FFT
df=12000.0/nfft
fac=(1.0/nfft)**2

View File

@ -1,5 +1,5 @@
subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, &
df3,ihsym,npts8)
df3,ihsym,npts8, rmsnogain, pxdbmax)
! Input:
! k pointer to the most recent new data
@ -27,6 +27,7 @@ subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, &
real*4 ssum(NSMAX)
real*4 xc(0:MAXFFT3-1)
real*4 tmp(NSMAX)
real*4 rmsnogain
complex cx(0:MAXFFT3/2)
integer nch(7)
@ -64,15 +65,20 @@ subroutine symspec(shared_data,k,ntrperiod,nsps,ingain,nminw,pxdb,s, &
endif
gain=10.0**(0.1*ingain)
sq=0.
pxmax=0.;
do i=k0+1,k
x1=shared_data%id2(i)
if (abs(x1).gt.pxmax) pxmax = abs(x1);
sq=sq + x1*x1
enddo
rmsnogain = 0.
if (sq.gt.0.0) rmsnogain=20*log10(sqrt(sq/(k-k0)))
sq=sq * gain
rms=sqrt(sq/(k-k0))
pxdb=0.
pxdbmax = 20*log10(pxmax)
if(rms.gt.0.0) pxdb=20.0*log10(rms)
if(pxdb.gt.60.0) pxdb=60.0
if(pxdb.gt.90.0) pxdb=90.0
k0=k
ja=ja+jstep !Index of first sample

View File

@ -66,13 +66,14 @@
extern "C" {
//----------------------------------------------------- C and Fortran routines
void symspec_(struct dec_data *, int* k, int* ntrperiod, int* nsps, int* ingain,
int* minw, float* px, float s[], float* df3, int* nhsym, int* npts8);
int* minw, float* px, float s[], float* df3, int* nhsym, int* npts8, float *rmsnogain, float *m_pxmax);
void hspec_(short int d2[], int* k, int* nutc0, int* ntrperiod, int* nrxfreq, int* ntol,
bool* bmsk144, bool* bcontest, bool* btrain, double const pcoeffs[], int* ingain,
char mycall[], char hiscall[], bool* bshmsg, bool* bswl, char ddir[], float green[],
float s[], int* jh, char line[], char mygrid[],
float s[], int* jh, float *pxmax, float *rmsNoGain, char line[], char mygrid[],
int len1, int len2, int len3, int len4, int len5);
// float s[], int* jh, char line[], char mygrid[],
void gen4_(char* msg, int* ichk, char* msgsent, int itone[],
int* itext, int len1, int len2);
@ -139,6 +140,7 @@ float fast_green2[703];
float fast_s[44992]; //44992=64*703
float fast_s2[44992];
int fast_jh {0};
int fast_jhpeak {0};
int fast_jh2 {0};
int narg[15];
QVector<QColor> g_ColorTbl;
@ -264,6 +266,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_ihsym {0},
m_nzap {0},
m_px {0.0},
m_rmsNoGain {0.0},
m_iptt0 {0},
m_btxok0 {false},
m_nsendingsh {0},
@ -837,7 +840,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->actionEnable_AP_DXcall->setChecked(m_ndepth&64);
m_UTCdisk=-1;
m_ntx = 1;
m_fCPUmskrtd=0.0;
m_bFastDone=false;
m_bAltV=false;
@ -845,7 +847,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_bVHFwarned=false;
m_bDoubleClicked=false;
m_wait=0;
ui->txrb1->setChecked(true);
if(m_mode.startsWith ("WSPR") and m_pctx>0) {
QPalette palette {ui->sbTxPercent->palette ()};
@ -1161,13 +1162,13 @@ void MainWindow::dataSink(qint64 frames)
int nsps=m_nsps;
if(m_bFastMode) nsps=6912;
int nsmo=m_wideGraph->smoothYellow()-1;
symspec_(&dec_data,&k,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&m_ihsym,&m_npts8);
symspec_(&dec_data,&k,&trmin,&nsps,&m_inGain,&nsmo,&m_px,s,&m_df3,&m_ihsym,&m_npts8,&m_rmsNoGain,&m_pxmax);
if(m_mode=="WSPR") wspr_downsample_(dec_data.d2,&k);
if(m_ihsym <=0) return;
QString t;
m_pctZap=m_nzap*100.0/m_nsps; // TODO: this is currently redundant
t.sprintf(" Rx noise: %5.1f ",m_px);
if (ui) ui->signal_meter_widget->setValue(m_px); // Update thermometer
if (ui) ui->signal_meter_widget->setValue(m_rmsNoGain,m_pxmax); // Update thermometer
if(m_monitoring || m_diskData) {
m_wideGraph->dataSink2(s,m_df3,m_ihsym,m_diskData);
}
@ -1383,15 +1384,17 @@ void MainWindow::fastSink(qint64 frames)
dataDir = m_dataDir.absolutePath ();
char ddir[512];
strncpy(ddir,dataDir.toLatin1(), sizeof (ddir) - 1);
float pxmax = 0;
float rmsNoGain = 0;
hspec_(dec_data.d2,&k,&nutc0,&nTRpDepth,&RxFreq,&m_Ftol,&bmsk144,&bcontest,
&m_bTrain,m_phaseEqCoefficients.constData(),&m_inGain,&dec_data.params.mycall[0],
&dec_data.params.hiscall[0],&bshmsg,&bswl,
&ddir[0],fast_green,fast_s,&fast_jh,&line[0],&dec_data.params.mygrid[0],
&ddir[0],fast_green,fast_s,&fast_jh,&pxmax,&rmsNoGain,&line[0],&dec_data.params.mygrid[0],
12,12,512,80,6);
float px = fast_green[fast_jh];
QString t;
t.sprintf(" Rx noise: %5.1f ",px);
ui->signal_meter_widget->setValue(px); // Update thermometer
ui->signal_meter_widget->setValue(rmsNoGain,pxmax); // Update thermometer
m_fastGraph->plotSpec(m_diskData,m_UTCdisk);
if(bmsk144 and (line[0]!=0)) {
@ -3230,7 +3233,7 @@ void MainWindow::guiUpdate()
t.time().toString() + " ";
ui->labUTC->setText(utc);
if(!m_monitoring and !m_diskData) {
ui->signal_meter_widget->setValue(0);
ui->signal_meter_widget->setValue(0,0);
}
m_sec0=nsec;
displayDialFrequency ();
@ -3252,7 +3255,7 @@ void MainWindow::startTx2()
if(t.mid(0,1)=="#") snr=t.mid(1,5).toDouble();
if(snr>0.0 or snr < -50.0) snr=99.0;
transmit (snr);
ui->signal_meter_widget->setValue(0);
ui->signal_meter_widget->setValue(0,0);
if(m_mode=="Echo" and !m_tune) m_bTransmittedEcho=true;
if(m_mode.startsWith ("WSPR") and !m_tune) {
@ -5482,7 +5485,7 @@ void MainWindow::transmitDisplay (bool transmitting)
{
if (transmitting == m_transmitting) {
if (transmitting) {
ui->signal_meter_widget->setValue(0);
ui->signal_meter_widget->setValue(0,0);
if (m_monitoring) monitor (false);
m_btxok=true;
}

View File

@ -444,6 +444,8 @@ private:
int m_nzap;
int m_npts8;
float m_px;
float m_pxmax;
float m_rmsNoGain;
float m_df3;
int m_iptt0;
bool m_btxok0;

View File

@ -2,6 +2,14 @@
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>867</width>
<height>583</height>
</rect>
</property>
<property name="windowTitle">
<string>WSJT-X by K1JT</string>
</property>
@ -1919,6 +1927,9 @@ list. The list can be maintained in Settings (F2).</string>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Noise level of 30dB recommended&lt;br/&gt;dB annotations:&lt;br/&gt;* = clipping occured&lt;br/&gt;- = signal too low&lt;br/&gt;+ = signal too high&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
@ -1930,7 +1941,7 @@ list. The list can be maintained in Settings (F2).</string>
<item row="1" column="1" rowspan="2">
<widget class="QSlider" name="inGain">
<property name="toolTip">
<string>Digital gain for audio input</string>
<string>Digital gain for graph windows</string>
</property>
<property name="minimum">
<number>-50</number>
@ -2355,6 +2366,14 @@ QPushButton[state=&quot;ok&quot;] {
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>867</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>

View File

@ -8,9 +8,12 @@
#include "moc_meterwidget.cpp"
#define MAXDB 90
MeterWidget::MeterWidget(QWidget * parent)
: QWidget {parent}
, m_signal {0}
, m_noisePeak {0}
, m_sigPeak {0}
{
for ( int i = 0; i < 10; i++ ) {
@ -30,7 +33,7 @@ void MeterWidget::setValue(int value)
if (signalQueue.at(i) > tmp)
tmp = signalQueue.at(i);
}
m_sigPeak = tmp;
m_noisePeak = tmp;
update();
}
@ -46,23 +49,35 @@ void MeterWidget::paintEvent (QPaintEvent * event)
// Sanitize
m_signal = m_signal < 0 ? 0 : m_signal;
m_signal = m_signal > 60 ? 60 : m_signal;
m_signal = m_signal > MAXDB ? MAXDB : m_signal;
QPainter p {this};
p.setPen (Qt::NoPen);
auto const& target = contentsRect ();
QRect r {QPoint {target.left (), static_cast<int> (target.top () + target.height () - m_signal / 60. * target.height ())}
QRect r {QPoint {target.left (), static_cast<int> (target.top () + target.height () - m_signal / (double)MAXDB * target.height ())}
, QPoint {target.right (), target.bottom ()}};
p.setBrush (QColor {255, 150, 0});
p.setBrush (QColor {Qt::green});
if (m_sigPeak > 85) {
p.setBrush(Qt::red);
}
else if (m_noisePeak < 15) {
p.setBrush(Qt::yellow);
}
p.drawRect (r);
if (m_sigPeak)
if (m_noisePeak)
{
// Draw peak hold indicator
auto peak = static_cast<int> (target.top () + target.height () - m_sigPeak / 60. * target.height ());
auto peak = static_cast<int> (target.top () + target.height () - m_noisePeak / (double)MAXDB * target.height ());
p.setBrush (Qt::black);
p.translate (target.left (), peak);
p.drawPolygon (QPolygon {{{0, -4}, {0, 4}, {target.width (), 0}}});
}
}
//
void MeterWidget::set_sigPeak(int value)
{
m_sigPeak = value;
}

View File

@ -19,13 +19,15 @@ public:
// QWidget implementation
QSize sizeHint () const override;
void set_sigPeak(int value);
protected:
void paintEvent( QPaintEvent * ) override;
private:
QQueue<int> signalQueue;
int m_signal;
int m_sigPeak;
int m_noisePeak;
int m_sigPeak; // peak value for color coding
};
#endif // METERWIDGET_H

View File

@ -15,6 +15,8 @@
#include "moc_signalmeter.cpp"
#define MAXDB 90
class Scale final
: public QWidget
{
@ -52,8 +54,10 @@ protected:
p.translate (target.left ()
, target.top () + font_offset + i * (target.height () - font_metrics.ascent () - font_metrics.descent ()) / range);
p.drawLine (0, 0, tick_length, 0);
auto text = i ? QString::number ((range - i) * scale) : QString {"%1%2"}.arg ((range - i) * scale).arg ('+');
p.drawText (tick_length + text_indent, font_offset, text);
if((i%2==1)) {
auto text = QString::number ((range - i) * scale);
p.drawText (tick_length + text_indent, font_offset, text);
}
p.restore ();
}
}
@ -62,7 +66,7 @@ private:
static int constexpr tick_length {4};
static int constexpr text_indent {2};
static int constexpr line_spacing {0};
static int constexpr range {6};
static int constexpr range {MAXDB/10};
static int constexpr scale {10};
};
@ -90,12 +94,13 @@ SignalMeter::SignalMeter (QWidget * parent)
setLayout (outer_layout);
}
void SignalMeter::setValue(float value)
void SignalMeter::setValue(float value, float valueMax)
{
if(value<0) value=0;
QFontMetrics font_metrics {m_scale->font (), nullptr};
m_meter->setContentsMargins (0, font_metrics.ascent () / 2, 0, font_metrics.ascent () / 2 + font_metrics.descent ());
m_meter->setValue(int(value));
m_meter->set_sigPeak(valueMax);
QString t;
t.sprintf("%4.1f dB",value);
m_reading->setText(t);

View File

@ -16,7 +16,7 @@ public:
explicit SignalMeter (QWidget * parent = nullptr);
public slots:
void setValue (float value);
void setValue (float value, float valueMax);
private:
MeterWidget * m_meter;