00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
#ifndef _VRCOMPLEXDEMOD_H_
00018
#define _VRCOMPLEXDEMOD_H_
00019
00020 #define SQR_HISTORY_OFFSET 20
00021
00022
#include <stdio.h>
00023
#include "VrHistoryProc.h"
00024
#include "VrGUI.h"
00025
00026
#if defined (ENABLE_MMX)
00027
#include <VrMMX.h>
00028
#endif
00029
00030
template<
class iType>
00031 class VrComplexDemod :
public VrHistoryProc<iType,VrComplex> {
00032
protected:
00033 VrSyncCorr<char>*
sync_ptr;
00034 float timeDuration,
slice,
sync_threshold;
00035 float pos_threshold,
high_pos_threshold,
low_pos_threshold;
00036 float neg_threshold,
high_neg_threshold,
low_neg_threshold;
00037 int size,
numTaps,
restart,
decimation;
00038 float min,
max,
center_freq,
corr_sign;
00039 int ready_for_syncs,
ready_for_max,
not_sync;
00040 int N,
flip,
flip_c,
plot,
plot_count,
symb_count,
symbol_sync;
00041 int sync_struct_size,
num;
00042
00043 int consec_sync,
remaining_symbols,
dropped_sync;
00044 int center_first,
center_second,
best_period;
00045 VrComplex sum,
old_conj, *
taps;
00046 VrComplex sqr_hist[2*
SQR_HISTORY_OFFSET], *
current_sqr, *
last_sqr;
00047 VrSampleIndex first_loc,
second_loc,
fresh_data_ts_1,
fresh_data_ts_2;
00048 VrSampleIndex sync_ts_offset,
data_ts_offset;
00049 struct corr_result best;
00050
void buildFilter_complex();
00051
00052
public:
00053
00054
VrComplexDemod(
VrSyncCorr<char>*,
int,
float);
00055
00056 virtual const char *
name() {
return "VrComplexDemod"; }
00057
virtual void initialize();
00058
virtual int forecast(
VrSampleRange output,
00059
VrSampleRange inputs[]);
00060
virtual int work(
VrSampleRange output,
void *o[],
00061
VrSampleRange inputs[],
void *i[]);
00062
00063
#if 0
00064
char symbol_decision(
float);
00065
#endif
00066
00067 };
00068
00069
template<
class iType>
int
00070 VrComplexDemod<iType>::work(
VrSampleRange output,
void *ao[],
00071
VrSampleRange inputs[],
void *ai[])
00072 {
00073
iType **i = (
iType **)ai;
00074
VrComplex **o = (
VrComplex **)ao;
00075
int size = output.
size;
00076
VrComplex point, est_theta;
00077
int window_length, period_length;
00078
struct corr_result input, *sync_input_ptr;
00079
float sync_fraction = 0.10;
00080
int req_consec_sync = 5;
00081
00082
00083 sync_input_ptr = (
struct corr_result *) i[sync_input];
00084
00085
#if 0
00086
if (
not_sync) {
00087
00088
00089
00090
if (!
ready_for_syncs) {
00091
00092
if (!
ready_for_max) {
00093 window_length = nominal_samples_per_period / (
float)
num;
00094 period_length = (
int) nominal_samples_per_period + 1 + window_length;
00095
00096
sync_ptr -> set_window(window_length);
00097
sync_ptr -> set_period(period_length);
00098
00099
fresh_data_ts_1 =
getMarkedWP();
00100
ready_for_max = 1;
00101
return 0;
00102 }
00103
00104
while (inputs[sync_input].
index <=
fresh_data_ts_1) {
00105 input = *sync_input_ptr++;
00106
sync_ts_offset++;
00107
return 0;
00108 }
00109
00110
max = 0.0;
00111
min = 0.0;
00112
while (
num-- > 0) {
00113
00114 input = *sync_input_ptr++;
00115
sync_ts_offset++;
00116
00117
if (input.
value >
max) {
00118
best.
value = input.
value;
00119
best.
index = input.
index;
00120 }
00121
if (input.
value <
min) {
00122
best.
value = input.
value;
00123
best.
index = input.
index;
00124 }
00125
return 0;
00126 }
00127
00128
if (
best.
value >= 0)
corr_sign = 1.0;
00129
if (
best.
value < 0)
corr_sign = -1.0;
00130
00131
sync_threshold = 0.90 *
best.
value;
00132
00133 window_length = (
int) (nominal_samples_per_period * sync_fraction);
00134 period_length = (
int) nominal_samples_per_period;
00135
00136
sync_ptr -> set_window(window_length);
00137
sync_ptr -> set_period(period_length);
00138
00139
fresh_data_ts_2 =
getMarkedWP();
00140
ready_for_syncs = 1;
00141
return 0;
00142 }
00143
00144
while (inputs[sync_input].
index <=
fresh_data_ts_2) {
00145 input = *sync_input_ptr++;
00146
sync_ts_offset++;
00147
return 0;
00148 }
00149
00150
while (
consec_sync < req_consec_sync) {
00151
00152 input = *sync_input_ptr++;
00153
sync_ts_offset++;
00154
00155
if (
corr_sign * input.
value >
sync_threshold) {
00156
consec_sync++;
00157
first_loc =
second_loc;
00158 second_loc = input.
index;
00159 }
00160
else {
00161
consec_sync=0;
00162
restart++;
00163 }
00164
if (
restart >= 2){
00165
restart = 0;
00166
sync_ptr -> increment_input_ptr(window_length + period_length);
00167 }
00168 }
00169
remaining_symbols = symbols_per_period;
00170
not_sync = 0;
00171
00172 }
00173
#endif
00174
while (size > 0) {
00175
00176
while ((size-- >0) & (
remaining_symbols-- > 0)) {
00177
00178 cout << size <<
" " <<
remaining_symbols << endl;
00179 point = *i[data_input]++;
00180 *
current_sqr = point * point;
00181 *(
current_sqr-
SQR_HISTORY_OFFSET) = point * point;
00182
sum =
sum + *
current_sqr - *(
current_sqr-
N);
00183
current_sqr++;
00184
if (
current_sqr ==
last_sqr)
current_sqr -=
SQR_HISTORY_OFFSET;
00185 est_theta =
sqrt (
sum /
sqrt((
real(
sum)*
real(sum) +
imag(sum)*
imag(sum))));
00186
if (
real(
old_conj*est_theta)<0)
flip = -
flip;
00187
old_conj =
VrComplex(
real(est_theta), -
imag(est_theta));
00188
00189
if (flip <0) point = -point;
00190
#if 0
00191
symbol = symbol_decision( constellation, point);
00192 o[0]++ = symbol;
00193
#endif
00194
*o[0]++ = point;
00195
00196 }
00197
00198
first_loc =
second_loc;
00199 input = *sync_input_ptr++;
00200
if (
corr_sign * input.
value >
sync_threshold) {
00201 second_loc = input.
index;
00202
dropped_sync = 0;
00203 }
else {
00204
dropped_sync++;
00205 second_loc =
first_loc +
best_period;
00206 }
00207
00208
if (
remaining_symbols <=0)
remaining_symbols = symbols_per_period;
00209
00210 }
00211
return output.
size;
00212 }
00213
00214
#if 0
00215
template <
class iType>
char
00216
VrComplexDemod<iType>::symbol_decision(
float slice)
00217 {
00218
char symbol;
00219
#ifdef EIGHT
00220
#define OUTER (slice > 0)
00221
#define MID (slice > pos_threshold)
00222
#define INNER (slice > high_pos_threshold)
00223
#define INNER2 (slice > low_pos_threshold)
00224
#else
00225
#define OUTER (1)
00226
#define INNER2 (slice > neg_threshold)
00227
#ifdef TWO
00228
#define MID (1)
00229
#define INNER (slice > 0)
00230
#else
00231
#define MID (slice > 0)
00232
#define INNER (slice > pos_threshold)
00233
#endif
00234
#endif
00235
if (
OUTER)
00236
if (
MID)
00237
if (
INNER)
00238 symbol = 0x00;
00239
else symbol = 0x01;
00240
else
00241
if (
INNER2)
00242 symbol = 0x02;
00243
else symbol = 0x03;
00244
else
00245
if (slice>neg_threshold)
00246
if (slice>high_neg_threshold) symbol = 0x04;
00247
else symbol = 0x05;
00248
else
00249
if (slice> low_neg_threshold) symbol = 0x06;
00250
else symbol = 0x07;
00251
00252
return symbol;
00253 }
00254
#endif
00255
00256
#if 0
00257
template <
class iType>
int
00258
VrComplexDemod<iType>::get_first_sync(
int number_of_windows,
int window_length) {
00259
00260
struct corr_result best, extreme;
00261
00262
int window_length =
best_period / number_of_windows+1;
00263
int num = number_of_windows;
00264
int current_ts = init_ts;
00265
00266 best.
value = 0.0;
00267
while (num-- > 0) {
00268
00269
00270
#if 0
00271
extreme = i[sync_input
00272
#endif
00273
current_ts +=
best_period +
best_period/number_of_windows;
00274
if(
abs(extreme.
value) >
abs(best.
value)) {
00275 best.
value = extreme.
value;
00276 best.
index = extreme.
index;
00277 }
00278
00279 }
00280
return best.
index;
00281 }
00282
#endif
00283
00284
template <
class iType>
void
00285 VrComplexDemod<iType>::initialize()
00286 {
00287
00288
00289
00290 history = 100;
00291
current_sqr = &
sqr_hist[
SQR_HISTORY_OFFSET];
00292
last_sqr =
current_sqr +
SQR_HISTORY_OFFSET;
00293
old_conj =
VrComplex();
00294
flip =1;
00295
plot_count =0;
00296
symb_count = 0;
00297 symbols_per_period = 50;
00298
00299
N = 5;
00300
for (
int i = 0; i<2*
SQR_HISTORY_OFFSET; i++)
00301 sqr_hist[i] = VrComplex();
00302
pos_threshold = 0.7;
00303
neg_threshold = -0.7;
00304
high_pos_threshold = 1.1;
00305
low_pos_threshold = 0.4;
00306
high_neg_threshold = -0.4;
00307
low_neg_threshold = -1.1;
00308
00309
decimation = (
int) nominal_samples_per_symbol;
00310 }
00311
00312
template<
class iType>
int
00313 VrComplexDemod<iType>::forecast(
VrSampleRange output,
00314
VrSampleRange inputs[]) {
00315
00316 inputs[sync_input].
index=(output.
index / symbols_per_period +
sync_ts_offset) *
sync_struct_size;
00317 inputs[sync_input].
size=(output.
size / symbols_per_period + 2) *
sync_struct_size;
00318
00319 inputs[data_input].
index=output.
index*
decimation +
data_ts_offset;
00320 inputs[data_input].
size=output.
size*
decimation + history - 1;
00321
00322
00323
00324
return 0;
00325 }
00326
template <
class iType>
00327 VrComplexDemod<iType>::VrComplexDemod(
VrSyncCorr<char> *ptr,
int num_taps,
float freq)
00328 :
VrHistoryProc<
iType,
VrComplex>(1), sync_ptr(ptr),numTaps(num_taps),center_freq(freq)
00329 {
00330
sync_struct_size =
sizeof(
struct corr_result);
00331 }
00332
00333
template<
class iType>
void
00334 VrComplexDemod<iType>::buildFilter_complex(){
00335
int inSampFreq;
00336
int index;
00337
float N =
numTaps;
00338
float M = N-1;
00339
00340 inSampFreq = (
int)
getInputSamplingFrequencyN(0);
00341
if (
center_freq == 0.0){
00342
00343
00344
for ( index=0 ; index < numTaps ; index++)
00345
taps[index] = gain*
VrComplex((0.54-0.46*
cos(2*M_PI*index/(M))));
00346 }
00347
else
00348 {
00349
float arg = 2*M_PI*
center_freq / (
float)inSampFreq;
00350
for ( index=0 ; index < numTaps ; index++)
00351
taps[index] =
VrComplex(gain*
cos(
arg*index)*(0.54-0.46*
cos(2*M_PI*index/(M))),
00352 gain*(-1)*
sin(
arg*index)*(0.54-0.46*
cos(2*M_PI*index/(M))));
00353 phase_corr_incr = VrComplex(
cos(
arg*(
float)symbol_period/(
float)(1<<
PRECISION_BITS)),
00354 (-1)*
sin(
arg*(
float)symbol_period/(
float)(1<<
PRECISION_BITS)));
00355 }
00356
#if defined (ENABLE_MMX)
00357
if(processedTaps!=
NULL)
00358
delete processedTaps;
00359 processedTaps=
new mmxTaps(
taps,numTaps);
00360
#endif
00361
}
00362
00363
00364
#endif
00365