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
Generated on Sun Jul 26 08:36:51 2009 for IT++ by Doxygen 1.5.9