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