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 
00046   enum Soft_Method {
00047     LOGMAP,                     
00048     APPROX                      
00049   };
00050 
00073   template <typename T>
00074   class Modulator {
00075   public:
00077     Modulator();
00079     Modulator(const Vec<T>& symbols, const ivec& bits2symbols);
00081     virtual ~Modulator() {}
00082 
00084     virtual void set(const Vec<T>& symbols, const ivec& bits2symbols);
00085 
00087     virtual int bits_per_symbol() const { return k; }
00089     virtual Vec<T> get_symbols() const { return symbols; }
00091     virtual ivec get_bits2symbols() const { return bits2symbols; }
00092 
00094     virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const;
00096     virtual Vec<T> modulate(const ivec& symbolnumbers) const;
00097 
00099     virtual void demodulate(const Vec<T>& signal, ivec& output) const;
00101     virtual ivec demodulate(const Vec<T>& signal) const;
00102 
00104     virtual void modulate_bits(const bvec& bits, Vec<T>& output) const;
00106     virtual Vec<T> modulate_bits(const bvec& bits) const;
00107 
00109     virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const;
00111     virtual bvec demodulate_bits(const Vec<T>& signal) const;
00112 
00152     virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00153                                       vec& soft_bits,
00154                                       Soft_Method method = LOGMAP) const;
00156     virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0,
00157                                      Soft_Method method = LOGMAP) const;
00158 
00163     virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00164                                              double N0, vec& soft_bits) const;
00169     virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00170                                             double N0) const;
00171 
00210     virtual void demodulate_soft_bits(const Vec<T>& rx_symbols,
00211                                       const Vec<T>& channel,
00212                                       double N0, vec& soft_bits,
00213                                       Soft_Method method = LOGMAP) const;
00215     virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols,
00216                                      const Vec<T>& channel,
00217                                      double N0,
00218                                      Soft_Method method = LOGMAP) const;
00219 
00224     virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00225                                              const Vec<T>& channel,
00226                                              double N0, vec& soft_bits) const;
00231     virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols,
00232                                             const Vec<T>& channel,
00233                                             double N0) const;
00234 
00235   protected:
00237     bool setup_done;
00239     int k;
00241     int M;
00243     bmat bitmap;
00245     ivec bits2symbols;
00247     Vec<T> symbols;
00250     imat S0;
00253     imat S1;
00254 
00256     void calculate_softbit_matrices(const ivec& bits2symbols);
00257   };
00258 
00259 
00260   // ----------------------------------------------------------------------
00261   // Type definitions of Modulator_1D and Modulator_2D
00262   // ----------------------------------------------------------------------
00263 
00268   typedef Modulator<double> Modulator_1D;
00269 
00274   typedef Modulator<std::complex<double> > Modulator_2D;
00275 
00276 
00277   // ----------------------------------------------------------------------
00278   // Implementation of templated Modulator members
00279   // ----------------------------------------------------------------------
00280 
00281   template<typename T>
00282   Modulator<T>::Modulator() :
00283     setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""),
00284     S0(""), S1("") {}
00285 
00286   template<typename T>
00287   Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols)
00288   {
00289     set(symbols, bits2symbols);
00290   }
00291 
00292   template<typename T>
00293   void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols)
00294   {
00295     it_assert(in_symbols.size() == in_bits2symbols.size(),
00296               "Modulator<T>::set(): Number of symbols and bits2symbols does not match");
00297     it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0),
00298               "Modulator<T>::set(): Number of symbols needs to be even and non-zero");
00299     it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1)
00300               && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector");
00301     symbols = in_symbols;
00302     bits2symbols = in_bits2symbols;
00303     M = bits2symbols.size();
00304     k = levels2bits(M);
00305     bitmap.set_size(M, k);
00306     for (int m = 0; m < M; m++) {
00307       bitmap.set_row(m, dec2bin(k, bits2symbols(m)));
00308     }
00309     calculate_softbit_matrices(bits2symbols);
00310     setup_done = true;
00311   }
00312 
00313 
00314   template<typename T>
00315   void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const
00316   {
00317     it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready.");
00318     output.set_size(symbolnumbers.length());
00319     for (int i = 0; i < symbolnumbers.length(); i++)
00320       output(i) = symbols(symbolnumbers(i));
00321   }
00322 
00323   template<typename T>
00324   Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const
00325   {
00326     Vec<T> output(symbolnumbers.length());
00327     modulate(symbolnumbers, output);
00328     return output;
00329   }
00330 
00331 
00332   template<typename T>
00333   void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const
00334   {
00335     it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready.");
00336     double dist, mindist;
00337     int closest;
00338     output.set_size(signal.size());
00339 
00340     for (int i = 0; i < signal.size(); i++) {
00341       mindist = std::abs(symbols(0) - signal(i));
00342       closest = 0;
00343       for (int j = 1; j < M; j++) {
00344         dist = std::abs(symbols(j) - signal(i));
00345         if (dist < mindist) {
00346           mindist = dist;
00347           closest = j;
00348         }
00349       }
00350       output(i) = closest;
00351     }
00352   }
00353 
00354   template<typename T>
00355   ivec Modulator<T>::demodulate(const Vec<T>& signal) const
00356   {
00357     ivec output(signal.length());
00358     demodulate(signal, output);
00359     return output;
00360   }
00361 
00362 
00363   template<typename T>
00364   void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const
00365   {
00366     it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready.");
00367     // Check if some bits have to be cut and print warning message in such
00368     // case.
00369     if (bits.length() % k) {
00370       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.");
00371     }
00372     int no_symbols = bits.length() / k;
00373     output.set_size(no_symbols);
00374     for (int i = 0; i < no_symbols; i++) {
00375       output(i) = symbols(bits2symbols(bin2dec(bits.mid(i*k, k))));
00376     }
00377   }
00378 
00379   template<typename T>
00380   Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const
00381   {
00382     Vec<T> output;
00383     modulate_bits(bits, output);
00384     return output;
00385   }
00386 
00387   template<typename T>
00388   void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const
00389   {
00390     it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready.");
00391     double dist, mindist;
00392     int closest;
00393     bits.set_size(k*signal.size());
00394 
00395     for (int i = 0; i < signal.size(); i++) {
00396       mindist = std::abs(symbols(0) - signal(i));
00397       closest = 0;
00398       for (int j = 1; j < M; j++) {
00399         dist = std::abs(symbols(j) - signal(i));
00400         if (dist < mindist) {
00401           mindist = dist;
00402           closest = j;
00403         }
00404       }
00405       bits.replace_mid(i*k, bitmap.get_row(closest));
00406     }
00407   }
00408 
00409   template<typename T>
00410   bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const
00411   {
00412     bvec bits;
00413     demodulate_bits(signal, bits);
00414     return bits;
00415   }
00416 
00417 
00418   template<typename T>
00419   void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0,
00420                                           vec &soft_bits,
00421                                           Soft_Method method) const
00422   {
00423     it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready.");
00424     double P0, P1, d0min, d1min, temp;
00425     vec metric(M);
00426 
00427     soft_bits.set_size(k * rx_symbols.size());
00428 
00429     if (method == LOGMAP) {
00430       for (int l = 0; l < rx_symbols.size(); l++) {
00431         for (int j = 0; j < M; j++) {
00432           metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0);
00433         }
00434         for (int i = 0; i < k; i++) {
00435           P0 = P1 = 0;
00436           for (int j = 0; j < (M >> 1); j++) {
00437             P0 += metric(S0(i, j));
00438             P1 += metric(S1(i, j));
00439           }
00440           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00441         }
00442       }
00443     }
00444     else { // method == APPROX
00445       for (int l = 0; l < rx_symbols.size(); l++) {
00446         for (int j = 0; j < M; j++) {
00447           metric(j) = sqr(rx_symbols(l) - symbols(j));
00448         }
00449         for (int i = 0; i < k; i++) {
00450           d0min = d1min = std::numeric_limits<double>::max();
00451           for (int j = 0; j < (M >> 1); j++) {
00452             temp = metric(S0(i, j));
00453             if (temp < d0min) { d0min = temp; }
00454             temp = metric(S1(i, j));
00455             if (temp < d1min) { d1min = temp; }
00456           }
00457           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00458         }
00459       }
00460     }
00461   }
00462 
00463   template<typename T>
00464   vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00465                                          double N0,
00466                                          Soft_Method method) const
00467   {
00468     vec output;
00469     demodulate_soft_bits(rx_symbols, N0, output, method);
00470     return output;
00471   }
00472 
00473   template<typename T>
00474   void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00475                                                  double N0,
00476                                                  vec &soft_bits) const
00477   {
00478     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00479     demodulate_soft_bits(rx_symbols, N0, soft_bits, APPROX);
00480   }
00481 
00482   template<typename T>
00483   vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00484                                                 double N0) const
00485   {
00486     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00487     vec output;
00488     demodulate_soft_bits(rx_symbols, N0, output, APPROX);
00489     return output;
00490   }
00491 
00492 
00493   template<typename T>
00494   void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00495                                           const Vec<T> &channel, double N0,
00496                                           vec &soft_bits,
00497                                           Soft_Method method) const
00498   {
00499     it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready.");
00500     double P0, P1, d0min, d1min, temp;
00501     vec metric(M);
00502 
00503     soft_bits.set_size(k * rx_symbols.size());
00504 
00505     if (method == LOGMAP) {
00506       for (int l = 0; l < rx_symbols.size(); l++) {
00507         for (int j = 0; j < M; j++) {
00508           metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j))
00509                                / N0);
00510         }
00511         for (int i = 0; i < k; i++) {
00512           P0 = P1 = 0;
00513           for (int j = 0; j < (M >> 1); j++) {
00514             P0 += metric(S0(i, j));
00515             P1 += metric(S1(i, j));
00516           }
00517           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00518         }
00519       }
00520     }
00521     else { // method == APPROX
00522       for (int l = 0; l < rx_symbols.size(); l++) {
00523         for (int j = 0; j < M; j++) {
00524           metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j));
00525         }
00526         for (int i = 0; i < k; i++) {
00527           d0min = d1min = std::numeric_limits<double>::max();
00528           for (int j = 0; j < (M >> 1); j++) {
00529             temp = metric(S0(i, j));
00530             if (temp < d0min) { d0min = temp; }
00531             temp = metric(S1(i, j));
00532             if (temp < d1min) { d1min = temp; }
00533           }
00534           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00535         }
00536       }
00537     }
00538   }
00539 
00540   template<typename T>
00541   vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols,
00542                                          const Vec<T> &channel,
00543                                          double N0,
00544                                          Soft_Method method) const
00545   {
00546     vec output;
00547     demodulate_soft_bits(rx_symbols, channel, N0, output, method);
00548     return output;
00549   }
00550 
00551   template<typename T>
00552   void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00553                                                  const Vec<T> &channel,
00554                                                  double N0,
00555                                                  vec &soft_bits) const
00556   {
00557     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00558     demodulate_soft_bits(rx_symbols, channel, N0, soft_bits, APPROX);
00559   }
00560 
00561   template<typename T>
00562   vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols,
00563                                                 const Vec<T> &channel,
00564                                                 double N0) const
00565   {
00566     it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead.");
00567     vec output;
00568     demodulate_soft_bits(rx_symbols, channel, N0, output, APPROX);
00569     return output;
00570   }
00571 
00572 
00573   template<typename T>
00574   void Modulator<T>::calculate_softbit_matrices(const ivec& in_bits2symbols)
00575   {
00576     int count0, count1;
00577 
00578     // Allocate storage space for the result matrices:
00579     S0.set_size(k, M >> 1, false);
00580     S1.set_size(k, M >> 1, false);
00581 
00582     for (int i = 0; i < k; i++) {
00583       count0 = 0;
00584       count1 = 0;
00585       for (int j = 0; j < M; j++) {
00586         if (bitmap(j, i) == bin(0)) {
00587           S0(i, count0++) = j;
00588         }
00589         else {
00590           S1(i, count1++) = j;
00591         }
00592       }
00593     }
00594   }
00595 
00596 
00597 
00598   // ----------------------------------------------------------------------
00599   // QAM : Modulator_2D
00600   // ----------------------------------------------------------------------
00601 
00622   class QAM : public Modulator<std::complex<double> > {
00623   public:
00625     QAM() {}
00627     QAM(int M) { set_M(M); }
00629     virtual ~QAM() { }
00631     void set_M(int M);
00632 
00634     void demodulate_bits(const cvec& signal, bvec& bits) const;
00636     bvec demodulate_bits(const cvec& signal) const;
00637 
00638   protected:
00640     int L;
00642     double scaling_factor;
00643   };
00644 
00645 
00646   // ----------------------------------------------------------------------
00647   // PSK : Modulator<std::complex<double> >
00648   // ----------------------------------------------------------------------
00649 
00670   class PSK : public Modulator<std::complex<double> > {
00671   public:
00673     PSK() {}
00675     PSK(int M) { set_M(M); }
00677     virtual ~PSK() { }
00679     void set_M(int M);
00680 
00682     void demodulate_bits(const cvec& signal, bvec& bits) const;
00684     bvec demodulate_bits(const cvec& signal) const;
00685   };
00686 
00687 
00688   // ----------------------------------------------------------------------
00689   // QPSK : PSK : Modulator<std::complex<double> >
00690   // ----------------------------------------------------------------------
00691 
00711   class QPSK : public PSK {
00712   public:
00714     QPSK(): PSK(4) {}
00716     virtual ~QPSK() {}
00717 
00739     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00740                                       vec& soft_bits,
00741                                       Soft_Method method = LOGMAP) const;
00743     vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00744                              Soft_Method method = LOGMAP) const;
00745 
00746 
00769     virtual void demodulate_soft_bits(const cvec& rx_symbols,
00770                                       const cvec& channel, double N0,
00771                                       vec& soft_bits,
00772                                       Soft_Method method = LOGMAP) const;
00774     vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00775                              double N0, Soft_Method method = LOGMAP) const;
00776   };
00777 
00778 
00779   // ----------------------------------------------------------------------
00780   // BPSK_c : PSK : Modulator<std::complex<double> >
00781   // ----------------------------------------------------------------------
00782 
00808   class BPSK_c : public PSK {
00809   public:
00811     BPSK_c(): PSK(2) {}
00813     virtual ~BPSK_c() {}
00814 
00816     void modulate_bits(const bvec& bits, cvec& output) const;
00818     cvec modulate_bits(const bvec& bits) const;
00820     void demodulate_bits(const cvec& signal, bvec& output) const;
00822     bvec demodulate_bits(const cvec& signal) const;
00823 
00843     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
00844                                       vec& soft_bits,
00845                                       Soft_Method method = LOGMAP) const;
00847     vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
00848                              Soft_Method method = LOGMAP) const;
00849 
00870     virtual void demodulate_soft_bits(const cvec& rx_symbols,
00871                                       const cvec& channel, double N0,
00872                                       vec& soft_bits,
00873                                       Soft_Method method = LOGMAP) const;
00875     vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel,
00876                              double N0, Soft_Method method = LOGMAP) const;
00877   };
00878 
00879 
00880 
00881   // ----------------------------------------------------------------------
00882   // BPSK : Modulator<double>
00883   // ----------------------------------------------------------------------
00884 
00908   class BPSK : public Modulator<double> {
00909   public:
00911     BPSK(): Modulator<double>("1.0 -1.0", "0 1") {}
00913     virtual ~BPSK() {}
00914 
00916     void modulate_bits(const bvec& bits, vec& output) const;
00918     vec modulate_bits(const bvec& bits) const;
00920     void demodulate_bits(const vec& signal, bvec& output) const;
00922     bvec demodulate_bits(const vec& signal) const;
00923 
00941     virtual void demodulate_soft_bits(const vec& rx_symbols, double N0,
00942                                       vec& soft_bits,
00943                                       Soft_Method method = LOGMAP) const;
00945     vec demodulate_soft_bits(const vec& rx_symbols, double N0,
00946                              Soft_Method method = LOGMAP) const;
00947 
00967     virtual void demodulate_soft_bits(const vec& rx_symbols,
00968                                       const vec& channel, double N0,
00969                                       vec& soft_bits,
00970                                       Soft_Method method = LOGMAP) const;
00972     vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel,
00973                              double N0, Soft_Method method = LOGMAP) const;
00974   };
00975 
00976 
00977   // ----------------------------------------------------------------------
00978   // PAM_c : Modulator<std::complex<double> >
00979   // ----------------------------------------------------------------------
00980 
00999   class PAM_c : public Modulator<std::complex<double> > {
01000   public:
01002     PAM_c() {}
01004     PAM_c(int M) { set_M(M); }
01006     virtual ~PAM_c() {}
01008     void set_M(int M);
01009 
01011     void demodulate_bits(const cvec& signal, bvec& output) const;
01013     bvec demodulate_bits(const cvec& signal) const;
01014 
01054     virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0,
01055                                       vec& soft_bits,
01056                                       Soft_Method method = LOGMAP) const;
01058     virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0,
01059                                      Soft_Method method = LOGMAP) const;
01060 
01099     virtual void demodulate_soft_bits(const cvec& rx_symbols,
01100                                       const cvec& channel, double N0,
01101                                       vec& soft_bits,
01102                                       Soft_Method method = LOGMAP) const;
01104     virtual vec demodulate_soft_bits(const cvec& rx_symbols,
01105                                      const cvec& channel, double N0,
01106                                      Soft_Method method = LOGMAP) const;
01107 
01108   protected:
01110     double scaling_factor;
01111   };
01112 
01113 
01114   // ----------------------------------------------------------------------
01115   // PAM : Modulator<double>
01116   // ----------------------------------------------------------------------
01117 
01134   class PAM : public Modulator<double> {
01135   public:
01137     PAM() {}
01139     PAM(int M) { set_M(M); }
01141     virtual ~PAM() {}
01143     void set_M(int M);
01144 
01146     void demodulate_bits(const vec& signal, bvec& output) const;
01148     bvec demodulate_bits(const vec& signal) const;
01149 
01150   protected:
01152     double scaling_factor;
01153   };
01154 
01155 } // namespace itpp
01156 
01157 #endif // #ifndef MODULATOR_H
SourceForge Logo

Generated on Thu Apr 24 13:39:00 2008 for IT++ by Doxygen 1.5.5