IT++ Logo
modulator.cpp
Go to the documentation of this file.
00001 
00029 #include <itpp/comm/modulator.h>
00030 #include <itpp/comm/commfunc.h>
00031 #include <itpp/base/math/elem_math.h>
00032 #include <itpp/base/specmat.h>
00033 
00034 
00035 namespace itpp
00036 {
00037 
00038 
00039 // ----------------------------------------------------------------------
00040 // QAM
00041 // ----------------------------------------------------------------------
00042 
00043 void QAM::set_M(int Mary)
00044 {
00045   k = levels2bits(Mary);
00046   M = Mary;
00047   it_assert((pow2i(k) == M) && (is_even(k)),
00048             "QAM::set_M(): M = " << M << " is not an even power of 2");
00049   L = round_i(std::sqrt(static_cast<double>(M)));
00050 
00051   double average_energy = (M - 1) * 2.0 / 3.0;
00052   scaling_factor = std::sqrt(average_energy);
00053 
00054   symbols.set_size(M);
00055   bitmap.set_size(M, k);
00056   bits2symbols.set_size(M);
00057 
00058   bmat gray_code = graycode(levels2bits(L));
00059 
00060   for (int i = 0; i < L; i++) {
00061     for (int j = 0; j < L; j++) {
00062       symbols(i*L + j) = std::complex<double>(((L - 1) - j * 2) / scaling_factor,
00063                                               ((L - 1) - i * 2) / scaling_factor);
00064       bitmap.set_row(i*L + j, concat(gray_code.get_row(i),
00065                                      gray_code.get_row(j)));
00066       bits2symbols(bin2dec(bitmap.get_row(i*L + j))) = i * L + j;
00067     }
00068   }
00069 
00070   calculate_softbit_matrices();
00071 
00072   setup_done = true;
00073 }
00074 
00075 
00076 void QAM::demodulate_bits(const cvec &signal, bvec &out) const
00077 {
00078   it_assert_debug(setup_done, "QAM::demodulate_bits(): Modulator not ready.");
00079   out.set_size(k*signal.size(), false);
00080 
00081   int temp_real, temp_imag;
00082 
00083   for (int i = 0; i < signal.size(); i++) {
00084     temp_real = round_i((L - 1) - (std::real(signal(i) * scaling_factor)
00085                                    + (L - 1)) / 2.0);
00086     temp_imag = round_i((L - 1) - (std::imag(signal(i) * scaling_factor)
00087                                    + (L - 1)) / 2.0);
00088     if (temp_real < 0)
00089       temp_real = 0;
00090     else if (temp_real > (L - 1))
00091       temp_real = (L - 1);
00092     if (temp_imag < 0)
00093       temp_imag = 0;
00094     else if (temp_imag > (L - 1))
00095       temp_imag = (L - 1);
00096     out.replace_mid(k*i, bitmap.get_row(temp_imag * L + temp_real));
00097   }
00098 }
00099 
00100 bvec QAM::demodulate_bits(const cvec &signal) const
00101 {
00102   bvec out;
00103   demodulate_bits(signal, out);
00104   return out;
00105 }
00106 
00107 
00108 // ----------------------------------------------------------------------
00109 // PSK
00110 // ----------------------------------------------------------------------
00111 
00112 void PSK::set_M(int Mary)
00113 {
00114   k = levels2bits(Mary);
00115   M = Mary;
00116   it_assert(pow2i(k) == M, "PSK::set_M(): M is not a power of 2");
00117 
00118   symbols.set_size(M);
00119   bitmap = graycode(k);
00120   bits2symbols.set_size(M);
00121 
00122   double delta = m_2pi / M;
00123   double epsilon = delta / 10000.0;
00124   std::complex<double> symb;
00125   for (int i = 0; i < M; i++) {
00126     symb = std::complex<double>(std::polar(1.0, delta * i));
00127     if (std::fabs(std::real(symb)) < epsilon) {
00128       symbols(i) = std::complex<double>(0.0, std::imag(symb));
00129     }
00130     else if (std::fabs(std::imag(symb)) < epsilon) {
00131       symbols(i) = std::complex<double>(std::real(symb), 0.0);
00132     }
00133     else {
00134       symbols(i) = symb;
00135     }
00136 
00137     bits2symbols(bin2dec(bitmap.get_row(i))) = i;
00138   }
00139 
00140   calculate_softbit_matrices();
00141 
00142   setup_done = true;
00143 }
00144 
00145 
00146 void PSK::demodulate_bits(const cvec &signal, bvec &out) const
00147 {
00148   it_assert_debug(setup_done, "PSK::demodulate_bits(): Modulator not ready.");
00149   int est_symbol;
00150   double ang, temp;
00151 
00152   out.set_size(k*signal.size(), false);
00153 
00154   for (int i = 0; i < signal.size(); i++) {
00155     ang = std::arg(signal(i));
00156     temp = (ang < 0) ? (m_2pi + ang) : ang;
00157     est_symbol = round_i(temp * (M >> 1) / pi) % M;
00158     out.replace_mid(i*k, bitmap.get_row(est_symbol));
00159   }
00160 }
00161 
00162 bvec PSK::demodulate_bits(const cvec &signal) const
00163 {
00164   bvec out;
00165   demodulate_bits(signal, out);
00166   return out;
00167 }
00168 
00169 
00170 // ----------------------------------------------------------------------
00171 // QPSK
00172 // ----------------------------------------------------------------------
00173 
00174 void QPSK::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00175                                 vec &soft_bits, Soft_Method) const
00176 {
00177   soft_bits.set_size(k * rx_symbols.size());
00178   std::complex<double> temp;
00179   double factor = 2 * std::sqrt(2.0) / N0;
00180   std::complex<double> exp_pi4 = std::complex<double>(std::cos(pi / 4),
00181                                  std::sin(pi / 4));
00182   for (int i = 0; i < rx_symbols.size(); i++) {
00183     temp = rx_symbols(i) * exp_pi4;
00184     soft_bits((i << 1) + 1) = std::real(temp) * factor;
00185     soft_bits(i << 1) = std::imag(temp) * factor;
00186   }
00187 }
00188 
00189 vec QPSK::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00190                                Soft_Method method) const
00191 {
00192   vec out;
00193   demodulate_soft_bits(rx_symbols, N0, out, method);
00194   return out;
00195 }
00196 
00197 
00198 void QPSK::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00199                                 double N0, vec &soft_bits,
00200                                 Soft_Method) const
00201 {
00202   soft_bits.set_size(2*rx_symbols.size(), false);
00203   std::complex<double> temp;
00204   double factor = 2 * std::sqrt(2.0) / N0;
00205   std::complex<double> exp_pi4 = std::complex<double>(std::cos(pi / 4),
00206                                  std::sin(pi / 4));
00207   for (int i = 0; i < rx_symbols.size(); i++) {
00208     temp = rx_symbols(i) * std::conj(channel(i)) * exp_pi4;
00209     soft_bits((i << 1) + 1) = std::real(temp) * factor;
00210     soft_bits(i << 1) = std::imag(temp) * factor;
00211   }
00212 }
00213 
00214 vec QPSK::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00215                                double N0, Soft_Method method) const
00216 {
00217   vec out;
00218   demodulate_soft_bits(rx_symbols, channel, N0, out, method);
00219   return out;
00220 }
00221 
00222 
00223 // ----------------------------------------------------------------------
00224 // BPSK_c
00225 // ----------------------------------------------------------------------
00226 
00227 void BPSK_c::modulate_bits(const bvec &bits, cvec &out) const
00228 {
00229   out.set_size(bits.size(), false);
00230   for (int i = 0; i < bits.size(); i++) {
00231     out(i) = (bits(i) == 0 ? 1.0 : -1.0);
00232   }
00233 }
00234 
00235 cvec BPSK_c::modulate_bits(const bvec &bits) const
00236 {
00237   cvec out(bits.size());
00238   modulate_bits(bits, out);
00239   return out;
00240 }
00241 
00242 
00243 void BPSK_c::demodulate_bits(const cvec &signal, bvec &out) const
00244 {
00245   out.set_size(signal.size(), false);
00246   for (int i = 0; i < signal.length(); i++) {
00247     out(i) = (std::real(signal(i)) > 0) ? bin(0) : bin(1);
00248   }
00249 }
00250 
00251 bvec BPSK_c::demodulate_bits(const cvec &signal) const
00252 {
00253   bvec out(signal.size());
00254   demodulate_bits(signal, out);
00255   return out;
00256 }
00257 
00258 
00259 void BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00260                                   vec &soft_bits, Soft_Method) const
00261 {
00262   double factor = 4 / N0;
00263   soft_bits.set_size(rx_symbols.size(), false);
00264 
00265   for (int i = 0; i < rx_symbols.size(); i++) {
00266     soft_bits(i) = factor * std::real(rx_symbols(i));
00267   }
00268 }
00269 
00270 vec BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00271                                  Soft_Method method) const
00272 {
00273   vec out;
00274   demodulate_soft_bits(rx_symbols, N0, out, method);
00275   return out;
00276 }
00277 
00278 
00279 void BPSK_c::demodulate_soft_bits(const cvec &rx_symbols,
00280                                   const cvec &channel,
00281                                   double N0, vec &soft_bits,
00282                                   Soft_Method) const
00283 {
00284   double factor = 4 / N0;
00285   soft_bits.set_size(rx_symbols.size(), false);
00286 
00287   for (int i = 0; i < rx_symbols.size(); i++) {
00288     soft_bits(i) = factor * std::real(rx_symbols(i) * std::conj(channel(i)));
00289   }
00290 }
00291 
00292 vec BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00293                                  double N0, Soft_Method method) const
00294 {
00295   vec out;
00296   demodulate_soft_bits(rx_symbols, channel, N0, out, method);
00297   return out;
00298 }
00299 
00300 
00301 // ----------------------------------------------------------------------
00302 // BPSK
00303 // ----------------------------------------------------------------------
00304 
00305 void BPSK::modulate_bits(const bvec &bits, vec &out) const
00306 {
00307   out.set_size(bits.size(), false);
00308   for (int i = 0; i < bits.size(); i++) {
00309     out(i) = (bits(i) == 0 ? 1.0 : -1.0);
00310   }
00311 }
00312 
00313 vec BPSK::modulate_bits(const bvec &bits) const
00314 {
00315   vec out(bits.size());
00316   modulate_bits(bits, out);
00317   return out;
00318 }
00319 
00320 
00321 void BPSK::demodulate_bits(const vec &signal, bvec &out) const
00322 {
00323   out.set_size(signal.size(), false);
00324   for (int i = 0; i < signal.length(); i++) {
00325     out(i) = (signal(i) > 0) ? bin(0) : bin(1);
00326   }
00327 }
00328 
00329 bvec BPSK::demodulate_bits(const vec &signal) const
00330 {
00331   bvec out(signal.size());
00332   demodulate_bits(signal, out);
00333   return out;
00334 }
00335 
00336 
00337 void BPSK::demodulate_soft_bits(const vec &rx_symbols, double N0,
00338                                 vec &soft_bits, Soft_Method) const
00339 {
00340   double factor = 4 / N0;
00341   soft_bits.set_size(rx_symbols.size(), false);
00342 
00343   for (int i = 0; i < rx_symbols.size(); i++) {
00344     soft_bits(i) = factor * rx_symbols(i);
00345   }
00346 }
00347 
00348 vec BPSK::demodulate_soft_bits(const vec &rx_symbols, double N0,
00349                                Soft_Method method) const
00350 {
00351   vec out;
00352   demodulate_soft_bits(rx_symbols, N0, out, method);
00353   return out;
00354 }
00355 
00356 
00357 void BPSK::demodulate_soft_bits(const vec &rx_symbols, const vec &channel,
00358                                 double N0, vec &soft_bits,
00359                                 Soft_Method) const
00360 {
00361   double factor = 4 / N0;
00362   soft_bits.set_size(rx_symbols.size(), false);
00363 
00364   for (int i = 0; i < rx_symbols.size(); i++) {
00365     soft_bits(i) = factor * (rx_symbols(i) * channel(i));
00366   }
00367 }
00368 
00369 vec BPSK::demodulate_soft_bits(const vec &rx_symbols, const vec &channel,
00370                                double N0, Soft_Method method) const
00371 {
00372   vec out;
00373   demodulate_soft_bits(rx_symbols, channel, N0, out, method);
00374   return out;
00375 }
00376 
00377 
00378 // ----------------------------------------------------------------------
00379 // PAM_c
00380 // ----------------------------------------------------------------------
00381 
00382 void PAM_c::set_M(int Mary)
00383 {
00384   M = Mary;
00385   k = levels2bits(M);
00386   it_assert(pow2i(k) == M, "PAM_c::set_M(): M is not a power of 2");
00387 
00388   symbols.set_size(M, false);
00389   bits2symbols.set_size(M, false);
00390   bitmap = graycode(k);
00391   double average_energy = (sqr(M) - 1) / 3.0;
00392   scaling_factor = std::sqrt(average_energy);
00393 
00394   for (int i = 0; i < M; i++) {
00395     symbols(i) = ((M - 1) - i * 2) / scaling_factor;
00396     bits2symbols(bin2dec(bitmap.get_row(i))) = i;
00397   }
00398 
00399   calculate_softbit_matrices();
00400 
00401   setup_done = true;
00402 }
00403 
00404 
00405 void PAM_c::demodulate_bits(const cvec &signal, bvec &out) const
00406 {
00407   it_assert_debug(setup_done, "PAM_c::demodulate_bits(): Modulator not ready.");
00408   int est_symbol;
00409   out.set_size(k*signal.size(), false);
00410 
00411   for (int i = 0; i < signal.size(); i++) {
00412     est_symbol = round_i((M - 1) - (std::real(signal(i)) * scaling_factor
00413                                     + (M - 1)) / 2);
00414     if (est_symbol < 0)
00415       est_symbol = 0;
00416     else if (est_symbol > (M - 1))
00417       est_symbol = M - 1;
00418     out.replace_mid(i*k, bitmap.get_row(est_symbol));
00419   }
00420 }
00421 
00422 bvec PAM_c::demodulate_bits(const cvec &signal) const
00423 {
00424   bvec temp(signal.size());
00425   demodulate_bits(signal, temp);
00426   return temp;
00427 }
00428 
00429 
00430 void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00431                                  vec &soft_bits, Soft_Method method) const
00432 {
00433   it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
00434   double P0, P1, d0min, d1min, temp;
00435   vec metric(M);
00436 
00437   soft_bits.set_size(k * rx_symbols.size());
00438 
00439   if (method == LOGMAP) {
00440     for (int l = 0; l < rx_symbols.size(); l++) {
00441       for (int j = 0; j < M; j++) {
00442         metric(j) = std::exp(-sqr(std::real(rx_symbols(l) - symbols(j)))
00443                              / N0);
00444       }
00445       for (int i = 0; i < k; i++) {
00446         P0 = P1 = 0;
00447         for (int j = 0; j < (M >> 1); j++) {
00448           P0 += metric(S0(i, j));
00449           P1 += metric(S1(i, j));
00450         }
00451         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00452       }
00453     }
00454   }
00455   else { // method == APPROX
00456     for (int l = 0; l < rx_symbols.size(); l++) {
00457       for (int j = 0; j < M; j++) {
00458         metric(j) = sqr(std::real(rx_symbols(l) - symbols(j)));
00459       }
00460       for (int i = 0; i < k; i++) {
00461         d0min = d1min = std::numeric_limits<double>::max();
00462         for (int j = 0; j < (M >> 1); j++) {
00463           temp = metric(S0(i, j));
00464           if (temp < d0min) { d0min = temp; }
00465           temp = metric(S1(i, j));
00466           if (temp < d1min) { d1min = temp; }
00467         }
00468         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00469       }
00470     }
00471   }
00472 }
00473 
00474 vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00475                                 Soft_Method method) const
00476 {
00477   vec out;
00478   demodulate_soft_bits(rx_symbols, N0, out, method);
00479   return out;
00480 }
00481 
00482 
00483 void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00484                                  double N0, vec &soft_bits,
00485                                  Soft_Method method) const
00486 {
00487   it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
00488   double P0, P1, d0min, d1min, temp;
00489   vec metric(M);
00490 
00491   soft_bits.set_size(k * rx_symbols.size());
00492 
00493   if (method == LOGMAP) {
00494     for (int l = 0; l < rx_symbols.size(); l++) {
00495       for (int j = 0; j < M; j++) {
00496         metric(j) = std::exp(-sqr(std::real(rx_symbols(l)
00497                                             - channel(l) * symbols(j))) / N0);
00498       }
00499       for (int i = 0; i < k; i++) {
00500         P0 = P1 = 0;
00501         for (int j = 0; j < (M >> 1); j++) {
00502           P0 += metric(S0(i, j));
00503           P1 += metric(S1(i, j));
00504         }
00505         soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
00506       }
00507     }
00508   }
00509   else { // method == APPROX
00510     for (int l = 0; l < rx_symbols.size(); l++) {
00511       for (int j = 0; j < M; j++) {
00512         metric(j) = sqr(std::real(rx_symbols(l) - channel(l) * symbols(j)));
00513       }
00514       for (int i = 0; i < k; i++) {
00515         d0min = d1min = std::numeric_limits<double>::max();
00516         for (int j = 0; j < (M >> 1); j++) {
00517           temp = metric(S0(i, j));
00518           if (temp < d0min) { d0min = temp; }
00519           temp = metric(S1(i, j));
00520           if (temp < d1min) { d1min = temp; }
00521         }
00522         soft_bits(l*k + i) = (-d0min + d1min) / N0;
00523       }
00524     }
00525   }
00526 }
00527 
00528 vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00529                                 double N0, Soft_Method method) const
00530 {
00531   vec out;
00532   demodulate_soft_bits(rx_symbols, channel, N0, out, method);
00533   return out;
00534 }
00535 
00536 
00537 // ----------------------------------------------------------------------
00538 // PAM
00539 // ----------------------------------------------------------------------
00540 
00541 void PAM::set_M(int Mary)
00542 {
00543   M = Mary;
00544   k = levels2bits(M);
00545   it_assert(pow2i(k) == M, "PAM::set_M(): M is not a power of 2");
00546 
00547   symbols.set_size(M, false);
00548   bits2symbols.set_size(M, false);
00549   bitmap = graycode(k);
00550   double average_energy = (sqr(M) - 1) / 3.0;
00551   scaling_factor = std::sqrt(average_energy);
00552 
00553   for (int i = 0; i < M; i++) {
00554     symbols(i) = ((M - 1) - i * 2) / scaling_factor;
00555     bits2symbols(bin2dec(bitmap.get_row(i))) = i;
00556   }
00557 
00558   calculate_softbit_matrices();
00559 
00560   setup_done = true;
00561 }
00562 
00563 
00564 void PAM::demodulate_bits(const vec &signal, bvec &out) const
00565 {
00566   it_assert_debug(setup_done, "PAM::demodulate_bits(): Modulator not ready.");
00567   int est_symbol;
00568   out.set_size(k*signal.size(), false);
00569 
00570   for (int i = 0; i < signal.size(); i++) {
00571     est_symbol = round_i((M - 1) - (signal(i) * scaling_factor + (M - 1)) / 2);
00572     if (est_symbol < 0)
00573       est_symbol = 0;
00574     else if (est_symbol > (M - 1))
00575       est_symbol = M - 1;
00576     out.replace_mid(i*k, bitmap.get_row(est_symbol));
00577   }
00578 }
00579 
00580 bvec PAM::demodulate_bits(const vec &signal) const
00581 {
00582   bvec temp(signal.size());
00583   demodulate_bits(signal, temp);
00584   return temp;
00585 }
00586 
00587 } // namespace itpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Sat Jul 9 2011 15:21:31 for IT++ by Doxygen 1.7.4