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; } 00107 virtual ivec get_bits2symbols() const { return bits2symbols; } 00108 00110 virtual void modulate(const ivec& symbolnumbers, Vec<T>& output) const; 00112 virtual Vec<T> modulate(const ivec& symbolnumbers) const; 00113 00115 virtual void demodulate(const Vec<T>& signal, ivec& output) const; 00117 virtual ivec demodulate(const Vec<T>& signal) const; 00118 00120 virtual void modulate_bits(const bvec& bits, Vec<T>& output) const; 00122 virtual Vec<T> modulate_bits(const bvec& bits) const; 00123 00125 virtual void demodulate_bits(const Vec<T>& signal, bvec& bits) const; 00127 virtual bvec demodulate_bits(const Vec<T>& signal) const; 00128 00168 virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, double N0, 00169 vec& soft_bits, 00170 Soft_Method method = LOGMAP) const; 00172 virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, double N0, 00173 Soft_Method method = LOGMAP) const; 00174 00179 virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols, 00180 double N0, vec& soft_bits) const; 00185 virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols, 00186 double N0) const; 00187 00226 virtual void demodulate_soft_bits(const Vec<T>& rx_symbols, 00227 const Vec<T>& channel, 00228 double N0, vec& soft_bits, 00229 Soft_Method method = LOGMAP) const; 00231 virtual vec demodulate_soft_bits(const Vec<T>& rx_symbols, 00232 const Vec<T>& channel, 00233 double N0, 00234 Soft_Method method = LOGMAP) const; 00235 00240 virtual void demodulate_soft_bits_approx(const Vec<T>& rx_symbols, 00241 const Vec<T>& channel, 00242 double N0, vec& soft_bits) const; 00247 virtual vec demodulate_soft_bits_approx(const Vec<T>& rx_symbols, 00248 const Vec<T>& channel, 00249 double N0) const; 00250 00251 protected: 00253 bool setup_done; 00255 int k; 00257 int M; 00259 bmat bitmap; 00261 ivec bits2symbols; 00263 Vec<T> symbols; 00266 imat S0; 00269 imat S1; 00270 00272 void calculate_softbit_matrices(const ivec& bits2symbols); 00273 }; 00274 00275 00276 // ---------------------------------------------------------------------- 00277 // Type definitions of Modulator_1D and Modulator_2D 00278 // ---------------------------------------------------------------------- 00279 00284 typedef Modulator<double> Modulator_1D; 00285 00290 typedef Modulator<std::complex<double> > Modulator_2D; 00291 00292 00293 // ---------------------------------------------------------------------- 00294 // Implementation of templated Modulator members 00295 // ---------------------------------------------------------------------- 00296 00297 template<typename T> 00298 Modulator<T>::Modulator() : 00299 setup_done(false), k(0), M(0), bitmap(""), bits2symbols(""), symbols(""), 00300 S0(""), S1("") {} 00301 00302 template<typename T> 00303 Modulator<T>::Modulator(const Vec<T> &symbols, const ivec &bits2symbols) 00304 { 00305 set(symbols, bits2symbols); 00306 } 00307 00308 template<typename T> 00309 void Modulator<T>::set(const Vec<T> &in_symbols, const ivec &in_bits2symbols) 00310 { 00311 it_assert(in_symbols.size() == in_bits2symbols.size(), 00312 "Modulator<T>::set(): Number of symbols and bits2symbols does not match"); 00313 it_assert(is_even(in_symbols.size()) && (in_symbols.size() > 0), 00314 "Modulator<T>::set(): Number of symbols needs to be even and non-zero"); 00315 it_assert((max(in_bits2symbols) == in_bits2symbols.size() - 1) 00316 && (min(in_bits2symbols) == 0), "Modulator<T>::set(): Improper bits2symbol vector"); 00317 symbols = in_symbols; 00318 bits2symbols = in_bits2symbols; 00319 M = bits2symbols.size(); 00320 k = levels2bits(M); 00321 bitmap.set_size(M, k); 00322 for (int m = 0; m < M; m++) { 00323 bitmap.set_row(bits2symbols(m), dec2bin(k, m)); 00324 } 00325 calculate_softbit_matrices(bits2symbols); 00326 setup_done = true; 00327 } 00328 00329 00330 template<typename T> 00331 void Modulator<T>::modulate(const ivec &symbolnumbers, Vec<T>& output) const 00332 { 00333 it_assert_debug(setup_done, "Modulator<T>::modulate(): Modulator not ready."); 00334 output.set_size(symbolnumbers.length()); 00335 for (int i = 0; i < symbolnumbers.length(); i++) 00336 output(i) = symbols(symbolnumbers(i)); 00337 } 00338 00339 template<typename T> 00340 Vec<T> Modulator<T>::modulate(const ivec &symbolnumbers) const 00341 { 00342 Vec<T> output(symbolnumbers.length()); 00343 modulate(symbolnumbers, output); 00344 return output; 00345 } 00346 00347 00348 template<typename T> 00349 void Modulator<T>::demodulate(const Vec<T> &signal, ivec& output) const 00350 { 00351 it_assert_debug(setup_done, "Modulator<T>::demodulate(): Modulator not ready."); 00352 double dist, mindist; 00353 int closest; 00354 output.set_size(signal.size()); 00355 00356 for (int i = 0; i < signal.size(); i++) { 00357 mindist = std::abs(symbols(0) - signal(i)); 00358 closest = 0; 00359 for (int j = 1; j < M; j++) { 00360 dist = std::abs(symbols(j) - signal(i)); 00361 if (dist < mindist) { 00362 mindist = dist; 00363 closest = j; 00364 } 00365 } 00366 output(i) = closest; 00367 } 00368 } 00369 00370 template<typename T> 00371 ivec Modulator<T>::demodulate(const Vec<T>& signal) const 00372 { 00373 ivec output(signal.length()); 00374 demodulate(signal, output); 00375 return output; 00376 } 00377 00378 00379 template<typename T> 00380 void Modulator<T>::modulate_bits(const bvec &bits, Vec<T> &output) const 00381 { 00382 it_assert_debug(setup_done, "Modulator<T>::modulate_bits(): Modulator not ready."); 00383 // Check if some bits have to be cut and print warning message in such 00384 // case. 00385 if (bits.length() % k) { 00386 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."); 00387 } 00388 int no_symbols = bits.length() / k; 00389 output.set_size(no_symbols); 00390 for (int i = 0; i < no_symbols; i++) { 00391 output(i) = symbols(bits2symbols(bin2dec(bits.mid(i*k, k)))); 00392 } 00393 } 00394 00395 template<typename T> 00396 Vec<T> Modulator<T>::modulate_bits(const bvec &bits) const 00397 { 00398 Vec<T> output; 00399 modulate_bits(bits, output); 00400 return output; 00401 } 00402 00403 template<typename T> 00404 void Modulator<T>::demodulate_bits(const Vec<T> &signal, bvec &bits) const 00405 { 00406 it_assert_debug(setup_done, "Modulator<T>::demodulate_bist(): Modulator not ready."); 00407 double dist, mindist; 00408 int closest; 00409 bits.set_size(k*signal.size()); 00410 00411 for (int i = 0; i < signal.size(); i++) { 00412 mindist = std::abs(symbols(0) - signal(i)); 00413 closest = 0; 00414 for (int j = 1; j < M; j++) { 00415 dist = std::abs(symbols(j) - signal(i)); 00416 if (dist < mindist) { 00417 mindist = dist; 00418 closest = j; 00419 } 00420 } 00421 bits.replace_mid(i*k, bitmap.get_row(closest)); 00422 } 00423 } 00424 00425 template<typename T> 00426 bvec Modulator<T>::demodulate_bits(const Vec<T> &signal) const 00427 { 00428 bvec bits; 00429 demodulate_bits(signal, bits); 00430 return bits; 00431 } 00432 00433 00434 template<typename T> 00435 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, double N0, 00436 vec &soft_bits, 00437 Soft_Method method) const 00438 { 00439 it_assert_debug(setup_done, "Modulator<T>::demodulate_soft_bits(): Modulator not ready."); 00440 double P0, P1, d0min, d1min, temp; 00441 vec metric(M); 00442 00443 soft_bits.set_size(k * rx_symbols.size()); 00444 00445 if (method == LOGMAP) { 00446 for (int l = 0; l < rx_symbols.size(); l++) { 00447 for (int j = 0; j < M; j++) { 00448 metric(j) = std::exp(-sqr(rx_symbols(l) - symbols(j)) / N0); 00449 } 00450 for (int i = 0; i < k; i++) { 00451 P0 = P1 = 0; 00452 for (int j = 0; j < (M >> 1); j++) { 00453 P0 += metric(S0(i, j)); 00454 P1 += metric(S1(i, j)); 00455 } 00456 soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1); 00457 } 00458 } 00459 } 00460 else { // method == APPROX 00461 for (int l = 0; l < rx_symbols.size(); l++) { 00462 for (int j = 0; j < M; j++) { 00463 metric(j) = sqr(rx_symbols(l) - symbols(j)); 00464 } 00465 for (int i = 0; i < k; i++) { 00466 d0min = d1min = std::numeric_limits<double>::max(); 00467 for (int j = 0; j < (M >> 1); j++) { 00468 temp = metric(S0(i, j)); 00469 if (temp < d0min) { d0min = temp; } 00470 temp = metric(S1(i, j)); 00471 if (temp < d1min) { d1min = temp; } 00472 } 00473 soft_bits(l*k+i) = (-d0min + d1min) / N0; 00474 } 00475 } 00476 } 00477 } 00478 00479 template<typename T> 00480 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, 00481 double N0, 00482 Soft_Method method) const 00483 { 00484 vec output; 00485 demodulate_soft_bits(rx_symbols, N0, output, method); 00486 return output; 00487 } 00488 00489 template<typename T> 00490 void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols, 00491 double N0, 00492 vec &soft_bits) const 00493 { 00494 it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead."); 00495 demodulate_soft_bits(rx_symbols, N0, soft_bits, APPROX); 00496 } 00497 00498 template<typename T> 00499 vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols, 00500 double N0) const 00501 { 00502 it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead."); 00503 vec output; 00504 demodulate_soft_bits(rx_symbols, N0, output, APPROX); 00505 return output; 00506 } 00507 00508 00509 template<typename T> 00510 void Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, 00511 const Vec<T> &channel, double N0, 00512 vec &soft_bits, 00513 Soft_Method method) const 00514 { 00515 it_assert_debug(setup_done, "Modulator_2D::demodulate_soft_bits(): Modulator not ready."); 00516 double P0, P1, d0min, d1min, temp; 00517 vec metric(M); 00518 00519 soft_bits.set_size(k * rx_symbols.size()); 00520 00521 if (method == LOGMAP) { 00522 for (int l = 0; l < rx_symbols.size(); l++) { 00523 for (int j = 0; j < M; j++) { 00524 metric(j) = std::exp(-sqr(rx_symbols(l) - channel(l) * symbols(j)) 00525 / N0); 00526 } 00527 for (int i = 0; i < k; i++) { 00528 P0 = P1 = 0; 00529 for (int j = 0; j < (M >> 1); j++) { 00530 P0 += metric(S0(i, j)); 00531 P1 += metric(S1(i, j)); 00532 } 00533 soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1); 00534 } 00535 } 00536 } 00537 else { // method == APPROX 00538 for (int l = 0; l < rx_symbols.size(); l++) { 00539 for (int j = 0; j < M; j++) { 00540 metric(j) = sqr(rx_symbols(l) - channel(l) * symbols(j)); 00541 } 00542 for (int i = 0; i < k; i++) { 00543 d0min = d1min = std::numeric_limits<double>::max(); 00544 for (int j = 0; j < (M >> 1); j++) { 00545 temp = metric(S0(i, j)); 00546 if (temp < d0min) { d0min = temp; } 00547 temp = metric(S1(i, j)); 00548 if (temp < d1min) { d1min = temp; } 00549 } 00550 soft_bits(l*k+i) = (-d0min + d1min) / N0; 00551 } 00552 } 00553 } 00554 } 00555 00556 template<typename T> 00557 vec Modulator<T>::demodulate_soft_bits(const Vec<T> &rx_symbols, 00558 const Vec<T> &channel, 00559 double N0, 00560 Soft_Method method) const 00561 { 00562 vec output; 00563 demodulate_soft_bits(rx_symbols, channel, N0, output, method); 00564 return output; 00565 } 00566 00567 template<typename T> 00568 void Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols, 00569 const Vec<T> &channel, 00570 double N0, 00571 vec &soft_bits) const 00572 { 00573 it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead."); 00574 demodulate_soft_bits(rx_symbols, channel, N0, soft_bits, APPROX); 00575 } 00576 00577 template<typename T> 00578 vec Modulator<T>::demodulate_soft_bits_approx(const Vec<T> &rx_symbols, 00579 const Vec<T> &channel, 00580 double N0) const 00581 { 00582 it_warning("Modulator<T>::demodulate_soft_bits_approx(): This function is deprecated. Please use demodulate_soft_bits() with method=APPROX instead."); 00583 vec output; 00584 demodulate_soft_bits(rx_symbols, channel, N0, output, APPROX); 00585 return output; 00586 } 00587 00588 00589 template<typename T> 00590 void Modulator<T>::calculate_softbit_matrices(const ivec& in_bits2symbols) 00591 { 00592 int count0, count1; 00593 00594 // Allocate storage space for the result matrices: 00595 S0.set_size(k, M >> 1, false); 00596 S1.set_size(k, M >> 1, false); 00597 00598 for (int i = 0; i < k; i++) { 00599 count0 = 0; 00600 count1 = 0; 00601 for (int j = 0; j < M; j++) { 00602 if (bitmap(j, i) == bin(0)) { 00603 S0(i, count0++) = j; 00604 } 00605 else { 00606 S1(i, count1++) = j; 00607 } 00608 } 00609 } 00610 } 00611 00612 00613 00614 // ---------------------------------------------------------------------- 00615 // QAM : Modulator_2D 00616 // ---------------------------------------------------------------------- 00617 00638 class QAM : public Modulator<std::complex<double> > { 00639 public: 00641 QAM() {} 00643 QAM(int M) { set_M(M); } 00645 virtual ~QAM() { } 00647 void set_M(int M); 00648 00650 void demodulate_bits(const cvec& signal, bvec& bits) const; 00652 bvec demodulate_bits(const cvec& signal) const; 00653 00654 protected: 00656 int L; 00658 double scaling_factor; 00659 }; 00660 00661 00662 // ---------------------------------------------------------------------- 00663 // PSK : Modulator<std::complex<double> > 00664 // ---------------------------------------------------------------------- 00665 00686 class PSK : public Modulator<std::complex<double> > { 00687 public: 00689 PSK() {} 00691 PSK(int M) { set_M(M); } 00693 virtual ~PSK() { } 00695 void set_M(int M); 00696 00698 void demodulate_bits(const cvec& signal, bvec& bits) const; 00700 bvec demodulate_bits(const cvec& signal) const; 00701 }; 00702 00703 00704 // ---------------------------------------------------------------------- 00705 // QPSK : PSK : Modulator<std::complex<double> > 00706 // ---------------------------------------------------------------------- 00707 00727 class QPSK : public PSK { 00728 public: 00730 QPSK(): PSK(4) {} 00732 virtual ~QPSK() {} 00733 00755 virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0, 00756 vec& soft_bits, 00757 Soft_Method method = LOGMAP) const; 00759 vec demodulate_soft_bits(const cvec& rx_symbols, double N0, 00760 Soft_Method method = LOGMAP) const; 00761 00762 00785 virtual void demodulate_soft_bits(const cvec& rx_symbols, 00786 const cvec& channel, double N0, 00787 vec& soft_bits, 00788 Soft_Method method = LOGMAP) const; 00790 vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel, 00791 double N0, Soft_Method method = LOGMAP) const; 00792 }; 00793 00794 00795 // ---------------------------------------------------------------------- 00796 // BPSK_c : PSK : Modulator<std::complex<double> > 00797 // ---------------------------------------------------------------------- 00798 00824 class BPSK_c : public PSK { 00825 public: 00827 BPSK_c(): PSK(2) {} 00829 virtual ~BPSK_c() {} 00830 00832 void modulate_bits(const bvec& bits, cvec& output) const; 00834 cvec modulate_bits(const bvec& bits) const; 00836 void demodulate_bits(const cvec& signal, bvec& output) const; 00838 bvec demodulate_bits(const cvec& signal) const; 00839 00859 virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0, 00860 vec& soft_bits, 00861 Soft_Method method = LOGMAP) const; 00863 vec demodulate_soft_bits(const cvec& rx_symbols, double N0, 00864 Soft_Method method = LOGMAP) const; 00865 00886 virtual void demodulate_soft_bits(const cvec& rx_symbols, 00887 const cvec& channel, double N0, 00888 vec& soft_bits, 00889 Soft_Method method = LOGMAP) const; 00891 vec demodulate_soft_bits(const cvec& rx_symbols, const cvec& channel, 00892 double N0, Soft_Method method = LOGMAP) const; 00893 }; 00894 00895 00896 00897 // ---------------------------------------------------------------------- 00898 // BPSK : Modulator<double> 00899 // ---------------------------------------------------------------------- 00900 00924 class BPSK : public Modulator<double> { 00925 public: 00927 BPSK(): Modulator<double>("1.0 -1.0", "0 1") {} 00929 virtual ~BPSK() {} 00930 00932 void modulate_bits(const bvec& bits, vec& output) const; 00934 vec modulate_bits(const bvec& bits) const; 00936 void demodulate_bits(const vec& signal, bvec& output) const; 00938 bvec demodulate_bits(const vec& signal) const; 00939 00957 virtual void demodulate_soft_bits(const vec& rx_symbols, double N0, 00958 vec& soft_bits, 00959 Soft_Method method = LOGMAP) const; 00961 vec demodulate_soft_bits(const vec& rx_symbols, double N0, 00962 Soft_Method method = LOGMAP) const; 00963 00983 virtual void demodulate_soft_bits(const vec& rx_symbols, 00984 const vec& channel, double N0, 00985 vec& soft_bits, 00986 Soft_Method method = LOGMAP) const; 00988 vec demodulate_soft_bits(const vec& rx_symbols, const vec& channel, 00989 double N0, Soft_Method method = LOGMAP) const; 00990 }; 00991 00992 00993 // ---------------------------------------------------------------------- 00994 // PAM_c : Modulator<std::complex<double> > 00995 // ---------------------------------------------------------------------- 00996 01015 class PAM_c : public Modulator<std::complex<double> > { 01016 public: 01018 PAM_c() {} 01020 PAM_c(int M) { set_M(M); } 01022 virtual ~PAM_c() {} 01024 void set_M(int M); 01025 01027 void demodulate_bits(const cvec& signal, bvec& output) const; 01029 bvec demodulate_bits(const cvec& signal) const; 01030 01070 virtual void demodulate_soft_bits(const cvec& rx_symbols, double N0, 01071 vec& soft_bits, 01072 Soft_Method method = LOGMAP) const; 01074 virtual vec demodulate_soft_bits(const cvec& rx_symbols, double N0, 01075 Soft_Method method = LOGMAP) const; 01076 01115 virtual void demodulate_soft_bits(const cvec& rx_symbols, 01116 const cvec& channel, double N0, 01117 vec& soft_bits, 01118 Soft_Method method = LOGMAP) const; 01120 virtual vec demodulate_soft_bits(const cvec& rx_symbols, 01121 const cvec& channel, double N0, 01122 Soft_Method method = LOGMAP) const; 01123 01124 protected: 01126 double scaling_factor; 01127 }; 01128 01129 01130 // ---------------------------------------------------------------------- 01131 // PAM : Modulator<double> 01132 // ---------------------------------------------------------------------- 01133 01150 class PAM : public Modulator<double> { 01151 public: 01153 PAM() {} 01155 PAM(int M) { set_M(M); } 01157 virtual ~PAM() {} 01159 void set_M(int M); 01160 01162 void demodulate_bits(const vec& signal, bvec& output) const; 01164 bvec demodulate_bits(const vec& signal) const; 01165 01166 protected: 01168 double scaling_factor; 01169 }; 01170 01171 } // namespace itpp 01172 01173 #endif // #ifndef MODULATOR_H
Generated on Sat Apr 19 10:43:54 2008 for IT++ by Doxygen 1.5.5