IT++ Logo

modulator.cpp

Go to the documentation of this file.
00001 
00030 #include <itpp/comm/modulator.h>
00031 #include <itpp/comm/commfunc.h>
00032 #include <itpp/base/math/elem_math.h>
00033 #include <itpp/base/specmat.h>
00034 
00035 
00036 namespace itpp {
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(bits2symbols);
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(bits2symbols);
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 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 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 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 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 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 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 the soft bit mapping matrices S0 and S1
00400     calculate_softbit_matrices(bits2symbols);
00401 
00402     setup_done = true;
00403   }
00404 
00405 
00406   void PAM_c::demodulate_bits(const cvec &signal, bvec &out) const
00407   {
00408     it_assert_debug(setup_done, "PAM_c::demodulate_bits(): Modulator not ready.");
00409     int est_symbol;
00410     out.set_size(k*signal.size(), false);
00411 
00412     for (int i = 0; i < signal.size(); i++) {
00413       est_symbol = round_i((M-1) - (std::real(signal(i)) * scaling_factor
00414                                     + (M-1)) / 2);
00415       if (est_symbol < 0)
00416         est_symbol = 0;
00417       else if (est_symbol > (M-1))
00418         est_symbol = M-1;
00419       out.replace_mid(i*k, bitmap.get_row(est_symbol));
00420     }
00421   }
00422 
00423   bvec PAM_c::demodulate_bits(const cvec &signal) const
00424   {
00425     bvec temp(signal.size());
00426     demodulate_bits(signal, temp);
00427     return temp;
00428   }
00429 
00430 
00431   void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00432                                    vec &soft_bits, Soft_Method method) const
00433   {
00434     it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
00435     double P0, P1, d0min, d1min, temp;
00436     vec metric(M);
00437 
00438     soft_bits.set_size(k * rx_symbols.size());
00439 
00440     if (method == LOGMAP) {
00441       for (int l = 0; l < rx_symbols.size(); l++) {
00442         for (int j = 0; j < M; j++) {
00443           metric(j) = std::exp(-sqr(std::real(rx_symbols(l) - symbols(j)))
00444                                / N0);
00445         }
00446         for (int i = 0; i < k; i++) {
00447           P0 = P1 = 0;
00448           for (int j = 0; j < (M >> 1); j++) {
00449             P0 += metric(S0(i, j));
00450             P1 += metric(S1(i, j));
00451           }
00452           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00453         }
00454       }
00455     }
00456     else { // method == APPROX
00457       for (int l = 0; l < rx_symbols.size(); l++) {
00458         for (int j = 0; j < M; j++) {
00459           metric(j) = sqr(std::real(rx_symbols(l) - symbols(j)));
00460         }
00461         for (int i = 0; i < k; i++) {
00462           d0min = d1min = std::numeric_limits<double>::max();
00463           for (int j = 0; j < (M >> 1); j++) {
00464             temp = metric(S0(i, j));
00465             if (temp < d0min) { d0min = temp; }
00466             temp = metric(S1(i, j));
00467             if (temp < d1min) { d1min = temp; }
00468           }
00469           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00470         }
00471       }
00472     }
00473   }
00474 
00475   vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
00476                                   Soft_Method method) const
00477   {
00478     vec out;
00479     demodulate_soft_bits(rx_symbols, N0, out, method);
00480     return out;
00481   }
00482 
00483 
00484   void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00485                                    double N0, vec &soft_bits,
00486                                    Soft_Method method) const
00487   {
00488     it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
00489     double P0, P1, d0min, d1min, temp;
00490     vec metric(M);
00491 
00492     soft_bits.set_size(k * rx_symbols.size());
00493 
00494     if (method == LOGMAP) {
00495       for (int l = 0; l < rx_symbols.size(); l++) {
00496         for (int j = 0; j < M; j++) {
00497           metric(j) = std::exp(-sqr(std::real(rx_symbols(l)
00498                                               - channel(l) * symbols(j))) / N0);
00499         }
00500         for (int i = 0; i < k; i++) {
00501           P0 = P1 = 0;
00502           for (int j = 0; j < (M >> 1); j++) {
00503             P0 += metric(S0(i, j));
00504             P1 += metric(S1(i, j));
00505           }
00506           soft_bits(l*k+i) = trunc_log(P0) - trunc_log(P1);
00507         }
00508       }
00509     }
00510     else { // method == APPROX
00511       for (int l = 0; l < rx_symbols.size(); l++) {
00512         for (int j = 0; j < M; j++) {
00513           metric(j) = sqr(std::real(rx_symbols(l) - channel(l) * symbols(j)));
00514         }
00515         for (int i = 0; i < k; i++) {
00516           d0min = d1min = std::numeric_limits<double>::max();
00517           for (int j = 0; j < (M >> 1); j++) {
00518             temp = metric(S0(i, j));
00519             if (temp < d0min) { d0min = temp; }
00520             temp = metric(S1(i, j));
00521             if (temp < d1min) { d1min = temp; }
00522           }
00523           soft_bits(l*k+i) = (-d0min + d1min) / N0;
00524         }
00525       }
00526     }
00527   }
00528 
00529   vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
00530                                   double N0, Soft_Method method) const
00531   {
00532     vec out;
00533     demodulate_soft_bits(rx_symbols, channel, N0, out, method);
00534     return out;
00535   }
00536 
00537 
00538   // ----------------------------------------------------------------------
00539   // PAM
00540   // ----------------------------------------------------------------------
00541 
00542   void PAM::set_M(int Mary)
00543   {
00544     M = Mary;
00545     k = levels2bits(M);
00546     it_assert(pow2i(k) == M, "PAM::set_M(): M is not a power of 2");
00547 
00548     symbols.set_size(M, false);
00549     bits2symbols.set_size(M, false);
00550     bitmap = graycode(k);
00551     double average_energy = (sqr(M) - 1) / 3.0;
00552     scaling_factor = std::sqrt(average_energy);
00553 
00554     for (int i = 0; i < M; i++) {
00555       symbols(i) = ((M-1) - i*2) / scaling_factor;
00556       bits2symbols(bin2dec(bitmap.get_row(i))) = i;
00557     }
00558 
00559     calculate_softbit_matrices(bits2symbols);
00560 
00561     setup_done = true;
00562   }
00563 
00564 
00565   void PAM::demodulate_bits(const vec &signal, bvec &out) const
00566   {
00567     it_assert_debug(setup_done, "PAM::demodulate_bits(): Modulator not ready.");
00568     int est_symbol;
00569     out.set_size(k*signal.size(), false);
00570 
00571     for (int i = 0; i < signal.size(); i++) {
00572       est_symbol = round_i((M-1) - (signal(i) * scaling_factor + (M-1)) / 2);
00573       if (est_symbol < 0)
00574         est_symbol = 0;
00575       else if (est_symbol > (M-1))
00576         est_symbol = M-1;
00577       out.replace_mid(i*k, bitmap.get_row(est_symbol));
00578     }
00579   }
00580 
00581   bvec PAM::demodulate_bits(const vec &signal) const
00582   {
00583     bvec temp(signal.size());
00584     demodulate_bits(signal, temp);
00585     return temp;
00586   }
00587 
00588 } // namespace itpp
SourceForge Logo

Generated on Sat Apr 19 10:43:54 2008 for IT++ by Doxygen 1.5.5