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
00251
00252
00257 typedef Modulator<double> Modulator_1D;
00258
00263 typedef Modulator<std::complex<double> > Modulator_2D;
00264
00265
00266
00267
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
00357
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 {
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 {
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
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
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
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
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
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
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
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
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 }
01110
01111 #endif // #ifndef MODULATOR_H