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

VrComplexDemod.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 #ifndef _VRCOMPLEXDEMOD_H_
00018 #define _VRCOMPLEXDEMOD_H_
00019 
00020 #define SQR_HISTORY_OFFSET 20
00021 
00022 #include <stdio.h>
00023 #include "VrHistoryProc.h"
00024 #include "VrGUI.h"
00025 
00026 #if defined (ENABLE_MMX)
00027 #include <VrMMX.h>
00028 #endif
00029 
00030 template<class iType>
00031 class VrComplexDemod : public VrHistoryProc<iType,VrComplex> {
00032 protected:
00033   VrSyncCorr<char>* sync_ptr;
00034   float timeDuration, slice, sync_threshold;
00035   float pos_threshold, high_pos_threshold, low_pos_threshold;
00036   float neg_threshold, high_neg_threshold, low_neg_threshold;
00037   int size, numTaps, restart, decimation;
00038   float min, max, center_freq, corr_sign;
00039   int ready_for_syncs, ready_for_max, not_sync;
00040   int N, flip, flip_c, plot, plot_count, symb_count, symbol_sync;
00041   int sync_struct_size, num;
00042 
00043   int consec_sync, remaining_symbols, dropped_sync;
00044   int center_first, center_second, best_period;
00045   VrComplex sum, old_conj, *taps;
00046   VrComplex sqr_hist[2*SQR_HISTORY_OFFSET], *current_sqr, *last_sqr;
00047   VrSampleIndex first_loc, second_loc, fresh_data_ts_1, fresh_data_ts_2;
00048   VrSampleIndex sync_ts_offset, data_ts_offset;
00049   struct corr_result best;
00050   void buildFilter_complex();
00051 
00052 public:
00053   //  VrComplexDemod(VrGUILayout *arg_layout, VrPulse<char, char>*, float td, int s);
00054   VrComplexDemod(VrSyncCorr<char>*,int,float);
00055   //  ~VrComplexDemod();
00056   virtual const char *name() { return "VrComplexDemod"; }
00057   virtual void initialize();
00058   virtual int forecast(VrSampleRange output,
00059                        VrSampleRange inputs[]);
00060   virtual int work(VrSampleRange output, void *o[],
00061                    VrSampleRange inputs[], void *i[]);
00062 
00063 #if 0
00064   char symbol_decision(float);
00065 #endif
00066 
00067 };
00068 
00069 template<class iType> int
00070 VrComplexDemod<iType>::work(VrSampleRange output, void *ao[],
00071                            VrSampleRange inputs[], void *ai[])
00072 {
00073   iType **i = (iType **)ai;
00074   VrComplex **o = (VrComplex **)ao;
00075   int size = output.size;
00076   VrComplex point, est_theta;
00077   int window_length, period_length;
00078   struct corr_result input, *sync_input_ptr;
00079   float sync_fraction = 0.10;
00080   int req_consec_sync = 5;
00081 
00082   
00083   sync_input_ptr = (struct corr_result *) i[sync_input];
00084 
00085 #if 0
00086   if (not_sync) {
00087 
00088     //    num = initial_sync_num_windows;
00089 
00090     if (!ready_for_syncs) {
00091 
00092       if (!ready_for_max) {
00093         window_length = nominal_samples_per_period / (float) num;
00094         period_length = (int) nominal_samples_per_period + 1 + window_length;
00095         
00096         sync_ptr -> set_window(window_length);
00097         sync_ptr -> set_period(period_length);
00098         
00099         fresh_data_ts_1 = getMarkedWP();
00100         ready_for_max = 1;
00101       return 0;
00102       }
00103       
00104       while (inputs[sync_input].index <= fresh_data_ts_1) {
00105         input = *sync_input_ptr++;
00106         sync_ts_offset++;
00107         return 0;
00108       }
00109       
00110       max = 0.0;
00111       min = 0.0;
00112       while (num-- > 0) {
00113         
00114         input = *sync_input_ptr++;
00115         sync_ts_offset++;
00116       
00117         if (input.value > max) {
00118           best.value = input.value;
00119           best.index = input.index;
00120         }
00121         if (input.value < min) {
00122           best.value = input.value;
00123           best.index = input.index;
00124         }
00125         return 0;
00126       }
00127       
00128       if (best.value >= 0) corr_sign = 1.0;
00129       if (best.value < 0) corr_sign = -1.0;
00130       
00131       sync_threshold = 0.90 * best.value;
00132     
00133       window_length = (int) (nominal_samples_per_period * sync_fraction);
00134       period_length = (int) nominal_samples_per_period;
00135       
00136       sync_ptr -> set_window(window_length);
00137       sync_ptr -> set_period(period_length);
00138       
00139       fresh_data_ts_2 = getMarkedWP();
00140       ready_for_syncs = 1;
00141       return 0;
00142     }
00143 
00144     while (inputs[sync_input].index <= fresh_data_ts_2) {
00145       input = *sync_input_ptr++;
00146       sync_ts_offset++;
00147       return 0;
00148     }
00149  
00150     while (consec_sync < req_consec_sync) {
00151 
00152       input = *sync_input_ptr++;
00153       sync_ts_offset++;
00154       
00155       if (corr_sign * input.value > sync_threshold) {
00156         consec_sync++;
00157         first_loc = second_loc;
00158         second_loc = input.index;
00159       }
00160       else {
00161         consec_sync=0;
00162         restart++;
00163       }
00164       if (restart >= 2){
00165         restart = 0;
00166         sync_ptr -> increment_input_ptr(window_length + period_length);
00167       }
00168     }
00169     remaining_symbols = symbols_per_period;
00170     not_sync = 0;
00171     
00172   }
00173 #endif
00174   while (size > 0) {
00175 
00176     while ((size-- >0) & (remaining_symbols-- > 0)) {
00177 
00178       cout << size << " " << remaining_symbols << endl;
00179       point = *i[data_input]++;
00180       *current_sqr = point * point;
00181       *(current_sqr-SQR_HISTORY_OFFSET) = point * point;
00182       sum = sum + *current_sqr - *(current_sqr-N);
00183       current_sqr++;
00184       if (current_sqr == last_sqr) current_sqr -= SQR_HISTORY_OFFSET;
00185       est_theta = sqrt ( sum / sqrt((real(sum)*real(sum) + imag(sum)*imag(sum))));
00186       if (real(old_conj*est_theta)<0) flip =  -flip;
00187       old_conj = VrComplex(real(est_theta), -imag(est_theta));
00188       //disable phase recovery:  point = point * VrComplex(real(est_theta), -imag(est_theta));
00189       if (flip <0) point = -point;
00190 #if 0
00191       symbol = symbol_decision( constellation, point);
00192       o[0]++ = symbol;
00193 #endif
00194       *o[0]++ = point;
00195 
00196     } /* while ((size-- >0) & (remaining_symbols-- > 0) */
00197 
00198     first_loc = second_loc;
00199     input = *sync_input_ptr++;
00200     if (corr_sign * input.value > sync_threshold) {
00201       second_loc = input.index;
00202       dropped_sync = 0;
00203     } else { 
00204       dropped_sync++;
00205       second_loc = first_loc + best_period;
00206     }
00207 
00208     if (remaining_symbols <=0) remaining_symbols = symbols_per_period; // ow size = 0
00209     
00210   } /* while (size-- > 0) */
00211   return output.size;
00212 }
00213 
00214 #if 0
00215 template <class iType> char
00216 VrComplexDemod<iType>::symbol_decision(float slice)
00217 {
00218   char symbol;
00219 #ifdef EIGHT
00220 #define OUTER (slice > 0)
00221 #define MID (slice > pos_threshold)
00222 #define INNER (slice > high_pos_threshold)
00223 #define INNER2 (slice > low_pos_threshold)
00224 #else /* !EIGHT */
00225 #define OUTER (1)
00226 #define INNER2 (slice > neg_threshold)
00227 #ifdef TWO
00228 #define MID (1)
00229 #define INNER (slice > 0)
00230 #else /* !TWO */
00231 #define MID (slice > 0)
00232 #define INNER (slice > pos_threshold)
00233 #endif /* TWO */
00234 #endif /* EIGHT */
00235   if (OUTER)
00236     if (MID)
00237       if (INNER)
00238                 symbol = 0x00;
00239       else  symbol = 0x01;
00240      else
00241       if (INNER2)
00242                 symbol = 0x02;
00243       else  symbol = 0x03;
00244    else
00245     if (slice>neg_threshold)
00246       if (slice>high_neg_threshold) symbol = 0x04;
00247       else  symbol = 0x05;
00248      else
00249       if (slice> low_neg_threshold) symbol = 0x06;
00250       else  symbol = 0x07;
00251   //      cout <<  (int)(symbol);
00252   return symbol;
00253 }
00254 #endif
00255 
00256 #if 0
00257 template <class iType> int
00258 VrComplexDemod<iType>::get_first_sync(int number_of_windows, int window_length) {
00259 
00260   struct corr_result best, extreme;
00261   //  int number_of_windows = 10; 
00262   int window_length = best_period / number_of_windows+1;
00263   int num = number_of_windows;
00264   int current_ts = init_ts;
00265 
00266   best.value = 0.0;
00267   while (num-- > 0) {
00268     
00269     //    extreme = window_max_ampl( current_ts, window_length);
00270 #if 0
00271     extreme = i[sync_input
00272 #endif
00273     current_ts += best_period + best_period/number_of_windows;// advance (100+X)% of a period
00274     if( abs(extreme.value) > abs(best.value)) {
00275       best.value = extreme.value;
00276       best.index = extreme.index;
00277     }
00278     
00279   }
00280   return best.index;
00281 }
00282 #endif
00283 
00284 template <class iType> void
00285 VrComplexDemod<iType>::initialize()
00286 {
00287   //  float dummy;
00288 
00289   //  increment = (int)(getInputSamplingFrequencyN(0) * timeDuration);
00290   history = 100; 
00291   current_sqr = &sqr_hist[SQR_HISTORY_OFFSET];
00292   last_sqr = current_sqr + SQR_HISTORY_OFFSET;
00293   old_conj = VrComplex();
00294   flip =1;
00295   plot_count =0;
00296   symb_count = 0;
00297   symbols_per_period = 50;
00298 
00299   N = 5;
00300   for (int i = 0; i<2*SQR_HISTORY_OFFSET; i++)
00301          sqr_hist[i] = VrComplex();
00302   pos_threshold = 0.7;
00303   neg_threshold = -0.7;
00304   high_pos_threshold = 1.1;
00305   low_pos_threshold = 0.4;
00306   high_neg_threshold = -0.4;
00307   low_neg_threshold = -1.1;
00308 
00309   decimation = (int) nominal_samples_per_symbol;
00310 }
00311 
00312 template<class iType> int
00313 VrComplexDemod<iType>::forecast(VrSampleRange output,
00314                                            VrSampleRange inputs[]) {
00315 
00316     inputs[sync_input].index=(output.index / symbols_per_period + sync_ts_offset) * sync_struct_size;
00317     inputs[sync_input].size=(output.size / symbols_per_period + 2) * sync_struct_size;
00318 
00319     inputs[data_input].index=output.index*decimation + data_ts_offset;
00320     inputs[data_input].size=output.size*decimation + history - 1;
00321 
00322 //jca printf ("VrSyncCorr forecast[i] ts %lld size %ld output.index %lld dec %d off %d\n", inputs[i].index, inputs[i].size,
00323         //jca output.index, decimation, differential_offset);
00324     return 0;
00325 }  
00326 template <class iType>
00327 VrComplexDemod<iType>::VrComplexDemod(VrSyncCorr<char> *ptr, int num_taps, float freq)
00328   : VrHistoryProc<iType, VrComplex>(1), sync_ptr(ptr),numTaps(num_taps),center_freq(freq)
00329 {
00330   sync_struct_size = sizeof(struct corr_result);
00331 }
00332 
00333 template<class iType> void
00334 VrComplexDemod<iType>::buildFilter_complex(){
00335   int inSampFreq;
00336   int index;
00337   float N = numTaps;
00338   float M = N-1; /* filter Order */
00339 
00340   inSampFreq = (int)getInputSamplingFrequencyN(0); 
00341   if (center_freq == 0.0){
00342       // Build Complex Filter => 
00343       //            produces a low-pass filter using a real Hamming window
00344       for ( index=0 ; index < numTaps ; index++)
00345        taps[index] = gain*VrComplex((0.54-0.46*cos(2*M_PI*index/(M))));
00346   } 
00347   else 
00348     {           // Build composite Complex Filter => adds freq-shifting part
00349     float arg = 2*M_PI*center_freq / (float)inSampFreq;
00350     for ( index=0 ; index < numTaps ; index++)
00351       taps[index] = VrComplex(gain*cos(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M))),
00352          gain*(-1)*sin(arg*index)*(0.54-0.46*cos(2*M_PI*index/(M))));
00353     phase_corr_incr = VrComplex(cos(arg*(float)symbol_period/(float)(1<<PRECISION_BITS)),
00354                                 (-1)*sin(arg*(float)symbol_period/(float)(1<<PRECISION_BITS)));
00355   }
00356 #if defined (ENABLE_MMX)
00357   if(processedTaps!=NULL)
00358     delete processedTaps;
00359   processedTaps=new mmxTaps(taps,numTaps);
00360 #endif
00361 }
00362 
00363 
00364 #endif
00365 

Generated on Tue Mar 15 23:46:36 2005 for GNU Radio by  doxygen 1.4.0