IT++ Logo

modulator.h

Go to the documentation of this file.
00001 
00030 #ifndef MODULATOR_H
00031 #define MODULATOR_H
00032 
00033 #include <itpp/base/mat.h>
00034 #include <itpp/base/math/elem_math.h>
00035 #include <itpp/base/math/log_exp.h>
00036 #include <itpp/base/converters.h>
00037 #include <itpp/base/math/min_max.h>
00038 
00039 
00040 namespace itpp
00041 {
00042 
00047 enum Soft_Method {
00048   LOGMAP,   
00049   APPROX   
00050 };
00051 
00074 template <typename T>
00075 class Modulator
00076 {
00077 public:
00079   Modulator();
00081   Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
00083   virtual ~Modulator() {}
00084 
00086   virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
00087 
00089   virtual int bits_per_symbol() const { return k; }
00091   virtual Vec<T> get_symbols() const { return symbols; }
00109   virtual ivec get_bits2symbols() const { return bits2symbols; }
00110 
00112   virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
00114   virtual Vec<T> modulate(const ivec& symbolnumbers) const;
00115 
00117   virtual void demodulate(const Vec<T>& signal, ivec& output) const;
00119   virtual ivec demodulate(const Vec<T>& signal) const;
00120 
00122   virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
00124   virtual Vec<T> modulate_bits(const bvec& bits) const;
00125 
00127   virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
00129   virtual bvec demodulate_bits(const Vec<T>& signal) const;
00130 
00170   virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00171                                     vec& soft_bits,
00172                                     Soft_Method method = LOGMAP) const;
00174   virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00175                                    Soft_Method method = LOGMAP) const;
00176 
00181   virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00182       double N0, vec& soft_bits) const;
00187   virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00188                                           double N0) const;
00189 
00228   virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
00229                                     const Vec<T>& channel,
00230                                     double N0, vec& soft_bits,
00231                                     Soft_Method method = LOGMAP) const;
00233   virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
00234                                    const Vec<T>& channel,
00235                                    double N0,
00236                                    Soft_Method method = LOGMAP) const;
00237 
00242   virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00243       const Vec<T>& channel,
00244       double N0, vec& soft_bits) const;
00249   virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00250                                           const Vec<T>& channel,
00251                                           double N0) const;
00252 
00253 protected:
00255   bool setup_done;
00257   int k;
00259   int M;
00261   bmat bitmap;
00263   ivec bits2symbols;
00265   Vec<T> symbols;
00268   imat S0;
00271   imat S1;
00272 
00274   void calculate_softbit_matrices();
00275 };
00276 
00277 
00278 // ----------------------------------------------------------------------
00279 // Type definitions of Modulator_1D and Modulator_2D
00280 // ----------------------------------------------------------------------
00281 
00286 typedef Modulator<double> Modulator_1D;
00287 
00292 typedef Modulator<std::complex<double> > Modulator_2D;
00293 
00294 
00295 // ----------------------------------------------------------------------
00296 // Implementation of templated Modulator members
00297 // ----------------------------------------------------------------------
00298 
00299 template<typename T>
00300 Modulator<T>::Modulator() :
00301     setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
00302     S0(""), S1("") {}
00303 
00304 template<typename T>
00305 Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
00306 {
00307   set(symbols, bits2symbols);
00308 }
00309 
00310 template<typename T>
00311 void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
00312 {
00313   it_assert(in_symbols.size() == in_bits2symbols.size(),
00314             "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
00315   it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
00316             "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
00317   it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
00318             && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
00319   symbols = in_symbols;
00320   bits2symbols = in_bits2symbols;
00321   M = bits2symbols.size();
00322   k = levels2bits(M);
00323   bitmap.set_size(M, k);
00324   for (int m = 0; m < M; m++) {
00325     bitmap.set_row(bits2symbols(m), dec2bin(k, m));
00326   }
00327   calculate_softbit_matrices();
00328   setup_done = true;
00329 }
00330 
00331 
00332 template<typename T>
00333 void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
00334 {
00335   it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
00336   output.set_size(symbolnumbers.length());
00337   for (int i = 0; i < symbolnumbers.length(); i++)
00338     output(i) = symbols(symbolnumbers(i));
00339 }
00340 
00341 template<typename T>
00342 Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
00343 {
00344   Vec<T> output(symbolnumbers.length());
00345   modulate(symbolnumbers, output);
00346   return output;
00347 }
00348 
00349 
00350 template<typename T>
00351 void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
00352 {
00353   it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
00354   double dist, mindist;
00355   int closest;
00356   output.set_size(signal.size());
00357 
00358   for (int i = 0; i < signal.size(); i++) {
00359     mindist = std::abs(symbols(0) - signal(i));
00360     closest = 0;
00361     for (int j = 1; j < M; j++) {
00362       dist = std::abs(symbols(j) - signal(i));
00363       if (dist < mindist) {
00364         mindist = dist;
00365         closest = j;
00366       }
00367     }
00368     output(i) = closest;
00369   }
00370 }
00371 
00372 template<typename T>
00373 ivec Modulator<T>::demodulate(const Vec<T>& signal) const
00374 {
00375   ivec output(signal.length());
00376   demodulate(signal, output);
00377   return output;
00378 }
00379 
00380 
00381 template<typename T>
00382 void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
00383 {
00384   it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
00385   // Check if some bits have to be cut and print warning message in such
00386   // case.
00387   if (bits.length() % k) {
00388     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.");
00389   }
00390   int no_symbols = bits.length() / k;
00391   output.set_size(no_symbols);
00392   for (int i = 0; i < no_symbols; i++) {
00393     output(i) = symbols(bits2symbols(bin2dec(bits.mid(i * k, k))));
00394   }
00395 }
00396 
00397 template<typename T>
00398 Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
00399 {
00400   Vec<T> output;
00401   modulate_bits(bits, output);
00402   return output;
00403 }
00404 
00405 template<typename T>
00406 void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
00407 {
00408   it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
00409   double dist, mindist;
00410   int closest;
00411   bits.set_size(k*signal.size());
00412 
00413   for (int i = 0; i < signal.size(); i++) {
00414     mindist = std::abs(symbols(0) - signal(i));
00415     closest = 0;
00416     for (int j = 1; j < M; j++) {
00417       dist = std::abs(symbols(j) - signal(i));
00418       if (dist < mindist) {
00419         mindist = dist;
00420         closest = j;
00421       }
00422     }
00423     bits.replace_mid(i*k, bitmap.get_row(closest));
00424   }
00425 }
00426 
00427 template<typename T>
00428 bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
00429 {
00430   bvec bits;
00431   demodulate_bits(signal, bits);
00432   return bits;
00433 }
00434 
00435 
00436 template<typename T>
00437 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
00438                                         vec &soft_bits,
00439                                         Soft_Method method) const
00440 {
00441   it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
00442   double P0, P1, d0min, d1min, temp;
00443   vec metric(M);
00444 
00445   soft_bits.set_size(k * rx_symbols.size());
00446 
00447   if (method == LOGMAP) {
00448     for (int l = 0; l < rx_symbols.size(); l++) {
00449       for (int j = 0; j < M; j++) {
00450         metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
00451       }
00452       for (int i = 0; i < k; i++) {
00453         P0 = P1 = 0;
00454         for (int j = 0; j < (M >> 1); j++) {
00455           P0 += metric(S0(i, j));
00456           P1 += metric(S1(i, j));
00457         }
00458         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00459       }
00460     }
00461   }
00462   else { // method == APPROX
00463     for (int l = 0; l < rx_symbols.size(); l++) {
00464       for (int j = 0; j < M; j++) {
00465         metric(j) = sqr(rx_symbols(l) - symbols(j));
00466       }
00467       for (int i = 0; i < k; i++) {
00468         d0min = d1min = std::numeric_limits<double>::max();
00469         for (int j = 0; j < (M >> 1); j++) {
00470           temp = metric(S0(i, j));
00471           if (temp < d0min) { d0min = temp; }
00472           temp = metric(S1(i, j));
00473           if (temp < d1min) { d1min = temp; }
00474         }
00475         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00476       }
00477     }
00478   }
00479 }
00480 
00481 template<typename T>
00482 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00483                                        double N0,
00484                                        Soft_Method method) const
00485 {
00486   vec output;
00487   demodulate_soft_bits(rx_symbols, N0, output, method);
00488   return output;
00489 }
00490 
00491 template<typename T>
00492 void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00493     double N0,
00494     vec &soft_bits) const
00495 {
00496   it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00497   demodulate_soft_bits(rx_symbols, N0, soft_bits, APPROX);
00498 }
00499 
00500 template<typename T>
00501 vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00502     double N0) const
00503 {
00504   it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00505   vec output;
00506   demodulate_soft_bits(rx_symbols, N0, output, APPROX);
00507   return output;
00508 }
00509 
00510 
00511 template<typename T>
00512 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00513                                         const Vec<T> &channel, double N0,
00514                                         vec &soft_bits,
00515                                         Soft_Method method) const
00516 {
00517   it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
00518   double P0, P1, d0min, d1min, temp;
00519   vec metric(M);
00520 
00521   soft_bits.set_size(k * rx_symbols.size());
00522 
00523   if (method == LOGMAP) {
00524     for (int l = 0; l < rx_symbols.size(); l++) {
00525       for (int j = 0; j < M; j++) {
00526         metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
00527                              / N0);
00528       }
00529       for (int i = 0; i < k; i++) {
00530         P0 = P1 = 0;
00531         for (int j = 0; j < (M >> 1); j++) {
00532           P0 += metric(S0(i, j));
00533           P1 += metric(S1(i, j));
00534         }
00535         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00536       }
00537     }
00538   }
00539   else { // method == APPROX
00540     for (int l = 0; l < rx_symbols.size(); l++) {
00541       for (int j = 0; j < M; j++) {
00542         metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
00543       }
00544       for (int i = 0; i < k; i++) {
00545         d0min = d1min = std::numeric_limits<double>::max();
00546         for (int j = 0; j < (M >> 1); j++) {
00547           temp = metric(S0(i, j));
00548           if (temp < d0min) { d0min = temp; }
00549           temp = metric(S1(i, j));
00550           if (temp < d1min) { d1min = temp; }
00551         }
00552         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00553       }
00554     }
00555   }
00556 }
00557 
00558 template<typename T>
00559 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00560                                        const Vec<T> &channel,
00561                                        double N0,
00562                                        Soft_Method method) const
00563 {
00564   vec output;
00565   demodulate_soft_bits(rx_symbols, channel, N0, output, method);
00566   return output;
00567 }
00568 
00569 template<typename T>
00570 void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00571     const Vec<T> &channel,
00572     double N0,
00573     vec &soft_bits) const
00574 {
00575   it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00576   demodulate_soft_bits(rx_symbols, channel, N0, soft_bits, APPROX);
00577 }
00578 
00579 template<typename T>
00580 vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00581     const Vec<T> &channel,
00582     double N0) const
00583 {
00584   it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00585   vec output;
00586   demodulate_soft_bits(rx_symbols, channel, N0, output, APPROX);
00587   return output;
00588 }
00589 
00590 
00591 template<typename T>
00592 void Modulator<T>::calculate_softbit_matrices()
00593 {
00594   int count0, count1;
00595 
00596   // Allocate storage space for the result matrices:
00597   S0.set_size(k, M >> 1, false);
00598   S1.set_size(k, M >> 1, false);
00599 
00600   for (int i = 0; i < k; i++) {
00601     count0 = 0;
00602     count1 = 0;
00603     for (int j = 0; j < M; j++) {
00604       if (bitmap(j, i) == bin(0)) {
00605         S0(i, count0++) = j;
00606       }
00607       else {
00608         S1(i, count1++) = j;
00609       }
00610     }
00611   }
00612 }
00613 
00614 
00615 
00616 // ----------------------------------------------------------------------
00617 // QAM : Modulator_2D
00618 // ----------------------------------------------------------------------
00619 
00640 class QAM : public Modulator<std::complex<double> >
00641 {
00642 public:
00644   QAM() {}
00646   QAM(int M) { set_M(M); }
00648   virtual ~QAM() { }
00650   void set_M(int M);
00651 
00653   void demodulate_bits(const cvec& signal, bvec& bits) const;
00655   bvec demodulate_bits(const cvec& signal) const;
00656 
00657 protected:
00659   int L;
00661   double scaling_factor;
00662 };
00663 
00664 
00665 // ----------------------------------------------------------------------
00666 // PSK : Modulator<std::complex<double> >
00667 // ----------------------------------------------------------------------
00668 
00689 class PSK : public Modulator<std::complex<double> >
00690 {
00691 public:
00693   PSK() {}
00695   PSK(int M) { set_M(M); }
00697   virtual ~PSK() { }
00699   void set_M(int M);
00700 
00702   void demodulate_bits(const cvec& signal, bvec& bits) const;
00704   bvec demodulate_bits(const cvec& signal) const;
00705 };
00706 
00707 
00708 // ----------------------------------------------------------------------
00709 // QPSK : PSK : Modulator<std::complex<double> >
00710 // ----------------------------------------------------------------------
00711 
00731 class QPSK : public PSK
00732 {
00733 public:
00735   QPSK(): PSK(4) {}
00737   virtual ~QPSK() {}
00738 
00760   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00761                                     vec& soft_bits,
00762                                     Soft_Method method = LOGMAP) const;
00764   vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00765                            Soft_Method method = LOGMAP) const;
00766 
00767 
00790   virtual void demodulate_soft_bits(const cvec& rx_symbols,
00791                                     const cvec& channel, double N0,
00792                                     vec& soft_bits,
00793                                     Soft_Method method = LOGMAP) const;
00795   vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00796                            double N0, Soft_Method method = LOGMAP) const;
00797 };
00798 
00799 
00800 // ----------------------------------------------------------------------
00801 // BPSK_c : PSK : Modulator<std::complex<double> >
00802 // ----------------------------------------------------------------------
00803 
00829 class BPSK_c : public PSK
00830 {
00831 public:
00833   BPSK_c(): PSK(2) {}
00835   virtual ~BPSK_c() {}
00836 
00838   void modulate_bits(const bvec& bits, cvec& output) const;
00840   cvec modulate_bits(const bvec& bits) const;
00842   void demodulate_bits(const cvec& signal, bvec& output) const;
00844   bvec demodulate_bits(const cvec& signal) const;
00845 
00865   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00866                                     vec& soft_bits,
00867                                     Soft_Method method = LOGMAP) const;
00869   vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00870                            Soft_Method method = LOGMAP) const;
00871 
00892   virtual void demodulate_soft_bits(const cvec& rx_symbols,
00893                                     const cvec& channel, double N0,
00894                                     vec& soft_bits,
00895                                     Soft_Method method = LOGMAP) const;
00897   vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00898                            double N0, Soft_Method method = LOGMAP) const;
00899 };
00900 
00901 
00902 
00903 // ----------------------------------------------------------------------
00904 // BPSK : Modulator<double>
00905 // ----------------------------------------------------------------------
00906 
00930 class BPSK : public Modulator<double>
00931 {
00932 public:
00934   BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
00936   virtual ~BPSK() {}
00937 
00939   void modulate_bits(const bvec& bits, vec& output) const;
00941   vec modulate_bits(const bvec& bits) const;
00943   void demodulate_bits(const vec& signal, bvec& output) const;
00945   bvec demodulate_bits(const vec& signal) const;
00946 
00964   virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
00965                                     vec& soft_bits,
00966                                     Soft_Method method = LOGMAP) const;
00968   vec demodulate_soft_bits(const vec& rx_symbols, double N0,
00969                            Soft_Method method = LOGMAP) const;
00970 
00990   virtual void demodulate_soft_bits(const vec& rx_symbols,
00991                                     const vec& channel, double N0,
00992                                     vec& soft_bits,
00993                                     Soft_Method method = LOGMAP) const;
00995   vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
00996                            double N0, Soft_Method method = LOGMAP) const;
00997 };
00998 
00999 
01000 // ----------------------------------------------------------------------
01001 // PAM_c : Modulator<std::complex<double> >
01002 // ----------------------------------------------------------------------
01003 
01022 class PAM_c : public Modulator<std::complex<double> >
01023 {
01024 public:
01026   PAM_c() {}
01028   PAM_c(int M) { set_M(M); }
01030   virtual ~PAM_c() {}
01032   void set_M(int M);
01033 
01035   void demodulate_bits(const cvec& signal, bvec& output) const;
01037   bvec demodulate_bits(const cvec& signal) const;
01038 
01078   virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
01079                                     vec& soft_bits,
01080                                     Soft_Method method = LOGMAP) const;
01082   virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
01083                                    Soft_Method method = LOGMAP) const;
01084 
01123   virtual void demodulate_soft_bits(const cvec& rx_symbols,
01124                                     const cvec& channel, double N0,
01125                                     vec& soft_bits,
01126                                     Soft_Method method = LOGMAP) const;
01128   virtual vec demodulate_soft_bits(const cvec& rx_symbols,
01129                                    const cvec& channel, double N0,
01130                                    Soft_Method method = LOGMAP) const;
01131 
01132 protected:
01134   double scaling_factor;
01135 };
01136 
01137 
01138 // ----------------------------------------------------------------------
01139 // PAM : Modulator<double>
01140 // ----------------------------------------------------------------------
01141 
01158 class PAM : public Modulator<double>
01159 {
01160 public:
01162   PAM() {}
01164   PAM(int M) { set_M(M); }
01166   virtual ~PAM() {}
01168   void set_M(int M);
01169 
01171   void demodulate_bits(const vec& signal, bvec& output) const;
01173   bvec demodulate_bits(const vec& signal) const;
01174 
01175 protected:
01177   double scaling_factor;
01178 };
01179 
01180 } // namespace itpp
01181 
01182 #endif // #ifndef MODULATOR_H
SourceForge Logo

Generated on Thu Apr 23 20:06:42 2009 for IT++ by Doxygen 1.5.8