IT++ Logo
modulator.h
Go to the documentation of this file.
00001 
00029 #ifndef MODULATOR_H
00030 #define MODULATOR_H
00031 
00032 #include <itpp/base/mat.h>
00033 #include <itpp/base/math/elem_math.h>
00034 #include <itpp/base/math/log_exp.h>
00035 #include <itpp/base/converters.h>
00036 #include <itpp/base/math/min_max.h>
00037 
00038 
00039 namespace itpp
00040 {
00041 
00046 enum Soft_Method {
00047   LOGMAP,   
00048   APPROX   
00049 };
00050 
00073 template <typename T>
00074 class Modulator
00075 {
00076 public:
00078   Modulator();
00080   Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
00082   virtual ~Modulator() {}
00083 
00085   virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
00086 
00088   virtual int bits_per_symbol() const { return k; }
00090   virtual Vec<T> get_symbols() const { return symbols; }
00108   virtual ivec get_bits2symbols() const { return bits2symbols; }
00109 
00111   virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
00113   virtual Vec<T> modulate(const ivec& symbolnumbers) const;
00114 
00116   virtual void demodulate(const Vec<T>& signal, ivec& output) const;
00118   virtual ivec demodulate(const Vec<T>& signal) const;
00119 
00121   virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
00123   virtual Vec<T> modulate_bits(const bvec& bits) const;
00124 
00126   virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
00128   virtual bvec demodulate_bits(const Vec<T>& signal) const;
00129 
00169   virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00170                                     vec& soft_bits,
00171                                     Soft_Method method = LOGMAP) const;
00173   virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00174                                    Soft_Method method = LOGMAP) const;
00175 
00214   virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
00215                                     const Vec<T>& channel,
00216                                     double N0, vec& soft_bits,
00217                                     Soft_Method method = LOGMAP) const;
00219   virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
00220                                    const Vec<T>& channel,
00221                                    double N0,
00222                                    Soft_Method method = LOGMAP) const;
00223 
00224 protected:
00226   bool setup_done;
00228   int k;
00230   int M;
00232   bmat bitmap;
00234   ivec bits2symbols;
00236   Vec<T> symbols;
00239   imat S0;
00242   imat S1;
00243 
00245   void calculate_softbit_matrices();
00246 };
00247 
00248 
00249 // ----------------------------------------------------------------------
00250 // Type definitions of Modulator_1D and Modulator_2D
00251 // ----------------------------------------------------------------------
00252 
00257 typedef Modulator<double> Modulator_1D;
00258 
00263 typedef Modulator<std::complex<double> > Modulator_2D;
00264 
00265 
00266 // ----------------------------------------------------------------------
00267 // Implementation of templated Modulator members
00268 // ----------------------------------------------------------------------
00269 
00270 template<typename T>
00271 Modulator<T>::Modulator() :
00272     setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
00273     S0(""), S1("") {}
00274 
00275 template<typename T>
00276 Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
00277 {
00278   set(symbols, bits2symbols);
00279 }
00280 
00281 template<typename T>
00282 void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
00283 {
00284   it_assert(in_symbols.size() == in_bits2symbols.size(),
00285             "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
00286   it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
00287             "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
00288   it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
00289             && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
00290   symbols = in_symbols;
00291   bits2symbols = in_bits2symbols;
00292   M = bits2symbols.size();
00293   k = levels2bits(M);
00294   bitmap.set_size(M, k);
00295   for (int m = 0; m < M; m++) {
00296     bitmap.set_row(bits2symbols(m), dec2bin(k, m));
00297   }
00298   calculate_softbit_matrices();
00299   setup_done = true;
00300 }
00301 
00302 
00303 template<typename T>
00304 void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
00305 {
00306   it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
00307   output.set_size(symbolnumbers.length());
00308   for (int i = 0; i < symbolnumbers.length(); i++)
00309     output(i) = symbols(symbolnumbers(i));
00310 }
00311 
00312 template<typename T>
00313 Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
00314 {
00315   Vec<T> output(symbolnumbers.length());
00316   modulate(symbolnumbers, output);
00317   return output;
00318 }
00319 
00320 
00321 template<typename T>
00322 void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
00323 {
00324   it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
00325   double dist, mindist;
00326   int closest;
00327   output.set_size(signal.size());
00328 
00329   for (int i = 0; i < signal.size(); i++) {
00330     mindist = std::abs(symbols(0) - signal(i));
00331     closest = 0;
00332     for (int j = 1; j < M; j++) {
00333       dist = std::abs(symbols(j) - signal(i));
00334       if (dist < mindist) {
00335         mindist = dist;
00336         closest = j;
00337       }
00338     }
00339     output(i) = closest;
00340   }
00341 }
00342 
00343 template<typename T>
00344 ivec Modulator<T>::demodulate(const Vec<T>& signal) const
00345 {
00346   ivec output(signal.length());
00347   demodulate(signal, output);
00348   return output;
00349 }
00350 
00351 
00352 template<typename T>
00353 void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
00354 {
00355   it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
00356   // Check if some bits have to be cut and print warning message in such
00357   // case.
00358   if (bits.length() % k) {
00359     it_warning("Modulator<T>::modulate_bits(): The number of input bits is not a multiple of k (number of bits per symbol). Remainder bits are not modulated.");
00360   }
00361   int no_symbols = bits.length() / k;
00362   output.set_size(no_symbols);
00363   for (int i = 0; i < no_symbols; i++) {
00364     output(i) = symbols(bits2symbols(bin2dec(bits.mid(i * k, k))));
00365   }
00366 }
00367 
00368 template<typename T>
00369 Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
00370 {
00371   Vec<T> output;
00372   modulate_bits(bits, output);
00373   return output;
00374 }
00375 
00376 template<typename T>
00377 void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
00378 {
00379   it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
00380   double dist, mindist;
00381   int closest;
00382   bits.set_size(k*signal.size());
00383 
00384   for (int i = 0; i < signal.size(); i++) {
00385     mindist = std::abs(symbols(0) - signal(i));
00386     closest = 0;
00387     for (int j = 1; j < M; j++) {
00388       dist = std::abs(symbols(j) - signal(i));
00389       if (dist < mindist) {
00390         mindist = dist;
00391         closest = j;
00392       }
00393     }
00394     bits.replace_mid(i*k, bitmap.get_row(closest));
00395   }
00396 }
00397 
00398 template<typename T>
00399 bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
00400 {
00401   bvec bits;
00402   demodulate_bits(signal, bits);
00403   return bits;
00404 }
00405 
00406 
00407 template<typename T>
00408 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
00409                                         vec &soft_bits,
00410                                         Soft_Method method) const
00411 {
00412   it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
00413   double P0, P1, d0min, d1min, temp;
00414   vec metric(M);
00415 
00416   soft_bits.set_size(k * rx_symbols.size());
00417 
00418   if (method == LOGMAP) {
00419     for (int l = 0; l < rx_symbols.size(); l++) {
00420       for (int j = 0; j < M; j++) {
00421         metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
00422       }
00423       for (int i = 0; i < k; i++) {
00424         P0 = P1 = 0;
00425         for (int j = 0; j < (M >> 1); j++) {
00426           P0 += metric(S0(i, j));
00427           P1 += metric(S1(i, j));
00428         }
00429         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00430       }
00431     }
00432   }
00433   else { // method == APPROX
00434     for (int l = 0; l < rx_symbols.size(); l++) {
00435       for (int j = 0; j < M; j++) {
00436         metric(j) = sqr(rx_symbols(l) - symbols(j));
00437       }
00438       for (int i = 0; i < k; i++) {
00439         d0min = d1min = std::numeric_limits<double>::max();
00440         for (int j = 0; j < (M >> 1); j++) {
00441           temp = metric(S0(i, j));
00442           if (temp < d0min) { d0min = temp; }
00443           temp = metric(S1(i, j));
00444           if (temp < d1min) { d1min = temp; }
00445         }
00446         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00447       }
00448     }
00449   }
00450 }
00451 
00452 template<typename T>
00453 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00454                                        double N0,
00455                                        Soft_Method method) const
00456 {
00457   vec output;
00458   demodulate_soft_bits(rx_symbols, N0, output, method);
00459   return output;
00460 }
00461 
00462 template<typename T>
00463 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00464                                         const Vec<T> &channel, double N0,
00465                                         vec &soft_bits,
00466                                         Soft_Method method) const
00467 {
00468   it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
00469   double P0, P1, d0min, d1min, temp;
00470   vec metric(M);
00471 
00472   soft_bits.set_size(k * rx_symbols.size());
00473 
00474   if (method == LOGMAP) {
00475     for (int l = 0; l < rx_symbols.size(); l++) {
00476       for (int j = 0; j < M; j++) {
00477         metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
00478                              / N0);
00479       }
00480       for (int i = 0; i < k; i++) {
00481         P0 = P1 = 0;
00482         for (int j = 0; j < (M >> 1); j++) {
00483           P0 += metric(S0(i, j));
00484           P1 += metric(S1(i, j));
00485         }
00486         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00487       }
00488     }
00489   }
00490   else { // method == APPROX
00491     for (int l = 0; l < rx_symbols.size(); l++) {
00492       for (int j = 0; j < M; j++) {
00493         metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
00494       }
00495       for (int i = 0; i < k; i++) {
00496         d0min = d1min = std::numeric_limits<double>::max();
00497         for (int j = 0; j < (M >> 1); j++) {
00498           temp = metric(S0(i, j));
00499           if (temp < d0min) { d0min = temp; }
00500           temp = metric(S1(i, j));
00501           if (temp < d1min) { d1min = temp; }
00502         }
00503         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00504       }
00505     }
00506   }
00507 }
00508 
00509 template<typename T>
00510 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00511                                        const Vec<T> &channel,
00512                                        double N0,
00513                                        Soft_Method method) const
00514 {
00515   vec output;
00516   demodulate_soft_bits(rx_symbols, channel, N0, output, method);
00517   return output;
00518 }
00519 
00520 template<typename T>
00521 void Modulator<T>::calculate_softbit_matrices()
00522 {
00523   int count0, count1;
00524 
00525   // Allocate storage space for the result matrices:
00526   S0.set_size(k, M >> 1, false);
00527   S1.set_size(k, M >> 1, false);
00528 
00529   for (int i = 0; i < k; i++) {
00530     count0 = 0;
00531     count1 = 0;
00532     for (int j = 0; j < M; j++) {
00533       if (bitmap(j, i) == bin(0)) {
00534         S0(i, count0++) = j;
00535       }
00536       else {
00537         S1(i, count1++) = j;
00538       }
00539     }
00540   }
00541 }
00542 
00543 
00544 
00545 // ----------------------------------------------------------------------
00546 // QAM : Modulator_2D
00547 // ----------------------------------------------------------------------
00548 
00569 class QAM : public Modulator<std::complex<double> >
00570 {
00571 public:
00573   QAM() {}
00575   QAM(int M) { set_M(M); }
00577   virtual ~QAM() { }
00579   void set_M(int M);
00580 
00582   void demodulate_bits(const cvec& signal, bvec& bits) const;
00584   bvec demodulate_bits(const cvec& signal) const;
00585 
00586 protected:
00588   int L;
00590   double scaling_factor;
00591 };
00592 
00593 
00594 // ----------------------------------------------------------------------
00595 // PSK : Modulator<std::complex<double> >
00596 // ----------------------------------------------------------------------
00597 
00618 class PSK : public Modulator<std::complex<double> >
00619 {
00620 public:
00622   PSK() {}
00624   PSK(int M) { set_M(M); }
00626   virtual ~PSK() { }
00628   void set_M(int M);
00629 
00631   void demodulate_bits(const cvec& signal, bvec& bits) const;
00633   bvec demodulate_bits(const cvec& signal) const;
00634 };
00635 
00636 
00637 // ----------------------------------------------------------------------
00638 // QPSK : PSK : Modulator<std::complex<double> >
00639 // ----------------------------------------------------------------------
00640 
00660 class QPSK : public PSK
00661 {
00662 public:
00664   QPSK(): PSK(4) {}
00666   virtual ~QPSK() {}
00667 
00689   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00690                                     vec& soft_bits,
00691                                     Soft_Method method = LOGMAP) const;
00693   vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00694                            Soft_Method method = LOGMAP) const;
00695 
00696 
00719   virtual void demodulate_soft_bits(const cvec& rx_symbols,
00720                                     const cvec& channel, double N0,
00721                                     vec& soft_bits,
00722                                     Soft_Method method = LOGMAP) const;
00724   vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00725                            double N0, Soft_Method method = LOGMAP) const;
00726 };
00727 
00728 
00729 // ----------------------------------------------------------------------
00730 // BPSK_c : PSK : Modulator<std::complex<double> >
00731 // ----------------------------------------------------------------------
00732 
00758 class BPSK_c : public PSK
00759 {
00760 public:
00762   BPSK_c(): PSK(2) {}
00764   virtual ~BPSK_c() {}
00765 
00767   void modulate_bits(const bvec& bits, cvec& output) const;
00769   cvec modulate_bits(const bvec& bits) const;
00771   void demodulate_bits(const cvec& signal, bvec& output) const;
00773   bvec demodulate_bits(const cvec& signal) const;
00774 
00794   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00795                                     vec& soft_bits,
00796                                     Soft_Method method = LOGMAP) const;
00798   vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00799                            Soft_Method method = LOGMAP) const;
00800 
00821   virtual void demodulate_soft_bits(const cvec& rx_symbols,
00822                                     const cvec& channel, double N0,
00823                                     vec& soft_bits,
00824                                     Soft_Method method = LOGMAP) const;
00826   vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00827                            double N0, Soft_Method method = LOGMAP) const;
00828 };
00829 
00830 
00831 
00832 // ----------------------------------------------------------------------
00833 // BPSK : Modulator<double>
00834 // ----------------------------------------------------------------------
00835 
00859 class BPSK : public Modulator<double>
00860 {
00861 public:
00863   BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
00865   virtual ~BPSK() {}
00866 
00868   void modulate_bits(const bvec& bits, vec& output) const;
00870   vec modulate_bits(const bvec& bits) const;
00872   void demodulate_bits(const vec& signal, bvec& output) const;
00874   bvec demodulate_bits(const vec& signal) const;
00875 
00893   virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
00894                                     vec& soft_bits,
00895                                     Soft_Method method = LOGMAP) const;
00897   vec demodulate_soft_bits(const vec& rx_symbols, double N0,
00898                            Soft_Method method = LOGMAP) const;
00899 
00919   virtual void demodulate_soft_bits(const vec& rx_symbols,
00920                                     const vec& channel, double N0,
00921                                     vec& soft_bits,
00922                                     Soft_Method method = LOGMAP) const;
00924   vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
00925                            double N0, Soft_Method method = LOGMAP) const;
00926 };
00927 
00928 
00929 // ----------------------------------------------------------------------
00930 // PAM_c : Modulator<std::complex<double> >
00931 // ----------------------------------------------------------------------
00932 
00951 class PAM_c : public Modulator<std::complex<double> >
00952 {
00953 public:
00955   PAM_c() {}
00957   PAM_c(int M) { set_M(M); }
00959   virtual ~PAM_c() {}
00961   void set_M(int M);
00962 
00964   void demodulate_bits(const cvec& signal, bvec& output) const;
00966   bvec demodulate_bits(const cvec& signal) const;
00967 
01007   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
01008                                     vec& soft_bits,
01009                                     Soft_Method method = LOGMAP) const;
01011   virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
01012                                    Soft_Method method = LOGMAP) const;
01013 
01052   virtual void demodulate_soft_bits(const cvec& rx_symbols,
01053                                     const cvec& channel, double N0,
01054                                     vec& soft_bits,
01055                                     Soft_Method method = LOGMAP) const;
01057   virtual vec demodulate_soft_bits(const cvec& rx_symbols,
01058                                    const cvec& channel, double N0,
01059                                    Soft_Method method = LOGMAP) const;
01060 
01061 protected:
01063   double scaling_factor;
01064 };
01065 
01066 
01067 // ----------------------------------------------------------------------
01068 // PAM : Modulator<double>
01069 // ----------------------------------------------------------------------
01070 
01087 class PAM : public Modulator<double>
01088 {
01089 public:
01091   PAM() {}
01093   PAM(int M) { set_M(M); }
01095   virtual ~PAM() {}
01097   void set_M(int M);
01098 
01100   void demodulate_bits(const vec& signal, bvec& output) const;
01102   bvec demodulate_bits(const vec& signal) const;
01103 
01104 protected:
01106   double scaling_factor;
01107 };
01108 
01109 } // namespace itpp
01110 
01111 #endif // #ifndef MODULATOR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Sat Jul 9 2011 15:21:31 for IT++ by Doxygen 1.7.4