mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-03-20 19:19:02 -04:00
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:
parent
220f03c7be
commit
0e87c974e9
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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><html><head/><body><p>Noise level of 30dB recommended<br/>dB annotations:<br/>* = clipping occured<br/>- = signal too low<br/>+ = signal too high</p></body></html></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="ok"] {
|
||||
</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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user