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

VrPulseCorrelator.h

Go to the documentation of this file.
00001 /* -*- Mode: c++ -*- 00002 * 00003 * Copyright 1997 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 _VRPULSECORRELATOR_H_ 00019 #define _VRPULSECORRELATOR_H_ 00020 00021 #include <VrDecimatingSigProc.h> 00022 00023 #if defined (ENABLE_MMX) 00024 #include <VrMMX.h> 00025 #endif 00026 00027 /* 00028 This filter is a version of the complex FIR filter that is designed 00029 to be "digital aware". It tracks the symbol boundaries and 00030 (eventually) will be able to provide any pattern of output samples 00031 in each symbol period. 00032 00033 The "digital aware" portions only support a single output stream 00034 now, but it seems feasible to make this filter supoort multiple 00035 outputs. 00036 */ 00037 // ******************************************************** 00038 00039 #define PRECISION_BITS 12 00040 00041 template<class iType> 00042 class VrPulseCorrelator : public VrDecimatingSigProc<iType,VrComplex> { 00043 protected: 00044 int num_taps, bump; 00045 int shift_bits, max_sample_count, sample_count, high_res, middle_offset, samples_per_symbol; 00046 int *all_done, high_res_start, high_res_waiting; 00047 VrComplex* taps; 00048 VrComplex phase_correction, phase_corr_incr, *over_sampled_result, small_corr_incr; 00049 long time; 00050 int symbol_boundary, symbol_period, pointer_incr, old_output_loc, new_output_loc; 00051 float center_freq, gain; 00052 void buildFilter_complex(); 00053 #if defined (ENABLE_MMX) 00054 mmxTaps* processedTaps; //Precomputed constants, shifted four times 00055 #endif 00056 public: 00057 virtual const char *name() { return "VrPulseCorrelator"; } 00058 virtual int work(VrSampleRange output, VrComplex *o[], 00059 VrSampleRange inputs[], iType *i[]); 00060 virtual void initialize(); 00061 int setCenter_Freq(float); 00062 int setNumber_Taps(int); 00063 00064 float getSymbol_Period(); 00065 int setSymbol_Period(float); 00066 int setSymbol_Timing(float); 00067 void start_oversampling(int, int,int,VrComplex*,int*); 00068 VrPulseCorrelator(int n, float d, const int t[], const float f[], 00069 const float g[]); 00070 VrPulseCorrelator(float d, int t,float f, float g); 00071 ~VrPulseCorrelator(); 00072 int version() { return 0; }; 00073 }; 00074 00075 template<class iType> int 00076 VrPulseCorrelator<iType>::work(VrSampleRange output, VrComplex *o[], 00077 VrSampleRange inputs[], iType *i[]) 00078 { 00079 unsigned int size = output.size; 00080 VrComplex result = 0; 00081 int output_offset = 0; 00082 00083 cout << " enter Work in filter" << endl; 00084 for (int i=0;i<size;) { 00085 00086 //cout << pointer_incr << endl; 00087 // symbol_boundary += symbol_period; 00088 00089 if (high_res_waiting & (high_res_start-- == 0)) { 00090 high_res = 1; 00091 high_res_waiting = 0; 00092 } 00093 if (high_res) { 00094 if (sample_count == 1) symbol_boundary += symbol_period; 00095 if (sample_count % (1 << shift_bits) == 0) symbol_boundary += symbol_period; 00096 output_offset = (sample_count % (1 << shift_bits)) * (symbol_period >> shift_bits); 00097 new_output_loc = (symbol_boundary + output_offset) >> PRECISION_BITS; 00098 } else { 00099 symbol_boundary += symbol_period; 00100 new_output_loc = (symbol_boundary + (symbol_period/2)) >> PRECISION_BITS; 00101 } 00102 00103 pointer_incr = new_output_loc - old_output_loc; 00104 if (pointer_incr <0) { 00105 // cout << pointer_incr << endl; 00106 pointer_incr += (1 << (32-PRECISION_BITS)); 00107 } 00108 //cout << "i: " << i << " sample_count: " << sample_count << " incr: " << pointer_incr << endl; 00109 old_output_loc = new_output_loc; 00110 00111 if (bump != 0) { 00112 symbol_boundary += bump; 00113 cout << "Bumping pointer " << (float) (bump) / (float)(1<<PRECISION_BITS) << endl; 00114 bump =0; 00115 } 00116 00117 result = 0; 00118 00119 //make input pointer local 00120 iType *inputArray = i[0]+history+(-num_taps+1); 00121 00122 #if defined (ENABLE_MMX) 00123 if(processedTaps->mmxReady()) 00124 result = processedTaps->mmxCVDProduct(inputArray); 00125 else { 00126 VrComplex *taps_tmp = taps; 00127 for (int j=0; j < num_taps; j++) 00128 result += taps_tmp[j] * inputArray[j]; 00129 } 00130 #else 00131 VrComplex *taps_tmp = taps; 00132 for (int j=0; j < num_taps; j++) 00133 result += taps_tmp[j] * inputArray[j]; 00134 #endif 00135 00136 // Perform phase correction (non-trivial only for freq-xlating filter) 00137 if (center_freq != 0.0) { 00138 if (high_res){ 00139 phase_correction *= small_corr_incr; 00140 } else { 00141 phase_correction *= phase_corr_incr; 00142 } 00143 result *= phase_correction; 00144 } 00145 if (high_res) { 00146 over_sampled_result[sample_count-1] = result; 00147 if ((sample_count - middle_offset) % samples_per_symbol == 0) { 00148 i++; 00149 *o[0]++ = result; 00150 } 00151 sample_count++; 00152 if (sample_count == max_sample_count) { 00153 sample_count = 1; 00154 high_res = 0; 00155 *all_done = 1; 00156 } 00157 } else /* not HIGH_RES */ { 00158 i++; 00159 *o[0]++ = result; 00160 } 00161 i[0] += pointer_incr; 00162 } 00163 cout << " leave Work in filter" << endl; 00164 return output.size; 00165 } 00166 00167 template<class iType> void 00168 VrPulseCorrelator<iType>::buildFilter_complex(){ 00169 int inSampFreq; 00170 int index; 00171 float N = num_taps, a=0.0; 00172 float M = N-1; /* filter Order */ 00173 00174 inSampFreq = getInputSamplingFrequencyN(0); 00175 00176 if (center_freq == 0.0){ 00177 00178 // Build Complex Filter => 00179 // produces a low-pass filter using a real Hamming window 00180 00181 for ( index=0 ; index < num_taps ; index++) { 00182 taps[index] = gain*VrComplex((0.54-0.46*cos(2*M_PI*index/(M)))); 00183 } 00184 } else { 00185 // Build composite Complex Filter => adds freq-shifting part 00186 a = 2*M_PI*center_freq / (float)inSampFreq; 00187 for ( index=0 ; index < num_taps ; index++) { 00188 00189 taps[index] = VrComplex(gain*cos(a*index)*(0.54-0.46*cos(2*M_PI*index/(M))), 00190 gain*(-1)*sin(a*index)*(0.54-0.46*cos(2*M_PI*index/(M)))); 00191 00192 } 00193 phase_corr_incr = VrComplex(cos(a*(float)decimation), 00194 (-1)*sin(a*(float)decimation)); 00195 } 00196 00197 a = a * ((float)(symbol_period) / (float)((int)1 << PRECISION_BITS)); 00198 VrComplex temp = VrComplex(cos(a),(-1)*sin(a)); 00199 phase_corr_incr = temp; 00200 00201 #if defined (ENABLE_MMX) 00202 if(processedTaps!=NULL) 00203 delete processedTaps; 00204 processedTaps=new mmxTaps(taps,num_taps); 00205 #endif 00206 } 00207 00208 template<class iType> 00209 VrPulseCorrelator<iType>::VrPulseCorrelator(float per,int t,float freq, float g) 00210 :VrDecimatingSigProc<iType,VrComplex>(1,(int) per) 00211 { 00212 00213 symbol_period = (int) (per * (float)(1 << PRECISION_BITS)); 00214 symbol_boundary = 0; 00215 old_output_loc = (symbol_period >>1) >> PRECISION_BITS; 00216 bump = 0; 00217 00218 00219 num_taps = t; 00220 phase_correction = VrComplex(1,0); 00221 phase_corr_incr = VrComplex(1,0); 00222 center_freq = freq; 00223 gain = g; 00224 #if defined (ENABLE_MMX) 00225 processedTaps=NULL; 00226 #endif 00227 } 00228 00229 template<class iType> 00230 void VrPulseCorrelator<iType>::initialize() 00231 { 00232 taps=new VrComplex[num_taps]; 00233 buildFilter_complex(); 00234 00235 //Set history 00236 int max_num_taps = num_taps; 00237 setHistory(max_num_taps); 00238 high_res_waiting = 0; 00239 } 00240 00241 template<class iType> 00242 int VrPulseCorrelator<iType>::setCenter_Freq(float cf) 00243 { 00244 center_freq = cf; 00245 buildFilter_complex(); 00246 return 1; 00247 } 00248 00249 template<class iType> 00250 int VrPulseCorrelator<iType>::setNumber_Taps(int numT) 00251 { 00252 num_taps = numT; 00253 delete taps; 00254 taps=new VrComplex[num_taps]; 00255 00256 //set history 00257 setHistory(num_taps); 00258 buildFilter_complex(); 00259 return 1; 00260 } 00261 00262 template<class iType> 00263 float VrPulseCorrelator<iType>::getSymbol_Period() 00264 { 00265 /* returns symbol period in seconds */ 00266 return (float)symbol_period /(float)(1 << PRECISION_BITS) / (float)getInputSamplingFrequencyN(0); 00267 } 00268 00269 template<class iType> 00270 int VrPulseCorrelator<iType>::setSymbol_Period(float period) 00271 { 00272 /* input symbol period in seconds -> converts to fractional number of samples*/ 00273 symbol_period = (int)(period * (float)(1 << PRECISION_BITS) * (float)getInputSamplingFrequencyN(0)); 00274 cout << " Set period to " << (double) symbol_period / (double)(1 << PRECISION_BITS) << endl; 00275 return 1; 00276 } 00277 00278 template<class iType> 00279 int VrPulseCorrelator<iType>::setSymbol_Timing(float fraction) 00280 { 00281 /* input fraction (FP) of symbol period for offset adjustment: (+) = 00282 advance boundary relative to sample stream, (-)= retard boundary */ 00283 bump = (int)( fraction * (float) symbol_period); 00284 return 1; 00285 } 00286 00287 template<class iType> 00288 void VrPulseCorrelator<iType>::start_oversampling(int N, int B, int wait, VrComplex *output_ptr, 00289 int *done_flag) 00290 { 00291 00292 /* this method sets up the filter to begin producing multiple 00293 outputs per symbol to allow the controlling (downstream) module 00294 to perform correlation to find a sync pulse to recover symbol 00295 timing 00296 00297 start in 'wait' symbols (wait = 0 => start with next symbol) 00298 2^B output samples per symbol period, N symbol periods 00299 */ 00300 00301 shift_bits = B; 00302 max_sample_count = N * (1 << shift_bits); 00303 high_res_start = wait; 00304 high_res_waiting = 1; 00305 sample_count = 1; 00306 high_res = 0; 00307 00308 over_sampled_result = output_ptr; 00309 middle_offset = (1 << (shift_bits-1))+1; 00310 samples_per_symbol = (1 << shift_bits); 00311 all_done = done_flag; 00312 *all_done = 0; 00313 00314 float arg = 2*M_PI*center_freq / (float)getInputSamplingFrequencyN(0); 00315 small_corr_incr = VrComplex(cos(arg*(float)symbol_period / (float)(1 << (PRECISION_BITS+B))), 00316 (-1)*sin(arg*(float)symbol_period / (float)(1 << PRECISION_BITS+B))); 00317 } 00318 00319 template<class iType> 00320 VrPulseCorrelator<iType>::~VrPulseCorrelator() 00321 { 00322 delete taps; 00323 #if defined (ENABLE_MMX) 00324 delete processedTaps; 00325 #endif 00326 } 00327 #endif

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