Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

mle.h

Go to the documentation of this file.
00001 // 
00002 // author="Tony Kirke" *
00003 // Copyright(c) 2001 Tony Kirke
00004 // SPUC - Signal processing using C++ - A DSP library
00005 /*
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 // $Id: mle.h,v 1.7 2005/09/16 17:01:03 spuc Exp $
00021 #ifndef BSE
00022 #define BSE
00023 //---------------------------------------------------------------------*/
00024 #include <math.h>
00025 #include <complex.h>
00026 #include <delay.h>
00027 #include <fir_adapt.h>
00028 namespace SPUC {
00032 
00033 
00034 
00042 template <class Numeric> class mle
00043 {
00044  public:
00045         const long mlsd_span;
00046         const long dfe_span; 
00047         long n_branches;     
00048         long n_states;       
00049         Numeric fb_est;      
00050         fir_adapt< Numeric > cfir; 
00051         Numeric* cir_mlsd;
00052         Numeric* cir_dfe;
00053         Numeric* f_est;      
00054         Numeric* b_est;
00055         double* weight;     
00056         long* path;
00057         long* tmp_path; // Temporary variable
00058         double* tmp_weight; // Temporary variable
00059         long* path_symbol;
00060         long phase_states;   
00061         long total_states;   
00062         double phase_inc;    
00063 
00066         mle(int mlsd_size, int dfe_size=0, long q=1) :
00067                 mlsd_span(mlsd_size+1),
00068                 dfe_span(dfe_size)
00069                 {
00070                         n_states = (1 << (q*mlsd_size));
00071                         n_branches = (2*q*n_states);
00072                         cfir.set_size(mlsd_span);
00073                         cir_mlsd = new Numeric[mlsd_span];
00074                         cir_dfe  = new Numeric[dfe_span];
00075                         f_est = new Numeric[n_branches];
00076                         b_est = new Numeric[n_states];
00077                         weight = new double[n_states];
00078                         path = new long[n_states];
00079                         tmp_path = new long[n_states];
00080                         tmp_weight = new double[n_states];
00081                         path_symbol = new long[n_states];
00082                         for (int i=0;i<n_states;i++) {
00083                                 path_symbol[i] = 0;
00084                                 path[i] = 0;
00085                                 weight[i] = 0;
00086                         }
00087                         fb_est = 0;
00088                 }
00089         ~mle(void) {
00090                 delete [] path;
00091                 delete [] path_symbol;
00092                 delete [] weight;
00093         }
00095         void reset() { cfir.reset(); }
00097         void update_taps_lms(Numeric err) {
00098                 cfir.update_lms(err);
00099         }
00101         Numeric tap0(void) { return(cfir.coeff[0]); }
00103         void set_cir(const fir < Numeric >& cir) {
00104                 int i;
00105                 for (i=0;i<mlsd_span;i++) cir_mlsd[i] = cir.coeff[i];
00106                 for (i=0;i<dfe_span;i++) {
00107                         if (i+mlsd_span < cir.num_taps) 
00108                                 cir_dfe[i] = cir.coeff[mlsd_span+i];
00109                         else
00110                                 cir_dfe[i] = 0;
00111                 }
00112         }
00115         Numeric df_est(int state) {
00116                 int pnt,i;
00117                 Numeric est = 0.0;
00118                 pnt = 0x1;
00119                 for (i=0;i<dfe_span;i++) {
00120                         if ((path[state] & pnt) != 0)  est += cir_dfe[i]; 
00121                         else      est -= cir_dfe[i]; 
00122                         pnt <<= 1;
00123                 }
00124                 return(est);
00125         }
00127         Numeric ff_estimate(long seq) {
00128                 int j, i;
00129                 long num_taps = mlsd_span;
00130                 Numeric pred = 0;
00131                 j = (0x1 << num_taps);
00132                 for(i = 0; i < num_taps; i++) {
00133                         j >>= 1;
00134                         if((seq & j) != 0) pred += cfir.coeff[i];
00135                         else pred -= cfir.coeff[i];
00136                 }
00137                 return(pred);
00138         }
00140         double estimate(Numeric rx, long seq, long state, long type) {
00141                 Numeric y;
00142                 if (type == 1) { // RSDFE
00143                         y = ff_estimate(seq)+ fb_est;
00144                         return(magsq(y-rx));
00145                 } else if (type == 2) { // DDFSE
00146                         y = ff_estimate(seq)+ b_est[state];
00147                         return(magsq(y-rx));
00148                 } else { // MLSD
00149                         y = ff_estimate(seq);
00150                         return(magsq(y-rx));
00151                 }
00152 
00153         }
00155         long ddfse(Numeric rx) {return(equalize(rx, 2));}
00157         long mlsd(Numeric rx)  {return(equalize(rx, 0));}
00159         long rsdfse(Numeric rx){return(equalize(rx,1));}
00161         long equalize(Numeric rx, long type) {
00162                 double temp0,temp1;
00163                 long ex_state0, ex_state1;
00164                 long old_state0, old_state1;
00165                 double metric0,metric1;
00166                 double min_weight;
00167                 long path_state;
00168                 int i;
00169                 for (i=0;i<n_states;i++) {
00170                         // 0 transition
00171                         ex_state0 = (i<<1);
00172                         // previous state assuming 0 transition
00173                         metric0 = estimate(rx, ex_state0, i, type);
00174                         old_state0 = ex_state0 % n_states;
00175                         temp0 = weight[old_state0] + metric0;
00176                         // 1 transition
00177                         ex_state1 = ex_state0 + 1;
00178                         // previous state assuming 1 transition
00179                         metric1 = estimate(rx, ex_state1, i+n_states, type);
00180                         old_state1 = ex_state1 % n_states;
00181                         temp1 = weight[old_state1] + metric1;
00182                         if (temp0 < temp1) {
00183                                 tmp_weight[i] = temp0;
00184                                 tmp_path[i] = (path[old_state0] << 1);
00185                         } else {
00186                                 tmp_weight[i] = temp1;
00187                                 tmp_path[i] = (path[old_state1] << 1) | 0x1;
00188                         }
00189                 }
00190                 // get minimum weight for all the
00191                 // states and return the path data
00192                 // for this minimum weight
00193                 // Also, store new weights and paths
00194                 // for all states
00195                 min_weight = tmp_weight[0];
00196                 path_state = 0;
00197                 for (i=0;i<n_states;i++) {
00198                         if (tmp_weight[i] < min_weight) {
00199                                 min_weight = tmp_weight[i];
00200                                 path_state = i;
00201                         }
00202                         // store for next iteration
00203                         weight[i] = tmp_weight[i];
00204                         path[i] = tmp_path[i];
00205                         b_est[i] = df_est(i); // for ddfse
00206                         fb_est   = df_est(path_state); // for rsdfse
00207                 }
00208                 return(path[path_state]);
00209         }
00210 };
00211 } // namespace SPUC
00212 #endif

Generated on Fri Sep 16 11:02:22 2005 for spuc by  doxygen 1.4.4