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

VrSyncCorr.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 00018 #ifndef _VrSYNCCORR_H_ 00019 #define _VrSYNCCORR_H_ 00020 00021 #define SIZE 4096 00022 #define MAX_RESULTS_SIZE 10000 00023 00024 #include <VrDecimatingSigProc.h> 00025 #include <fstream> 00026 #if defined (ENABLE_MMX) 00027 #include <VrMMX.h> 00028 #endif 00029 00030 00031 // ******************************************************** 00032 00033 struct corr_result { 00034 float value; 00035 VrSampleIndex index; 00036 }; 00037 00038 00039 template<class iType> 00040 class VrSyncCorr : public VrDecimatingSigProc<iType,char> { 00041 protected: 00042 00043 float result, old_result, *sqr, weight_sign; 00044 u_int first, first_high, first_low, current, mask; 00045 int step_size, skip, differential_offset; 00046 int low_interval, high_interval, best_period; 00047 int corr_count, pattern_length, pattern_count, corr_init; 00048 int window_size, excess_samples, numTaps, struct_size; 00049 float freq; 00050 virtual void get_filter_output(iType*,int,int,VrComplex*,int); 00051 VrComplex *filter_results; 00052 VrComplex phase_corr_incr, phase_bump, phase_offset; 00053 VrComplex* filter_taps; 00054 #if defined (ENABLE_MMX) 00055 mmxTaps* processedTaps; //Precomputed constants, shifted four times 00056 #endif 00057 00058 public: 00059 virtual void set_window(int w) {window_size = w;} 00060 virtual void set_period(int p) {best_period = p;} 00061 virtual void increment_input_ptr(int i) {differential_offset+=i;} 00062 virtual const char *name() { return "VrSyncCorr"; } 00063 virtual int forecast(VrSampleRange output, 00064 VrSampleRange inputs[]); 00065 virtual int work(VrSampleRange output, void *o[], 00066 VrSampleRange inputs[], void *i[]); 00067 virtual void initialize(); 00068 VrSyncCorr(int, int, int, float); 00069 ~VrSyncCorr(); 00070 }; 00071 00072 00073 00074 /* Correlator that looks for "low-high-low" shape in symbol sequence 00075 * 00076 * |------------| 00077 * | | 00078 * | | 00079 * | | 00080 * |--------------------------------| |----------| 00081 * 00082 * ^ ^ ^ 00083 * | Initialize | Produce output values | OFF 00084 * 00085 * |--pattern length-| <---- desired number of outputs ---->| 00086 * 00087 * 00088 * |<-- corr_init -->| 00089 * |<----- corr_on --------------------------------------->| 00090 00091 */ 00092 00093 template<class iType> int 00094 VrSyncCorr<iType>::work(VrSampleRange output, void *ao[], 00095 VrSampleRange inputs[], void *ai[]) 00096 { 00097 iType **i = (iType **)ai; 00098 char **o = (char **)ao; 00099 struct corr_result best, *out_ptr; 00100 int size = output.size; 00101 float x, y, sign, *sqr; 00102 int current, output_time, step_size, number_outputs; 00103 float max, min; 00104 VrSampleIndex max_loc, min_loc; 00105 VrSampleIndex offset = inputs[0].index; 00106 00107 iType *input_ptr; 00108 VrComplex *f_results; 00109 00110 input_ptr = i[0]; 00111 out_ptr = (struct corr_result*) o[0]; 00112 f_results = filter_results; 00113 00114 00115 output_time = 0; // I think that this only affects phase -> doesn't matter 00116 number_outputs = window_size * size / step_size + 5; 00117 get_filter_output(input_ptr, output_time, number_outputs, f_results, step_size); 00118 00119 while(size-->0) { 00120 00121 x = real(*f_results); 00122 y = imag(*f_results++); 00123 sign = (float) (2 * (x>0.0))-1; 00124 00125 sqr[(current)&mask] = sign*(x*x + y*y); 00126 00127 if (corr_init) { // initialize array used for correlation 00128 00129 pattern_count++; 00130 if (pattern_count == 1){ 00131 old_result = 0.0; 00132 weight_sign = -1.0; 00133 max = 0.0; 00134 min = 0.0; 00135 } 00136 if (pattern_count == low_interval + 1){ 00137 weight_sign = 1.0; 00138 } 00139 if (pattern_count == low_interval + high_interval + 1) { 00140 weight_sign = -1.0; 00141 } 00142 00143 old_result += weight_sign * sign * (x*x + y*y); 00144 current++; 00145 00146 if (pattern_count == pattern_length){ 00147 pattern_count = 0; 00148 corr_init = 0; 00149 first = current-pattern_length; 00150 first_high = first + low_interval; 00151 first_low = first_high + high_interval; 00152 } 00153 } else { // now start producing output values 00154 00155 result = old_result; 00156 00157 result += sqr[(first++)&mask]; 00158 result -= (2 * sqr[(first_high++)&mask]); 00159 result += (2 * sqr[(first_low++)&mask]); 00160 result -= sqr[(current)&mask]; 00161 00162 if (result > max) { 00163 max = result; 00164 max_loc = (current - (pattern_length/2)) * step_size;// middle of footprint 00165 } 00166 if (result < min) { 00167 min = result; 00168 min_loc = (current - (pattern_length/2)) * step_size;// middle of footprint 00169 } 00170 00171 current++; 00172 00173 old_result = result; 00174 } 00175 if (max >= -min) { //highest magnitude was positive 00176 best.value = max; 00177 best.index = max_loc + offset; 00178 } 00179 else { 00180 best.value = min; 00181 best.index = min_loc + offset; 00182 } 00183 } 00184 *out_ptr++ = best; 00185 return output.size; 00186 } 00187 00188 template<class iType> void 00189 VrSyncCorr<iType>::get_filter_output(iType *inputArray, int output_time, 00190 int num_outputs, VrComplex *result_array, int decimation) 00191 { 00192 VrComplex result = 0; 00193 unsigned int size = num_outputs; 00194 00195 VrComplex phase_correction; 00196 phase_correction=pow(phase_corr_incr, output_time) * phase_offset; 00197 00198 for (;size>0;size--,inputArray+=decimation) { 00199 result = 0; 00200 00201 #if defined (ENABLE_MMX) 00202 if(processedTaps->mmxReady()) 00203 result = processedTaps->mmxCVDProduct(inputArray); 00204 else 00205 #endif 00206 { 00207 VrComplex *taps_tmp = filter_taps; 00208 for (int j=0; j < numTaps; j++) 00209 result += taps_tmp[j] * inputArray[j]; 00210 } 00211 00212 phase_correction *= phase_corr_incr; 00213 result *= phase_correction; 00214 *result_array++ = result; 00215 } 00216 } 00217 00218 template<class iType> 00219 VrSyncCorr<iType>::VrSyncCorr(int dec, int step, int num_taps, float center_freq) 00220 :VrDecimatingSigProc<iType,char>(1,dec) 00221 { 00222 numTaps = num_taps; 00223 freq = center_freq; 00224 step_size = step; 00225 struct_size = sizeof(struct corr_result); 00226 00227 } 00228 00229 template<class iType> int 00230 VrSyncCorr<iType>::forecast(VrSampleRange output, 00231 VrSampleRange inputs[]) { 00232 /* dec:1 ratio with history */ 00233 for(unsigned int i=0;i<numberInputs;i++) { 00234 inputs[i].index=output.index*best_period+ differential_offset; /* ! do not subtract history ! */ 00235 inputs[i].size=output.size*decimation + window_size + 2*excess_samples; 00236 //jca printf ("VrSyncCorr forecast[i] index %lld size %ld output.index %lld dec %d off %d\n", inputs[i].index, inputs[i].size, 00237 //jca output.index, decimation, differential_offset); 00238 } 00239 return 0; 00240 } 00241 00242 00243 template<class iType> 00244 void VrSyncCorr<iType>::initialize() 00245 { 00246 00247 sqr = new float[SIZE]; 00248 mask = (u_int) (SIZE-1); 00249 differential_offset = 0; 00250 excess_samples = 0; 00251 00252 00253 /* template for sync pulse is [2x low + 4x high + 2x low] symbols */ 00254 00255 first = 0; 00256 first_high = (int) (2.0 * nominal_samples_per_symbol / (float) step_size); 00257 first_low = (int) (6.0 * nominal_samples_per_symbol / (float) step_size); 00258 00259 current = 0; 00260 corr_init = 1; 00261 corr_count = 0; 00262 00263 pattern_length = (int) (8.0 * nominal_samples_per_symbol / (float) step_size)/2*2;//even 00264 excess_samples = pattern_length / 2 * step_size; 00265 pattern_count = 0; 00266 00267 filter_results = new VrComplex[MAX_RESULTS_SIZE]; 00268 history = excess_samples; 00269 00270 00271 window_size = source_rate / sync_rate / 10; 00272 best_period = (int) (nominal_samples_per_symbol * symbols_per_period); 00273 00274 } 00275 00276 template<class iType> 00277 VrSyncCorr<iType>::~VrSyncCorr() 00278 { 00279 delete sqr; 00280 delete filter_results; 00281 } 00282 00283 #endif 00284 00285 00286 00287 00288 00289 00290 00291 00292

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