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
Generated on Sun Dec 9 17:38:47 2007 for IT++ by Doxygen 1.5.4