1
/***************************************************************************
2
qpskdemodulator.cpp - description
5
copyright : (C) 2001 by Volker Schroer
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
15
* based on the work of Moe Wheatly, AE4JY *
16
***************************************************************************/
18
#include "qpskdemodulator.h"
20
// phase wraparound correction table for viterbi decoder
21
const double AngleTbl1[4] = { M_PI_3_2, 0.0, M_PI/2.0, M_PI};
22
const double AngleTbl2[4] = { M_PI_3_2, PI2, M_PI/2.0, M_PI};
26
QPskDemodulator::QPskDemodulator():CPskDemodulator()
30
ViterbiDecode( M_PI_3_2); // init the Viterbi decoder
35
QPskDemodulator::~QPskDemodulator()
38
void QPskDemodulator::DecodeSymbol(double_complex newsamp)
43
//unsigned char ch = 0;
50
m_I1 = m_I0; //form the multi delayed symbol samples
52
m_I0 = newsamp.real();
53
m_Q0 = newsamp.imag();
54
// calculates difference angle for QPSK, BPSK, and IQPSK decoding
55
//create vector whose angle is the difference angle by multiplying the
56
// current smaple by the complex conjugate of the previous sample.
57
//swap I and Q axis to keep away from the +/-Pi discontinuity and
58
// add Pi to make make range from 0 to 2Pi.
59
// 180 deg phase changes center at Pi/4
60
// 0 deg phase changes center at 3Pi/2
61
// +90 deg phase changes center at 2Pi or 0
62
// -90 deg phase changes center at Pi
64
angle = M_PI + atan2( (m_I1*m_I0 + m_Q1*m_Q0),
65
(m_I1*m_Q0 - m_I0*m_Q1)); //QPSK or BPSK
69
bit = ViterbiDecode( angle);
71
if( (bit==0) && m_LastBitZero ) //if character delimiter
75
m_BitAcc >>= 2; //get rid of last zero and one
77
ch = m_VaricodeDecTbl[m_BitAcc];
89
m_LastBitZero = false;
91
if(GotChar && (ch!=0) )
97
emit setFastSquelch(true);
103
if (m_OffCount++ > 20)
104
emit setFastSquelch(false);
110
///////////////////////////////////////////////////////////////////////
111
// Soft-decision Viterbi decoder function.
112
///////////////////////////////////////////////////////////////////////
113
bool QPskDemodulator::ViterbiDecode( double newangle)
117
int bitestimates[32];
120
const double* pAngleTbl;
121
min = 1.0e100; // make sure can find a minimum value
122
//alternative soft decision method using angle differences
124
if( newangle >= PI2/2 ) //deal with ambiguity at +/- 2PI
125
pAngleTbl = AngleTbl2; // by using two different tables
127
pAngleTbl = AngleTbl1;
128
for(i = 0; i < 32; i++) // calculate all possible distances
129
{ //lsb of 'i' is newest bit estimate
130
pathdist[i] = m_SurvivorStates[i / 2].Pathdistance +
131
fabs(newangle - pAngleTbl[ ConvolutionCodeTable[i] ]);
132
if(pathdist[i] < min) // keep track of minimum distance
134
// shift in newest bit estimates
135
bitestimates[i] = ((m_SurvivorStates[i / 2].BitEstimates) << 1) + (i & 1);
138
for(i = 0; i < 16; i++) //compare path lengths with the same end state
139
// and keep only the smallest path in m_SurvivorStates[].
141
if(pathdist[i] < pathdist[16 + i])
143
m_SurvivorStates[i].Pathdistance = pathdist[i] - min;
144
m_SurvivorStates[i].BitEstimates = bitestimates[i];
148
m_SurvivorStates[i].Pathdistance = pathdist[16 + i] - min;
149
m_SurvivorStates[i].BitEstimates = bitestimates[16 + i];
153
for(i = 0; i < 16; i++) // find if more ones than zeros at bit 20 position
154
ones += (m_SurvivorStates[i].BitEstimates&(1L << 20));
155
if( ones == (8L << 20 ) )
156
return ( rand() & 0x1000 ); //if a tie then guess
158
return(ones > (8L << 20) ); //else return most likely bit value
161
//////////////////////////////////////////////////////////////////////
162
// Calculate signal quality based on the statistics of the phase
163
// difference angle. The more dispersion of the "0" and "180" degree
164
// phase shifts, the worse the signal quality. This information is used
165
// to activate the squelch control. If 20 consecutive "180" degree shifts
166
// occur, the squelch is forced on, and if 20 consecutive "0" degree
167
// shifts occur, the squelch is forced off quickly.
168
//////////////////////////////////////////////////////////////////////
170
void QPskDemodulator::CalcQuality( double angle )
177
angle = angle - M_PI_2;
181
temp = fmod(angle,M_PI_2);
191
m_DevAve =0.47 * ave1 + 0.46 * ave2 + 0.03 *temp;
195
temp=100.-250.0*m_DevAve;
196
emit setSquelchValue((int)temp);