00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00029
00030
00031
00032
00033
00034
00035
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;
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
00087
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
00106 pointer_incr += (1 << (32-PRECISION_BITS));
00107 }
00108
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
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
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 {
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;
00173
00174 inSampFreq = getInputSamplingFrequencyN(0);
00175
00176 if (center_freq == 0.0){
00177
00178
00179
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
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
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
00257 setHistory(num_taps);
00258 buildFilter_complex();
00259 return 1;
00260 }
00261
00262 template<class iType>
00263 float VrPulseCorrelator<iType>::getSymbol_Period()
00264 {
00265
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
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
00282
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
00293
00294
00295
00296
00297
00298
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