Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

VrComplexDemod.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- 00002 * 00003 * Copyright 1999 Massachusetts Institute of Technology 00004 * 00005 * Permission to use, copy, modify, distribute, and sell this software and its 00006 * documentation for any purpose is hereby granted without fee, provided that 00007 * the above copyright notice appear in all copies and that both that 00008 * copyright notice and this permission notice appear in supporting 00009 * documentation, and that the name of M.I.T. not be used in advertising or 00010 * publicity pertaining to distribution of the software without specific, 00011 * written prior permission. M.I.T. makes no representations about the 00012 * suitability of this software for any purpose. It is provided "as is" 00013 * without express or implied warranty. 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 // VrComplexDemod(VrGUILayout *arg_layout, VrPulse<char, char>*, float td, int s); 00054 VrComplexDemod(VrSyncCorr<char>*,int,float); 00055 // ~VrComplexDemod(); 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 // num = initial_sync_num_windows; 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 //disable phase recovery: point = point * VrComplex(real(est_theta), -imag(est_theta)); 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 } /* while ((size-- >0) & (remaining_symbols-- > 0) */ 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; // ow size = 0 00209 00210 } /* while (size-- > 0) */ 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 /* !EIGHT */ 00225 #define OUTER (1) 00226 #define INNER2 (slice > neg_threshold) 00227 #ifdef TWO 00228 #define MID (1) 00229 #define INNER (slice > 0) 00230 #else /* !TWO */ 00231 #define MID (slice > 0) 00232 #define INNER (slice > pos_threshold) 00233 #endif /* TWO */ 00234 #endif /* EIGHT */ 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 // cout << (int)(symbol); 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 // int number_of_windows = 10; 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 // extreme = window_max_ampl( current_ts, window_length); 00270 #if 0 00271 extreme = i[sync_input 00272 #endif 00273 current_ts += best_period + best_period/number_of_windows;// advance (100+X)% of a period 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 // float dummy; 00288 00289 // increment = (int)(getInputSamplingFrequencyN(0) * timeDuration); 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 //jca printf ("VrSyncCorr forecast[i] ts %lld size %ld output.index %lld dec %d off %d\n", inputs[i].index, inputs[i].size, 00323 //jca output.index, decimation, differential_offset); 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; /* filter Order */ 00339 00340 inSampFreq = (int)getInputSamplingFrequencyN(0); 00341 if (center_freq == 0.0){ 00342 // Build Complex Filter => 00343 // produces a low-pass filter using a real Hamming window 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 { // Build composite Complex Filter => adds freq-shifting part 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

Generated on Wed Aug 4 02:22:05 2004 for GNU Radio by doxygen 1.3.8