mirror of
https://github.com/JvanKatwijk/qt-dab.git
synced 2025-10-06 00:02:40 +02:00
added F6 key
This commit is contained in:
@@ -264,9 +264,9 @@ float bitSum = 0;
|
||||
meanLevelVector [index] =
|
||||
compute_avg (meanLevelVector [index], binAbsLevel, ALPHA);
|
||||
|
||||
DABFLOAT d_x = real (fftBin_at_1) -
|
||||
DABFLOAT d_x = abs (real (fftBin_at_1)) -
|
||||
meanLevelVector [index] / sqrt_2;
|
||||
DABFLOAT d_y = imag (fftBin_at_1) -
|
||||
DABFLOAT d_y = abs (imag (fftBin_at_1)) -
|
||||
meanLevelVector [index] / sqrt_2;
|
||||
DABFLOAT sigmaSQ = d_x * d_x + d_y * d_y;
|
||||
sigmaSQ_Vector [index] =
|
||||
@@ -276,12 +276,12 @@ float bitSum = 0;
|
||||
// working best
|
||||
if (this -> decoder == DECODER_1) {
|
||||
DABFLOAT corrector =
|
||||
1.5 * meanLevelVector [index] / sigmaSQ_Vector [index];
|
||||
1.5 * meanLevelVector [index] / sigmaSQ_Vector [index];
|
||||
corrector /= (1 / snr + 2);
|
||||
Complex R1 = corrector * normalize (fftBin) *
|
||||
(DABFLOAT)(sqrt (jan_abs (fftBin) *
|
||||
sqrt (jan_abs (phaseReference [index]))));
|
||||
float scaler = 100.0 / meanValue;
|
||||
(DABFLOAT)(sqrt (binAbsLevel *
|
||||
jan_abs (phaseReference [index])));
|
||||
float scaler = 140.0 / meanValue;
|
||||
DABFLOAT leftBit = - real (R1) * scaler;
|
||||
limit_symmetrically (leftBit, MAX_VITERBI);
|
||||
softbits [i] = (int16_t)leftBit;
|
||||
@@ -298,9 +298,9 @@ float bitSum = 0;
|
||||
meanLevelVector [index] / sigmaSQ_Vector [index];
|
||||
corrector /= (1 / snr + 3);
|
||||
Complex R1 = corrector * normalize (fftBin) *
|
||||
(DABFLOAT)(sqrt (jan_abs (fftBin) *
|
||||
sqrt (jan_abs (phaseReference [index]))));
|
||||
float scaler = 140 / meanValue;
|
||||
(DABFLOAT)(sqrt (binAbsLevel *
|
||||
jan_abs (phaseReference [index])));
|
||||
float scaler = 100 / meanValue;
|
||||
DABFLOAT leftBit = - real (R1) * scaler;
|
||||
limit_symmetrically (leftBit, MAX_VITERBI);
|
||||
softbits [i] = (int16_t)leftBit;
|
||||
|
@@ -1,484 +0,0 @@
|
||||
#
|
||||
/*
|
||||
* Copyright (C) 2014 .. 2024
|
||||
* Jan van Katwijk (J.vanKatwijk@gmail.com)
|
||||
* Lazy Chair Computing
|
||||
*
|
||||
* This file is part of Qt-DAB
|
||||
*
|
||||
* Qt-DAB is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Qt-DAB is distributed in the hope that it will be useful,
|
||||
* 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
|
||||
* along with Qt-DAB; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Once the bits are "in", interpretation and manipulation
|
||||
* should reconstruct the data blocks.
|
||||
* Ofdm_decoder is called for Block_0 and the FIC blocks,
|
||||
* its invocation results in 2 * Tu bits
|
||||
*
|
||||
* The commented decoders were from Thomas Neder and used in an
|
||||
* experiment, the "shifting" from fftBinRaw to fftBin is from his work
|
||||
*/
|
||||
#include <vector>
|
||||
#include "ofdm-decoder.h"
|
||||
#include "radio.h"
|
||||
#include "fic-handler.h"
|
||||
#include "msc-handler.h"
|
||||
#include "freq-interleaver.h"
|
||||
#include "dab-params.h"
|
||||
#include "dab-constants.h"
|
||||
/**
|
||||
* \brief ofdmDecoder
|
||||
* The class ofdmDecoder is
|
||||
* taking the data from the ofdmProcessor class in, and
|
||||
* will extract the Tu samples, do an FFT and extract the
|
||||
* carriers and map them on (soft) bits
|
||||
*/
|
||||
#define ALPHA 0.01f
|
||||
static inline
|
||||
Complex normalize (const Complex &V) {
|
||||
float Length = jan_abs (V);
|
||||
return Length == 0.0f ? Complex (0.0, 0.0) : V / (DABFLOAT)Length;
|
||||
}
|
||||
|
||||
#define GRANULARITY 5000
|
||||
#define TABLE_SIZE (int)(GRANULARITY + RAD_PER_DEGREE * 30.0)
|
||||
//Complex makeComplex (DABFLOAT phase) {
|
||||
//DABFLOAT p2 = phase * phase;
|
||||
//DABFLOAT p3 = p2 * phase;
|
||||
//DABFLOAT p4 = p3 * phase;
|
||||
//DABFLOAT p5 = p4 * phase;
|
||||
//DABFLOAT p6 = p5 * phase;
|
||||
//DABFLOAT sine = phase - p3 / 6 + p5 / 120;
|
||||
//DABFLOAT cosi = 1 - p2 / 2 + p4 / 24 - p6 / 720;
|
||||
// return Complex (cosi, sine);
|
||||
//}
|
||||
|
||||
ofdmDecoder::ofdmDecoder (RadioInterface *mr,
|
||||
uint8_t dabMode,
|
||||
int16_t bitDepth,
|
||||
RingBuffer<float> *devBuffer_i,
|
||||
RingBuffer<Complex> *iqBuffer_i) :
|
||||
myRadioInterface (mr),
|
||||
params (dabMode),
|
||||
theTable (dabMode),
|
||||
myMapper (dabMode),
|
||||
fft (params. get_T_u (), false),
|
||||
devBuffer (devBuffer_i),
|
||||
iqBuffer (iqBuffer_i),
|
||||
phaseReference (params. get_T_u ()),
|
||||
conjVector (params. get_T_u ()),
|
||||
fft_buffer (params. get_T_u ()),
|
||||
stdDevVector (params. get_T_u ()),
|
||||
IntegAbsPhaseVector (params. get_T_u ()),
|
||||
meanLevelVector (params. get_T_u ()),
|
||||
meanPowerVector (params. get_T_u ()),
|
||||
meanSigmaSqVector (params. get_T_u ())
|
||||
{
|
||||
(void)bitDepth;
|
||||
connect (this, &ofdmDecoder::showIQ,
|
||||
myRadioInterface, &RadioInterface::showIQ);
|
||||
connect (this, &ofdmDecoder::show_quality,
|
||||
myRadioInterface, &RadioInterface::show_quality);
|
||||
connect (this, &ofdmDecoder::show_stdDev,
|
||||
myRadioInterface, &RadioInterface::show_stdDev);
|
||||
//
|
||||
this -> T_s = params. get_T_s ();
|
||||
this -> T_u = params. get_T_u ();
|
||||
this -> nrBlocks = params. get_L ();
|
||||
this -> carriers = params. get_carriers ();
|
||||
this -> T_g = T_s - T_u;
|
||||
|
||||
repetitionCounter = 10;
|
||||
|
||||
reset ();
|
||||
iqSelector = SHOW_DECODED;
|
||||
decoder = DECODER_1;
|
||||
|
||||
nullPower = 0.1f;
|
||||
compTable. resize (TABLE_SIZE);
|
||||
for (int i = 0; i < TABLE_SIZE; i ++) {
|
||||
float argum = (float)(i - TABLE_SIZE / 2) / TABLE_SIZE;
|
||||
compTable [i] = Complex (cos (argum), sin (argum));
|
||||
}
|
||||
}
|
||||
|
||||
ofdmDecoder::~ofdmDecoder () {
|
||||
}
|
||||
//
|
||||
void ofdmDecoder::stop () {
|
||||
}
|
||||
//
|
||||
void ofdmDecoder::reset () {
|
||||
memset (stdDevVector. data (), 0, T_u * sizeof (DABFLOAT));
|
||||
memset (IntegAbsPhaseVector. data (), 0, T_u * sizeof (DABFLOAT));
|
||||
memset (meanLevelVector. data (), 0, T_u * sizeof (DABFLOAT));
|
||||
memset (meanPowerVector. data (), 0, T_u * sizeof (DABFLOAT));
|
||||
memset (meanSigmaSqVector. data (), 0, T_u * sizeof (DABFLOAT));
|
||||
meanValue = 1.0f;
|
||||
}
|
||||
//
|
||||
void ofdmDecoder::setPowerLevel (DABFLOAT level) {
|
||||
nullPower = level * level;
|
||||
}
|
||||
|
||||
float ofdmDecoder::processBlock_0 (
|
||||
std::vector <Complex> buffer, bool withTII) {
|
||||
fft. fft (buffer);
|
||||
// we are now in the frequency domain, and we keep the carriers
|
||||
// as coming from the FFT as phase reference.
|
||||
//
|
||||
memcpy (phaseReference. data (), buffer. data (),
|
||||
T_u * sizeof (Complex));
|
||||
|
||||
Complex temp = Complex (0, 0);;
|
||||
if (withTII) {
|
||||
return arg (temp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Just interested. In the ideal case the constellation of the
|
||||
// decoded symbols is precisely in the four points
|
||||
// k * (1, 1), k * (1, -1), k * (-1, -1), k * (-1, 1)
|
||||
// To ease computation, we map all incoming values onto quadrant 1
|
||||
//
|
||||
// For the computation of the MER we use the definition
|
||||
// from ETSI TR 101 290 (appendix C1)
|
||||
float ofdmDecoder::computeQuality (Complex *v) {
|
||||
static float f_n = 1;
|
||||
static float f_d = 1;
|
||||
for (int i = 0; i < carriers; i ++) {
|
||||
Complex ss = v [T_u / 2 - carriers / 2 + i];
|
||||
float ab = jan_abs (ss) / sqrt (2);
|
||||
f_n = 0.99 * f_n + 0.01 * (jan_abs (ss) * jan_abs (ss));
|
||||
float R = abs (abs (real (ss)) - ab);
|
||||
float I = abs (abs (imag (ss)) - ab);
|
||||
f_d = 0.99 * f_d + 0.01 * (R * R + I * I);
|
||||
}
|
||||
return 10 * log10 (f_n / f_d + 0.1);
|
||||
}
|
||||
|
||||
// for the other blocks of data, the first step is to go from
|
||||
// time to frequency domain, to get the carriers.
|
||||
// we distinguish between FIC blocks and other blocks,
|
||||
// only to spare a test. The mapping code is the same
|
||||
|
||||
static int cnt = 0;
|
||||
|
||||
//
|
||||
// DAB (and DAB+) bits are encoded is DPSK, 2 bits per carrier,
|
||||
// depending on the quadrant the carrier is in. There are
|
||||
// of course two different approaches in decoding the bits
|
||||
// One is looking at the X and Y components, and
|
||||
// their length, relative to each other,
|
||||
// Ideally, the X and Y are of equal size, in practice they are not.
|
||||
|
||||
int sign (DABFLOAT x) {
|
||||
return x < 0 ? -1 : x > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
void limit_symmetrically (DABFLOAT &v, float limit) {
|
||||
if (v < -limit)
|
||||
v = -limit;
|
||||
if (v > limit)
|
||||
v = limit;
|
||||
}
|
||||
//
|
||||
// How to compute a sin or cos for (hopefully) small angles,
|
||||
// Some tests showed the using the first few terms of the
|
||||
// Taylor series for angles up to PI / 4 were up to the fourth
|
||||
// decimal correct.
|
||||
// A more performance oriented solution could be a table,
|
||||
// but then, the granularity of the table should be pretty high.
|
||||
|
||||
void ofdmDecoder::decode (std::vector <Complex> &buffer,
|
||||
int32_t blkno,
|
||||
std::vector<int16_t> &softbits) {
|
||||
DABFLOAT sum = 0;
|
||||
|
||||
memcpy (fft_buffer. data (), &((buffer. data ()) [T_g]),
|
||||
T_u * sizeof (Complex));
|
||||
// first step: do the FFT
|
||||
fft. fft (fft_buffer. data ());
|
||||
|
||||
// a little optimization: we do not interchange the
|
||||
// positive/negative frequencies to their right positions.
|
||||
// The de-interleaving understands this
|
||||
// DABFLOAT max = 0;
|
||||
|
||||
for (int i = 0; i < carriers; i ++) {
|
||||
int16_t index = myMapper. mapIn (i);
|
||||
if (index < 0)
|
||||
index += T_u;
|
||||
//
|
||||
// decoding is computing the phase difference between
|
||||
// carriers with the same index in subsequent blocks.
|
||||
// The carrier of a block is the reference for the carrier
|
||||
// on the same position in the next block
|
||||
|
||||
Complex fftBinRaw = fft_buffer [index] *
|
||||
normalize (conj (phaseReference [index]));
|
||||
conjVector [index] = fftBinRaw;
|
||||
#define __FAST_DECODING__
|
||||
#ifdef __FAST_DECODING__
|
||||
float binAbsLevel = jan_abs (fftBinRaw);
|
||||
softbits [i] = - real (fftBinRaw) / binAbsLevel * MAX_VITERBI;
|
||||
softbits [carriers + i]
|
||||
= - imag (fftBinRaw) / binAbsLevel * MAX_VITERBI;
|
||||
}
|
||||
#else
|
||||
// In the original code, "borrowed" from Tomneda, the
|
||||
// correction factor was dynamically computed, i.e
|
||||
// Complex fftBin = fftBinRaw *
|
||||
// makeComplex (-IntegAbsPhaseVector [index]);
|
||||
// It turned out that the makeComplex function took app 10 % of the
|
||||
// overall processing time.
|
||||
// Table lookup was the answer, accuracy of the table increases
|
||||
// by making the table longer
|
||||
// since we are dealing with non int values, choosing the length
|
||||
// requires attention
|
||||
int dd = (int)(-IntegAbsPhaseVector [index] * GRANULARITY +
|
||||
TABLE_SIZE / 2);
|
||||
Complex fftBin = fftBinRaw * compTable [dd];
|
||||
// Get the phase (real and absolute)
|
||||
DABFLOAT re = real (fftBin);
|
||||
DABFLOAT im = imag (fftBin);
|
||||
if (re < 0)
|
||||
re = -re;
|
||||
if (im < 0)
|
||||
im = -im;
|
||||
Complex fftBin_at_1 = Complex (re, im);
|
||||
DABFLOAT binAbsLevel = jan_abs (fftBin_at_1);
|
||||
DABFLOAT phaseError = arg (fftBin_at_1) - M_PI_4;
|
||||
IntegAbsPhaseVector [index] =
|
||||
(1 - ALPHA) * IntegAbsPhaseVector [index] + ALPHA * phaseError;
|
||||
limit_symmetrically (IntegAbsPhaseVector [index],
|
||||
RAD_PER_DEGREE * (DABFLOAT)9.9);
|
||||
|
||||
//
|
||||
// When trying alternative decoder implementations
|
||||
// as implemented in DABstar by Rolf Zerr (aka old-dab) and
|
||||
// Thomas Neder (aka) Tomneda, I wanted to do some investigation
|
||||
// to get actual figures.
|
||||
// The different decoders were tested with an old file
|
||||
// with a recording of a poor signal, that ran for (almost) exact
|
||||
// two minutes from the start, and the BER results were accumulated
|
||||
// to get a more or less reliable answer.
|
||||
// It turned out that the major effect on the decoding quality
|
||||
// was with the phase shifting as done above.
|
||||
// With that setting there turned out to be a marginal difference
|
||||
// between decoders 1 and decoder 4,
|
||||
// the other two decoders 2 and 3 performed
|
||||
// slightly less (roughly speaking app 740000 repairs by
|
||||
// decoder 1 and 4, and 746000 by decoders 2 and 3).
|
||||
// So, we have chosen decoders 1 (most simple one) and 4 (log likelihood)
|
||||
// as decoders here.
|
||||
// the contributions of Rolf Zerr (aka OldDab) and
|
||||
// Thomas Neder (aka tomneda) for their decoders is greatly acknowledged
|
||||
//
|
||||
DABFLOAT stdDev = phaseError * phaseError;
|
||||
stdDevVector [index] =
|
||||
compute_avg (stdDevVector [index], stdDev, ALPHA);
|
||||
//
|
||||
meanLevelVector [index] =
|
||||
compute_avg (meanLevelVector[index],
|
||||
binAbsLevel, ALPHA);
|
||||
meanPowerVector [index] =
|
||||
compute_avg (meanPowerVector [index],
|
||||
binAbsLevel * binAbsLevel, ALPHA);
|
||||
DABFLOAT meanLevelPerBin = meanLevelVector [index] / sqrt (2);
|
||||
|
||||
// x distance to reference point
|
||||
DABFLOAT x_distance =
|
||||
abs (real (fftBin)) - meanLevelPerBin;
|
||||
// y distance to reference point
|
||||
DABFLOAT y_distance =
|
||||
abs (imag (fftBin)) - meanLevelPerBin;
|
||||
|
||||
DABFLOAT sigmaSq = x_distance * x_distance +
|
||||
y_distance * y_distance;
|
||||
meanSigmaSqVector [index] =
|
||||
compute_avg (meanSigmaSqVector [index], sigmaSq, ALPHA);
|
||||
|
||||
DABFLOAT signalPower = meanPowerVector [index] - nullPower;
|
||||
|
||||
if (signalPower <= 0.0f)
|
||||
signalPower = 0.1f;
|
||||
|
||||
DABFLOAT snr = signalPower / nullPower;
|
||||
DABFLOAT ff = meanLevelVector [index] /
|
||||
meanSigmaSqVector [index];
|
||||
ff /= 1 / snr + 2;
|
||||
|
||||
DABFLOAT weight_r;
|
||||
DABFLOAT weight_i;
|
||||
Complex R1;
|
||||
switch (decoder) {
|
||||
default:
|
||||
case DECODER_1:
|
||||
R1 = fftBin;
|
||||
softbits [i]
|
||||
= - real (R1) / binAbsLevel * MAX_VITERBI;
|
||||
softbits [carriers + i]
|
||||
= - imag (R1) / binAbsLevel * MAX_VITERBI;
|
||||
break;
|
||||
case DECODER_2:
|
||||
R1 = normalize (fftBin) * ff *
|
||||
(DABFLOAT)(sqrt (jan_abs (fftBin) * jan_abs (phaseReference [index])));
|
||||
weight_r = weight_i = -100 / meanValue;
|
||||
softbits [i] = (int16_t)(real (R1) * weight_r);
|
||||
softbits [carriers + i] = (int16_t)(imag (R1) * weight_i);
|
||||
break;
|
||||
}
|
||||
|
||||
sum += jan_abs (R1);
|
||||
} // end of decode loop
|
||||
|
||||
meanValue = sum / carriers;
|
||||
#endif
|
||||
// From time to time we show the constellation of symbol 2.
|
||||
if (blkno == 2) {
|
||||
if (++cnt > repetitionCounter) {
|
||||
DABFLOAT maxAmp = 0;
|
||||
for (int j = -carriers / 2; j < carriers / 2; j ++)
|
||||
if (j != 0)
|
||||
if (jan_abs (fft_buffer [(T_u + j) % T_u]) > maxAmp)
|
||||
maxAmp = jan_abs (fft_buffer [(T_u + j) % T_u]);
|
||||
Complex displayVector [carriers];
|
||||
|
||||
if (iqSelector == SHOW_RAW) {
|
||||
for (int j = 0; j < carriers; j ++)
|
||||
displayVector [j] =
|
||||
fft_buffer [(T_u - carriers / 2 - 1 + j) % T_u] / maxAmp;
|
||||
}
|
||||
else {
|
||||
for (int j = 1; j < carriers; j ++) {
|
||||
displayVector [j] =
|
||||
conjVector [T_u / 2 - carriers / 2 + j] / maxAmp;
|
||||
}
|
||||
}
|
||||
iqBuffer -> putDataIntoBuffer (displayVector, carriers);
|
||||
|
||||
float freqOffset = compute_frequencyOffset (fft_buffer. data (),
|
||||
phaseReference. data ());
|
||||
if (devBuffer != nullptr) {
|
||||
float tempVector [carriers];
|
||||
for (int i = 0; i < carriers; i ++) {
|
||||
tempVector [i] =
|
||||
stdDevVector [(T_u - carriers / 2 + i) % T_u];
|
||||
tempVector [i] = tempVector [i] / M_PI * 180.0;
|
||||
}
|
||||
|
||||
devBuffer -> putDataIntoBuffer (tempVector, carriers);
|
||||
show_stdDev (carriers);
|
||||
}
|
||||
|
||||
showIQ (carriers);
|
||||
float Quality = computeQuality (conjVector. data ());
|
||||
float timeOffset = compute_timeOffset (fft_buffer. data (),
|
||||
phaseReference. data ());
|
||||
// float freqOffset = compute_frequencyOffset (fft_buffer. data (),
|
||||
// phaseReference. data ());
|
||||
show_quality (Quality, timeOffset, freqOffset);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (phaseReference. data(), fft_buffer. data (),
|
||||
T_u * sizeof (Complex));
|
||||
}
|
||||
|
||||
//
|
||||
// While DAB symbols do not carry pilots, it is known that
|
||||
// arg (carrier [i, j] * conj (carrier [i + 1, j])
|
||||
// should be K * M_PI / 4, (k in {1, 3, 5, 7}) so basically
|
||||
// carriers in decoded symbols can be used as if they were pilots
|
||||
//
|
||||
// so, with that in mind we experiment with formula 5.39
|
||||
// and 5.40 from "OFDM Baseband Receiver Design for Wireless
|
||||
// Communications (Chiueh and Tsai)"
|
||||
float ofdmDecoder::compute_timeOffset (Complex *r, Complex *v) {
|
||||
Complex sum = Complex (0, 0);
|
||||
|
||||
for (int i = -carriers / 2; i < carriers / 2; i += 6) {
|
||||
int index_1 = i < 0 ? i + T_u : i;
|
||||
int index_2 = (i + 1) < 0 ? (i + 1) + T_u : (i + 1);
|
||||
Complex s = r [index_1] * conj (v [index_2]);
|
||||
s = Complex (abs (real (s)), abs (imag (s)));
|
||||
Complex leftTerm = s * conj (Complex (abs (s) / sqrt (2),
|
||||
abs (s) / sqrt (2)));
|
||||
s = r [index_2] * conj (v [index_2]);
|
||||
s = Complex (abs (real (s)), abs (imag (s)));
|
||||
Complex rightTerm = s * conj (Complex (abs (s) / sqrt (2),
|
||||
abs (s) / sqrt (2)));
|
||||
sum += conj (leftTerm) * rightTerm;
|
||||
}
|
||||
|
||||
return arg (sum);
|
||||
}
|
||||
//
|
||||
// Ideally, the processed carrier should have a value
|
||||
// equal to (2 * k + 1) * PI / 4
|
||||
// The offset is a measure of the frequency "error"
|
||||
float ofdmDecoder::compute_frequencyOffset (Complex *r, Complex *c) {
|
||||
Complex theta = Complex (0, 0);
|
||||
static float vv = 0;
|
||||
|
||||
for (int i = - carriers / 2; i < carriers / 2; i += 6) {
|
||||
int index = i < 0 ? i + T_u : i;
|
||||
Complex val = r [index] * conj (c [index]);
|
||||
val = Complex (abs (real (val)), abs (imag (val)));
|
||||
theta += val * Complex (1, -1);
|
||||
}
|
||||
|
||||
float uu = arg (theta) / (2 * M_PI) * SAMPLERATE / T_u;
|
||||
vv = 0.9 * vv + 0.1 * abs (uu);;
|
||||
return vv;
|
||||
}
|
||||
|
||||
float ofdmDecoder::compute_clockOffset (Complex *r, Complex *v) {
|
||||
float offsa = 0;
|
||||
int offsb = 0;
|
||||
|
||||
for (int i = - carriers / 2; i < carriers / 2; i += 6) {
|
||||
int index = i < 0 ? (i + T_u) : i;
|
||||
int index_2 = i + carriers / 2;
|
||||
Complex a1 =
|
||||
Complex (abs (real (r [index])),
|
||||
abs (imag (r [index])));
|
||||
Complex a2 =
|
||||
Complex (abs (real (v [index])),
|
||||
abs (imag (v [index])));
|
||||
float s = abs (arg (a1 * conj (a2)));
|
||||
offsa += index * s;
|
||||
offsb += index_2 * index_2;
|
||||
}
|
||||
|
||||
float sampleClockOffset =
|
||||
offsa / (2 * M_PI * (float)T_s/ T_u * offsb);
|
||||
|
||||
return sampleClockOffset;
|
||||
}
|
||||
|
||||
void ofdmDecoder::handle_iqSelector () {
|
||||
if (iqSelector == SHOW_RAW)
|
||||
iqSelector = SHOW_DECODED;
|
||||
else
|
||||
iqSelector = SHOW_RAW;
|
||||
}
|
||||
|
||||
void ofdmDecoder::handle_decoderSelector (int decoder) {
|
||||
this -> decoder = decoder;
|
||||
}
|
||||
|
@@ -1921,48 +1921,10 @@ bool RadioInterface::eventFilter (QObject *obj, QEvent *event) {
|
||||
theEnsembleHandler -> selectCurrentItem ();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// if (theEnsembleHandler -> hasFocus ())
|
||||
// fprintf (stderr, "ensembleHandler\n");
|
||||
// else
|
||||
// if (configHandler_p -> hasFocus ())
|
||||
// fprintf (stderr, "Config handler\n");
|
||||
// else
|
||||
// if (techWindow_p -> hasFocus ())
|
||||
// fprintf (stderr, "techWindow\n");
|
||||
// else
|
||||
// fprintf (stderr, "focus elsewhere\n");
|
||||
if (keyEvent -> key () == Qt::Key_F1) {
|
||||
theEnsembleHandler -> activateWindow ();
|
||||
theEnsembleHandler -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (keyEvent -> key () == Qt::Key_F2) {
|
||||
configHandler_p -> activateWindow ();
|
||||
configHandler_p -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (keyEvent -> key () == Qt::Key_F3) {
|
||||
techWindow_p -> activateWindow ();
|
||||
techWindow_p -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (keyEvent -> key () == Qt::Key_F4) {
|
||||
// theSCANHandler. show ();
|
||||
// theSCANHandler. activateWindow ();
|
||||
// theSCANHandler. setFocus ();
|
||||
this -> activateWindow ();
|
||||
this -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else // handling function keys
|
||||
if (handle_keyEvent (keyEvent -> key ()))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
// An option is to click - right hand mouse button - on a
|
||||
// service in the scanlist in order to add it to the
|
||||
// list of favorites
|
||||
@@ -4813,6 +4775,59 @@ void RadioInterface::journalineData (QByteArray data,
|
||||
|
||||
|
||||
void RadioInterface::focusInEvent (QFocusEvent *evt) {
|
||||
fprintf (stderr, "In focus now\n");
|
||||
}
|
||||
//
|
||||
// This function is called whenever a key is touched
|
||||
// that is not the return key
|
||||
bool RadioInterface::handle_keyEvent (int theKey) {
|
||||
switch (theKey) {
|
||||
case Qt::Key_F1:
|
||||
theEnsembleHandler -> activateWindow ();
|
||||
theEnsembleHandler -> setFocus ();
|
||||
return true;
|
||||
|
||||
case Qt::Key_F2:
|
||||
configHandler_p -> activateWindow ();
|
||||
configHandler_p -> setFocus ();
|
||||
return true;
|
||||
|
||||
case Qt::Key_F3:
|
||||
techWindow_p -> activateWindow ();
|
||||
techWindow_p -> setFocus ();
|
||||
return true;
|
||||
|
||||
case Qt::Key_F4:
|
||||
this -> activateWindow ();
|
||||
this -> setFocus ();
|
||||
return true;
|
||||
|
||||
case Qt::Key_F6:
|
||||
if (theEnsembleHandler -> hasFocus ()) {
|
||||
this -> activateWindow ();
|
||||
this -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (this -> hasFocus ()) {
|
||||
configHandler_p -> activateWindow ();
|
||||
configHandler_p -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (configHandler_p -> hasFocus ()) {
|
||||
techWindow_p -> activateWindow ();
|
||||
techWindow_p -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if (techWindow_p -> hasFocus ()) {
|
||||
theEnsembleHandler -> activateWindow ();
|
||||
theEnsembleHandler -> setFocus ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -452,6 +452,8 @@ private:
|
||||
|
||||
void announcement_start (uint16_t, uint16_t);
|
||||
void announcement_stop ();
|
||||
|
||||
bool handle_keyEvent (int);
|
||||
//
|
||||
signals:
|
||||
void select_ensemble_font ();
|
||||
|
Reference in New Issue
Block a user