Main Page | Namespace List | Class Hierarchy | Class List | Directories | 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 Tue Mar 15 23:47:08 2005 for GNU Radio by  doxygen 1.4.0