2008-02-14 20:19:42 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// pskeval.cxx -- psk signal evaluator
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Copyright (C) 2008-2009
|
2008-02-14 20:19:42 +00:00
|
|
|
// Dave Freese, W1HKJ
|
|
|
|
//
|
|
|
|
// This file is part of fldigi. Adapted from code contained in gmfsk source code
|
|
|
|
// distribution.
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Fldigi is free software: you can redistribute it and/or modify
|
2008-02-14 20:19:42 +00:00
|
|
|
// it under the terms of the GNU General Public License as published by
|
2010-03-01 12:56:30 +00:00
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
2008-02-14 20:19:42 +00:00
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Fldigi is distributed in the hope that it will be useful,
|
2008-02-14 20:19:42 +00:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
2010-03-01 12:56:30 +00:00
|
|
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
2008-02-14 20:19:42 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2010-03-01 12:56:30 +00:00
|
|
|
|
2008-03-02 08:22:41 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
2009-04-12 22:57:17 +00:00
|
|
|
#include "fl_digi.h"
|
2008-02-14 20:19:42 +00:00
|
|
|
#include "pskeval.h"
|
2010-12-23 02:14:44 +00:00
|
|
|
#include "configuration.h"
|
|
|
|
#include "misc.h"
|
2008-02-14 20:19:42 +00:00
|
|
|
|
2008-12-10 21:05:53 +00:00
|
|
|
using namespace std;
|
2008-02-14 20:19:42 +00:00
|
|
|
//=============================================================================
|
|
|
|
//========================== psk signal evaluation ============================
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
pskeval::pskeval() {
|
|
|
|
bw = 31.25;
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
pskeval::~pskeval() {
|
|
|
|
}
|
|
|
|
|
2010-12-28 04:06:15 +00:00
|
|
|
int countdown = 8;
|
|
|
|
int rows = 0;
|
2010-12-23 02:14:44 +00:00
|
|
|
|
2008-02-14 20:19:42 +00:00
|
|
|
void pskeval::sigdensity() {
|
2010-12-28 21:58:33 +00:00
|
|
|
int ihbw = (int)(0.6*bw);
|
2008-02-14 20:19:42 +00:00
|
|
|
int ibw = 2 * ihbw;
|
2010-12-28 04:06:15 +00:00
|
|
|
|
2010-12-23 02:14:44 +00:00
|
|
|
double *vals = new double[ibw];
|
2010-12-28 04:06:15 +00:00
|
|
|
double sig = 0.0;
|
|
|
|
double val = 0.0;
|
|
|
|
|
|
|
|
int low = progdefaults.LowFreqCutoff;
|
|
|
|
if (low < ihbw) low = ihbw;
|
|
|
|
int high = progdefaults.HighFreqCutoff;
|
|
|
|
if (high > FFT_LEN - ihbw) high = FFT_LEN - ihbw;
|
|
|
|
int nbr = high - low;
|
|
|
|
|
2010-12-28 21:58:33 +00:00
|
|
|
sigmin = 1e6;
|
2010-12-28 04:06:15 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < ibw; i++) {
|
|
|
|
val = vals[i] = wf->Pwr(i + low - ihbw);
|
2008-02-14 20:19:42 +00:00
|
|
|
sig += val;
|
2010-12-28 04:06:15 +00:00
|
|
|
}
|
|
|
|
for (int i = 0, j = 0; i < nbr; i++) {
|
2010-12-28 21:58:33 +00:00
|
|
|
sigpwr[i + low] = decayavg(sigpwr[i + low], sig, 32);
|
2010-12-28 04:06:15 +00:00
|
|
|
sig -= vals[j];
|
|
|
|
val = vals[j] = wf->Pwr(i + ihbw + low);
|
|
|
|
sig += val;
|
|
|
|
if (++j == ibw) j = 0;
|
2010-12-28 21:58:33 +00:00
|
|
|
if (sig < sigmin) sigmin = sig;
|
2010-12-28 04:06:15 +00:00
|
|
|
}
|
2010-12-28 21:58:33 +00:00
|
|
|
|
|
|
|
if (sigmin < 1e-8) sigmin = 1e-8;
|
2008-04-04 09:18:52 +00:00
|
|
|
delete [] vals;
|
2008-02-14 20:19:42 +00:00
|
|
|
}
|
|
|
|
|
High Speed / Multi-Carrier Modems
* This commit contributed to by:
- John Douyere <vk2eta@gmail.com>
- Dave Freese <w1hkj@w1hkj.com>
- John Phelps <kl4yfd@gmail.com>
- Andrej Lajovic <s57ln@hamradio.si>
* New high speed and multi carrier modems
- psk, pskr
- DominoEX
- Thor
* Added separate modem initialization for
Olivia tone / bandwidth pairs:
- 4/250, 8/250
- 4/500, 8/500, 16/500
- 8/1000, 16/1000, 32/1000
- 64/2000
* RSID changes
- Added secondary RsID code set
- RsID code 263 enables detection of the secondary
RsID code burst.
* MFSK UTF-8 tx
- corrected transmit of two-byte UTF-8 characters
* PSK-UTF-8 tx
- corrected transmit of two-byte UTF-8 characters
* Changed PSK multicarrier bandwidth markers to show full
extent of signal in the waterfall.
* THOR modem updates
- Added Thor high speed modes
25x4, 50, 50x2, 100 Baud, all < 1800 Hz bandwidth
- IFK+ Softdecode function for THOR
dynamically detects and suppresses CWI
Rx printing is disabled when "File IO only" is selected for
soundcard. Decoder uses puncture in this condition.
- THOR FEC confidence indicator
Uses the actual path-metrics from the Viterbi decoder.
Displays next to the S/N in the main dialog.
2012-12-27 14:24:20 +00:00
|
|
|
double pskeval::sigpeak(int &f, int f1, int f2)
|
2008-02-14 20:19:42 +00:00
|
|
|
{
|
|
|
|
double peak = 0;
|
2010-12-28 04:06:15 +00:00
|
|
|
f1 -= bw;
|
|
|
|
if (f1 <= progdefaults.LowFreqCutoff) f1 = progdefaults.LowFreqCutoff;
|
|
|
|
f2 += bw;
|
|
|
|
if (f2 >= progdefaults.HighFreqCutoff) f2 = progdefaults.HighFreqCutoff;
|
|
|
|
|
|
|
|
int fa = f2, fb = f1;
|
|
|
|
|
|
|
|
for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
|
|
|
|
if (!peak) return 0;
|
|
|
|
for (int i = f1; i < f2; i++)
|
|
|
|
if (sigpwr[i] > peak*0.75) fb = i;
|
|
|
|
for (int i = f2; i > f1; i--)
|
|
|
|
if (sigpwr[i] > peak*0.75) fa = i;
|
|
|
|
if (fa > fb) return 0;
|
|
|
|
f = (fa + fb) / 2;
|
2010-12-28 21:58:33 +00:00
|
|
|
return peak / sigmin / bw;
|
2008-02-14 20:19:42 +00:00
|
|
|
}
|
|
|
|
|
2010-12-28 21:58:33 +00:00
|
|
|
double pskeval::peak(int &f0, int f1, int f2, double db)
|
2010-12-23 02:14:44 +00:00
|
|
|
{
|
|
|
|
double peak = 0;
|
2010-12-28 04:06:15 +00:00
|
|
|
|
2010-12-23 02:14:44 +00:00
|
|
|
int fa = f2, fb = f1;
|
2010-12-28 21:58:33 +00:00
|
|
|
double level = pow(10, (10 + db) / 10.0);
|
2010-12-28 04:06:15 +00:00
|
|
|
|
|
|
|
//step 1
|
|
|
|
for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
|
2010-12-28 21:58:33 +00:00
|
|
|
|
|
|
|
if (((peak-sigmin) / sigmin ) < level) {
|
|
|
|
return 0;
|
|
|
|
}
|
2010-12-28 04:06:15 +00:00
|
|
|
|
|
|
|
for (int i = f1; i < f2; i++)
|
|
|
|
if (sigpwr[i] > peak*0.75) fb = i;
|
|
|
|
for (int i = f2; i > f1; i--)
|
|
|
|
if (sigpwr[i] > peak*0.75) fa = i;
|
2010-12-28 21:58:33 +00:00
|
|
|
if (fa > fb) {
|
|
|
|
return 0;
|
|
|
|
}
|
2010-12-28 04:06:15 +00:00
|
|
|
f0 = (fa + fb) / 2;
|
|
|
|
//step 2
|
2010-12-31 11:31:52 +00:00
|
|
|
f1 = f0 - 1.5*bw;
|
|
|
|
if (f1 < bw) f1 = bw;
|
|
|
|
f2 = f0 + 1.5*bw;
|
|
|
|
fb = f1; fa = f2;
|
2010-12-28 04:06:15 +00:00
|
|
|
peak = 0;
|
|
|
|
for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
|
|
|
|
for (int i = f1; i < f2; i++)
|
|
|
|
if (sigpwr[i] > peak*0.75) fb = i;
|
|
|
|
for (int i = f2; i > f1; i--)
|
|
|
|
if (sigpwr[i] > peak*0.75) fa = i;
|
2010-12-28 21:58:33 +00:00
|
|
|
if (fa > fb) {
|
|
|
|
return 0;
|
|
|
|
}
|
2010-12-28 04:06:15 +00:00
|
|
|
f0 = (fa + fb) / 2;
|
2010-12-28 21:58:33 +00:00
|
|
|
return (peak - sigmin) / sigmin ;
|
2010-12-23 02:14:44 +00:00
|
|
|
}
|
|
|
|
|
2008-02-14 20:19:42 +00:00
|
|
|
void pskeval::clear() {
|
|
|
|
for (int i = 0; i < FFT_LEN; i++) sigpwr[i] = 0.0;
|
|
|
|
}
|