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

VrSyncFilter.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 _VRSYNCFILTER_H_ 00019 #define _VRSYNCFILTER_H_ 00020 00021 #include <VrPulse.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 00040 #define PRECISION_BITS 12 00041 #define BOZO_HISTORY 1000 00042 00043 template<class iType> 00044 class VrSyncFilter : public VrPulse<iType,VrComplex> { 00045 protected: 00046 int *num_taps, num_ch, bump; 00047 VrComplex** taps; 00048 VrComplex *phase_corr_incr, phase_bump, *phase_offset; 00049 long time; 00050 long differential_offset, delta_differential_offset; 00051 int symbol_boundary, symbol_period, pointer_incr, old_output_loc, new_output_loc; 00052 float *center_freq, *gain; 00053 void buildFilter_complex(int); 00054 #if defined (ENABLE_MMX) 00055 mmxTaps** processedTaps; //Precomputed constants, shifted four times 00056 #endif 00057 public: 00058 virtual const char *name() { return "VrSyncFilter"; } 00059 virtual int work(VrSampleRange output, void *o[], 00060 VrSampleRange inputs[], void *i[]); 00061 virtual void initialize(); 00062 int setCenter_Freq(int, float); 00063 int setCenter_Freq(float); 00064 int setPhase_Offset(VrComplex); 00065 int setNumber_Taps(int,int); 00066 int setNumber_Taps(int); 00067 00068 float getSymbol_Period(); 00069 int setSymbol_Period(float); 00070 int setSymbol_Timing(float); 00071 void start_oversampling(int, int,int,VrComplex*,int*) {}; 00072 virtual int forecast(VrSampleRange output, 00073 VrSampleRange inputs[]); 00074 VrSyncFilter(int n, float d, const int t[], const float f[], 00075 const float g[]); 00076 VrSyncFilter(float d, int t,float f, float g); 00077 ~VrSyncFilter(); 00078 int version() { return 1; }; 00079 }; 00080 00081 template<class iType> int 00082 VrSyncFilter<iType>::work(VrSampleRange output, void *ao[], 00083 VrSampleRange inputs[], void *ai[]) 00084 { 00085 iType **i = (iType **)ai; 00086 VrComplex **o = (VrComplex **)ao; 00087 unsigned int size = output.size; 00088 VrComplex result = 0; 00089 int ch_num = 0; 00090 VrComplex *taps_tmp; 00091 00092 VrComplex phase_correction[num_ch]; 00093 00094 for(ch_num=0;ch_num<num_ch; ch_num++) { 00095 phase_correction[ch_num]=pow(phase_corr_incr[ch_num],(int) output.index) * phase_offset[ch_num]; 00096 } 00097 00098 while (size--) { 00099 symbol_boundary += symbol_period; 00100 new_output_loc = (symbol_boundary + (symbol_period >> 1)) >> PRECISION_BITS; 00101 /* note: offset of output location is specified as 1/2 period by above */ 00102 00103 pointer_incr = new_output_loc - old_output_loc; 00104 if (pointer_incr <0) { /* counter must have rolled over */ 00105 // cout << pointer_incr << endl; 00106 pointer_incr += (1 << (32-PRECISION_BITS)); 00107 } 00108 old_output_loc = new_output_loc; 00109 00110 if (pointer_incr != decimation) { 00111 differential_offset += pointer_incr-decimation; 00112 //cout << "adjusting diff offset: " << differential_offset << endl; 00113 } 00114 00115 if (bump != 0) { 00116 delta_differential_offset = bump >> PRECISION_BITS; 00117 differential_offset += delta_differential_offset; 00118 phase_correction[0] *= phase_bump; 00119 phase_bump = VrComplex(1,0); 00120 printf ("setting offset %ld\n", differential_offset); 00121 //jca symbol_boundary += bump; 00122 cout << "Bumping pointer " << (float) (bump) / (float)(1<<PRECISION_BITS) << endl; 00123 bump =0; 00124 } 00125 result = 0; 00126 00127 for (ch_num =0; ch_num<num_ch; ch_num++){ 00128 //make input pointer local 00129 iType *inputptr = &i[0][0]; //jca differential_offset]; 00130 00131 #if defined (ENABLE_MMX) 00132 if(processedTaps[ch_num]->mmxReady()) 00133 result = processedTaps[ch_num]->mmxCVDProduct(inputptr); 00134 else 00135 #endif 00136 { 00137 taps_tmp = taps[ch_num]; 00138 for (int j=0; j < num_taps[ch_num]; j++) 00139 result += *taps_tmp++ * *inputptr++; 00140 } 00141 00142 // Perform phase correction 00143 phase_correction[ch_num] *= phase_corr_incr[ch_num]; 00144 result *= phase_correction[ch_num]; 00145 *o[ch_num]++ = result; 00146 } 00147 i[0] += pointer_incr; 00148 } 00149 return output.size; 00150 } 00151 00152 template<class iType> void 00153 VrSyncFilter<iType>::buildFilter_complex(int ch){ 00154 int inSampFreq; 00155 int index; 00156 float N = num_taps[ch]; 00157 float M = N-1; /* filter Order */ 00158 00159 inSampFreq = (int)getInputSamplingFrequencyN(0); 00160 if (center_freq[ch] == 0.0){ 00161 // Build Complex Filter => 00162 // produces a low-pass filter using a real Hamming window 00163 for ( index=0 ; index < num_taps[ch] ; index++) 00164 taps[ch][index] = gain[ch]*VrComplex((0.54-0.46*cos(2*M_PI*index/(M)))); 00165 } else { // Build composite Complex Filter => adds freq-shifting part 00166 float arg = 2*M_PI*center_freq[ch] / (float)inSampFreq; 00167 for ( index=0 ; index < num_taps[ch] ; index++) 00168 taps[ch][index] = VrComplex(gain[ch]*cos(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M))), 00169 gain[ch]*(-1)*sin(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M)))); 00170 phase_corr_incr[ch] = VrComplex(cos(arg*(float)symbol_period/(float)(1<<PRECISION_BITS)), 00171 (-1)*sin(arg*(float)symbol_period/(float)(1<<PRECISION_BITS))); 00172 } 00173 #if defined (ENABLE_MMX) 00174 if(processedTaps[ch]!=NULL) 00175 delete processedTaps[ch]; 00176 processedTaps[ch]=new mmxTaps(taps[ch],num_taps[ch]); 00177 #endif 00178 } 00179 00180 template<class iType> 00181 VrSyncFilter<iType>::VrSyncFilter(int n, float per, const int t[], 00182 const float freq[], const float g[]) 00183 :VrPulse<iType,VrComplex>(n, (int) per), num_ch(n) 00184 { 00185 00186 differential_offset = 0; 00187 num_taps=new int[num_ch]; 00188 phase_corr_incr = new VrComplex[num_ch]; 00189 phase_offset = new VrComplex[num_ch]; 00190 center_freq = new float[num_ch]; 00191 gain = new float[num_ch]; 00192 taps = new (VrComplex *[num_ch]); 00193 symbol_period = (int) (per * (float)(1 << PRECISION_BITS)); 00194 00195 #if defined (ENABLE_MMX) 00196 processedTaps = new (mmxTaps *[num_ch]); 00197 #endif 00198 00199 for (int i=0; i<num_ch; i++){ 00200 num_taps[i] = t[i]; 00201 phase_corr_incr[i] = VrComplex(1,0); 00202 phase_offset[i] = VrComplex(1,0); 00203 center_freq[i] = freq[i]; 00204 gain[i] = g[i]; 00205 #if defined (ENABLE_MMX) 00206 processedTaps[i]=NULL; 00207 #endif 00208 } 00209 00210 } 00211 00212 template<class iType> 00213 VrSyncFilter<iType>::VrSyncFilter(float per,int t,float freq, float g) 00214 :VrPulse<iType,VrComplex>(1,(int) per), num_ch(1) 00215 { 00216 differential_offset = 0; 00217 num_taps=new int[num_ch]; 00218 phase_corr_incr = new VrComplex[num_ch]; 00219 phase_offset = new VrComplex[num_ch]; 00220 center_freq = new float[num_ch]; 00221 gain = new float[num_ch]; 00222 taps = new (VrComplex *[num_ch]); 00223 symbol_period = (int) (per * (float)(1 << PRECISION_BITS)); 00224 symbol_boundary = 0; 00225 old_output_loc = (symbol_period >>1) >> PRECISION_BITS; 00226 bump = 0; 00227 00228 #if defined (ENABLE_MMX) 00229 processedTaps = new (mmxTaps *[num_ch]); 00230 processedTaps[0]=NULL; 00231 #endif 00232 num_taps[0] = t; 00233 phase_corr_incr[0] = VrComplex(1,0); 00234 phase_offset[0] = VrComplex(1,0); 00235 center_freq[0] = freq; 00236 gain[0] = g; 00237 } 00238 00239 template<class iType> 00240 void VrSyncFilter<iType>::initialize() 00241 { 00242 for (int i=0; i<num_ch; i++){ 00243 taps[i]=new VrComplex[num_taps[i]]; 00244 buildFilter_complex(i); 00245 } 00246 //Set history 00247 int max_num_taps = 0; 00248 for (int i=0; i<num_ch; i++) 00249 if (num_taps[i] > max_num_taps) max_num_taps = num_taps[i]; 00250 history = max_num_taps + BOZO_HISTORY; //jca 00251 differential_offset = 0; 00252 delta_differential_offset=0; 00253 } 00254 00255 template<class iType> 00256 int VrSyncFilter<iType>::setCenter_Freq(int ch, float cf) 00257 { 00258 center_freq[ch] = cf; 00259 buildFilter_complex(ch); 00260 return 1; 00261 } 00262 00263 template<class iType> 00264 int VrSyncFilter<iType>::setCenter_Freq(float cf) 00265 { 00266 return setCenter_Freq(0,cf); 00267 } 00268 00269 template<class iType> 00270 int VrSyncFilter<iType>::setPhase_Offset(VrComplex f) 00271 { 00272 phase_offset[0]=f; 00273 return 1; 00274 } 00275 00276 template<class iType> 00277 int VrSyncFilter<iType>::setNumber_Taps(int ch, int numT) 00278 { 00279 num_taps[ch] = numT; 00280 delete taps[ch]; 00281 taps[ch]=new VrComplex[num_taps[ch]]; 00282 00283 //set history 00284 int max_num_taps = 0; 00285 for (int i=0; i<num_ch; i++){ 00286 if (num_taps[i] > max_num_taps) max_num_taps = num_taps[i]; 00287 } 00288 //jca history = max_num_taps; 00289 history = max_num_taps + BOZO_HISTORY; //jca 00290 00291 buildFilter_complex(ch); 00292 return 1; 00293 } 00294 00295 template<class iType> 00296 int VrSyncFilter<iType>::setNumber_Taps(int numT) 00297 { 00298 return setNumber_Taps(0, numT); 00299 } 00300 00301 template<class iType> 00302 float VrSyncFilter<iType>::getSymbol_Period() 00303 { 00304 /* returns symbol period in seconds */ 00305 return (float)symbol_period /(float)(1 << PRECISION_BITS) / (float)getInputSamplingFrequencyN(0); 00306 } 00307 00308 template<class iType> 00309 int VrSyncFilter<iType>::setSymbol_Period(float period) 00310 { 00311 double arg = 2*M_PI*center_freq[0] / (double)getInputSamplingFrequencyN(0); 00312 00313 /* input symbol period in seconds -> converts to fractional number of samples*/ 00314 symbol_period = (int)(period * (float)(1 << PRECISION_BITS) * (float)getInputSamplingFrequencyN(0)); 00315 00316 phase_corr_incr[0] = VrComplex(cos(arg*(double)symbol_period/(double)(1<<PRECISION_BITS)), 00317 (-1)*sin(arg*(double)symbol_period/(double)(1<<PRECISION_BITS))); 00318 00319 cout << " Set period to " << (double) symbol_period / (double)(1 << PRECISION_BITS) << endl; 00320 return 1; 00321 } 00322 00323 template<class iType> 00324 int VrSyncFilter<iType>::setSymbol_Timing(float fraction) 00325 { 00326 double arg = 2*M_PI*center_freq[0] / (double)getInputSamplingFrequencyN(0); 00327 00328 /* input fraction (FP) of symbol period for offset adjustment: (+) = 00329 advance boundary relative to sample stream, (-)= retard boundary */ 00330 bump = (int)( fraction * (float) symbol_period); 00331 phase_bump = VrComplex(cos(arg*(double)bump/(double)(1<<PRECISION_BITS)), 00332 (-1)*sin(arg*(double)bump/(double)(1<<PRECISION_BITS))); 00333 return 1; 00334 } 00335 00336 template<class iType> int 00337 VrSyncFilter<iType>::forecast(VrSampleRange output, 00338 VrSampleRange inputs[]) { 00339 // if (output.index>WP) return -1; 00340 if (!is_synced(output.index)) return -1; 00341 /* dec:1 ratio with history */ 00342 for(unsigned int i=0;i<numberInputs;i++) { 00343 inputs[i].index=output.index*decimation+ differential_offset; /* ! do not subtract history ! */ 00344 //cout << inputs[i].index << " " << differential_offset << endl; 00345 inputs[i].size=output.size*decimation + history-1; 00346 } 00347 return 0; 00348 } 00349 00350 template<class iType> 00351 VrSyncFilter<iType>::~VrSyncFilter() 00352 { 00353 00354 for (int i=0; i<num_ch; i++){ 00355 delete taps[i]; 00356 #if defined (ENABLE_MMX) 00357 if(processedTaps[i]!=NULL) 00358 delete processedTaps[i]; 00359 #endif 00360 } 00361 delete num_taps; 00362 delete [] phase_corr_incr; 00363 delete [] phase_offset; 00364 delete center_freq; 00365 delete gain; 00366 delete taps; 00367 } 00368 #endif

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