IT++ Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
modulator.cpp
Go to the documentation of this file.
1 
29 #include <itpp/comm/modulator.h>
30 #include <itpp/comm/commfunc.h>
32 #include <itpp/base/specmat.h>
33 
34 
35 namespace itpp
36 {
37 
38 
39 // ----------------------------------------------------------------------
40 // QAM
41 // ----------------------------------------------------------------------
42 
43 void QAM::set_M(int Mary)
44 {
45  k = levels2bits(Mary);
46  M = Mary;
47  it_assert((pow2i(k) == M) && (is_even(k)),
48  "QAM::set_M(): M = " << M << " is not an even power of 2");
49  L = round_i(std::sqrt(static_cast<double>(M)));
50 
51  double average_energy = (M - 1) * 2.0 / 3.0;
52  scaling_factor = std::sqrt(average_energy);
53 
55  bitmap.set_size(M, k);
56  bits2symbols.set_size(M);
57 
59 
60  for (int i = 0; i < L; i++) {
61  for (int j = 0; j < L; j++) {
62  symbols(i*L + j) = std::complex<double>(((L - 1) - j * 2) / scaling_factor,
63  ((L - 1) - i * 2) / scaling_factor);
64  bitmap.set_row(i*L + j, concat(gray_code.get_row(i),
65  gray_code.get_row(j)));
66  bits2symbols(bin2dec(bitmap.get_row(i*L + j))) = i * L + j;
67  }
68  }
69 
71 
72  setup_done = true;
73 }
74 
75 
76 void QAM::demodulate_bits(const cvec &signal, bvec &out) const
77 {
78  it_assert_debug(setup_done, "QAM::demodulate_bits(): Modulator not ready.");
79  out.set_size(k*signal.size(), false);
80 
81  int temp_real, temp_imag;
82 
83  for (int i = 0; i < signal.size(); i++) {
84  temp_real = round_i((L - 1) - (std::real(signal(i) * scaling_factor)
85  + (L - 1)) / 2.0);
86  temp_imag = round_i((L - 1) - (std::imag(signal(i) * scaling_factor)
87  + (L - 1)) / 2.0);
88  if (temp_real < 0)
89  temp_real = 0;
90  else if (temp_real > (L - 1))
91  temp_real = (L - 1);
92  if (temp_imag < 0)
93  temp_imag = 0;
94  else if (temp_imag > (L - 1))
95  temp_imag = (L - 1);
96  out.replace_mid(k*i, bitmap.get_row(temp_imag * L + temp_real));
97  }
98 }
99 
100 bvec QAM::demodulate_bits(const cvec &signal) const
101 {
102  bvec out;
103  demodulate_bits(signal, out);
104  return out;
105 }
106 
107 
108 // ----------------------------------------------------------------------
109 // PSK
110 // ----------------------------------------------------------------------
111 
112 void PSK::set_M(int Mary)
113 {
114  k = levels2bits(Mary);
115  M = Mary;
116  it_assert(pow2i(k) == M, "PSK::set_M(): M is not a power of 2");
117 
118  symbols.set_size(M);
119  bitmap = graycode(k);
120  bits2symbols.set_size(M);
121 
122  double delta = m_2pi / M;
123  double epsilon = delta / 10000.0;
124  std::complex<double> symb;
125  for (int i = 0; i < M; i++) {
126  symb = std::complex<double>(std::polar(1.0, delta * i));
127  if (std::fabs(std::real(symb)) < epsilon) {
128  symbols(i) = std::complex<double>(0.0, std::imag(symb));
129  }
130  else if (std::fabs(std::imag(symb)) < epsilon) {
131  symbols(i) = std::complex<double>(std::real(symb), 0.0);
132  }
133  else {
134  symbols(i) = symb;
135  }
136 
137  bits2symbols(bin2dec(bitmap.get_row(i))) = i;
138  }
139 
141 
142  setup_done = true;
143 }
144 
145 
146 void PSK::demodulate_bits(const cvec &signal, bvec &out) const
147 {
148  it_assert_debug(setup_done, "PSK::demodulate_bits(): Modulator not ready.");
149  int est_symbol;
150  double ang, temp;
151 
152  out.set_size(k*signal.size(), false);
153 
154  for (int i = 0; i < signal.size(); i++) {
155  ang = std::arg(signal(i));
156  temp = (ang < 0) ? (m_2pi + ang) : ang;
157  est_symbol = round_i(temp * (M >> 1) / pi) % M;
158  out.replace_mid(i*k, bitmap.get_row(est_symbol));
159  }
160 }
161 
162 bvec PSK::demodulate_bits(const cvec &signal) const
163 {
164  bvec out;
165  demodulate_bits(signal, out);
166  return out;
167 }
168 
169 
170 // ----------------------------------------------------------------------
171 // QPSK
172 // ----------------------------------------------------------------------
173 
174 void QPSK::demodulate_soft_bits(const cvec &rx_symbols, double N0,
175  vec &soft_bits, Soft_Method) const
176 {
177  soft_bits.set_size(k * rx_symbols.size());
178  std::complex<double> temp;
179  double factor = 2 * std::sqrt(2.0) / N0;
180  std::complex<double> exp_pi4 = std::complex<double>(std::cos(pi / 4),
181  std::sin(pi / 4));
182  for (int i = 0; i < rx_symbols.size(); i++) {
183  temp = rx_symbols(i) * exp_pi4;
184  soft_bits((i << 1) + 1) = std::real(temp) * factor;
185  soft_bits(i << 1) = std::imag(temp) * factor;
186  }
187 }
188 
189 vec QPSK::demodulate_soft_bits(const cvec &rx_symbols, double N0,
190  Soft_Method method) const
191 {
192  vec out;
193  demodulate_soft_bits(rx_symbols, N0, out, method);
194  return out;
195 }
196 
197 
198 void QPSK::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
199  double N0, vec &soft_bits,
200  Soft_Method) const
201 {
202  soft_bits.set_size(2*rx_symbols.size(), false);
203  std::complex<double> temp;
204  double factor = 2 * std::sqrt(2.0) / N0;
205  std::complex<double> exp_pi4 = std::complex<double>(std::cos(pi / 4),
206  std::sin(pi / 4));
207  for (int i = 0; i < rx_symbols.size(); i++) {
208  temp = rx_symbols(i) * std::conj(channel(i)) * exp_pi4;
209  soft_bits((i << 1) + 1) = std::real(temp) * factor;
210  soft_bits(i << 1) = std::imag(temp) * factor;
211  }
212 }
213 
214 vec QPSK::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
215  double N0, Soft_Method method) const
216 {
217  vec out;
218  demodulate_soft_bits(rx_symbols, channel, N0, out, method);
219  return out;
220 }
221 
222 
223 // ----------------------------------------------------------------------
224 // BPSK_c
225 // ----------------------------------------------------------------------
226 
227 void BPSK_c::modulate_bits(const bvec &bits, cvec &out) const
228 {
229  out.set_size(bits.size(), false);
230  for (int i = 0; i < bits.size(); i++) {
231  out(i) = (bits(i) == 0 ? 1.0 : -1.0);
232  }
233 }
234 
235 cvec BPSK_c::modulate_bits(const bvec &bits) const
236 {
237  cvec out(bits.size());
238  modulate_bits(bits, out);
239  return out;
240 }
241 
242 
243 void BPSK_c::demodulate_bits(const cvec &signal, bvec &out) const
244 {
245  out.set_size(signal.size(), false);
246  for (int i = 0; i < signal.length(); i++) {
247  out(i) = (std::real(signal(i)) > 0) ? bin(0) : bin(1);
248  }
249 }
250 
251 bvec BPSK_c::demodulate_bits(const cvec &signal) const
252 {
253  bvec out(signal.size());
254  demodulate_bits(signal, out);
255  return out;
256 }
257 
258 
259 void BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
260  vec &soft_bits, Soft_Method) const
261 {
262  double factor = 4 / N0;
263  soft_bits.set_size(rx_symbols.size(), false);
264 
265  for (int i = 0; i < rx_symbols.size(); i++) {
266  soft_bits(i) = factor * std::real(rx_symbols(i));
267  }
268 }
269 
270 vec BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
271  Soft_Method method) const
272 {
273  vec out;
274  demodulate_soft_bits(rx_symbols, N0, out, method);
275  return out;
276 }
277 
278 
279 void BPSK_c::demodulate_soft_bits(const cvec &rx_symbols,
280  const cvec &channel,
281  double N0, vec &soft_bits,
282  Soft_Method) const
283 {
284  double factor = 4 / N0;
285  soft_bits.set_size(rx_symbols.size(), false);
286 
287  for (int i = 0; i < rx_symbols.size(); i++) {
288  soft_bits(i) = factor * std::real(rx_symbols(i) * std::conj(channel(i)));
289  }
290 }
291 
292 vec BPSK_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
293  double N0, Soft_Method method) const
294 {
295  vec out;
296  demodulate_soft_bits(rx_symbols, channel, N0, out, method);
297  return out;
298 }
299 
300 
301 // ----------------------------------------------------------------------
302 // BPSK
303 // ----------------------------------------------------------------------
304 
305 void BPSK::modulate_bits(const bvec &bits, vec &out) const
306 {
307  out.set_size(bits.size(), false);
308  for (int i = 0; i < bits.size(); i++) {
309  out(i) = (bits(i) == 0 ? 1.0 : -1.0);
310  }
311 }
312 
313 vec BPSK::modulate_bits(const bvec &bits) const
314 {
315  vec out(bits.size());
316  modulate_bits(bits, out);
317  return out;
318 }
319 
320 
321 void BPSK::demodulate_bits(const vec &signal, bvec &out) const
322 {
323  out.set_size(signal.size(), false);
324  for (int i = 0; i < signal.length(); i++) {
325  out(i) = (signal(i) > 0) ? bin(0) : bin(1);
326  }
327 }
328 
329 bvec BPSK::demodulate_bits(const vec &signal) const
330 {
331  bvec out(signal.size());
332  demodulate_bits(signal, out);
333  return out;
334 }
335 
336 
337 void BPSK::demodulate_soft_bits(const vec &rx_symbols, double N0,
338  vec &soft_bits, Soft_Method) const
339 {
340  double factor = 4 / N0;
341  soft_bits.set_size(rx_symbols.size(), false);
342 
343  for (int i = 0; i < rx_symbols.size(); i++) {
344  soft_bits(i) = factor * rx_symbols(i);
345  }
346 }
347 
348 vec BPSK::demodulate_soft_bits(const vec &rx_symbols, double N0,
349  Soft_Method method) const
350 {
351  vec out;
352  demodulate_soft_bits(rx_symbols, N0, out, method);
353  return out;
354 }
355 
356 
357 void BPSK::demodulate_soft_bits(const vec &rx_symbols, const vec &channel,
358  double N0, vec &soft_bits,
359  Soft_Method) const
360 {
361  double factor = 4 / N0;
362  soft_bits.set_size(rx_symbols.size(), false);
363 
364  for (int i = 0; i < rx_symbols.size(); i++) {
365  soft_bits(i) = factor * (rx_symbols(i) * channel(i));
366  }
367 }
368 
369 vec BPSK::demodulate_soft_bits(const vec &rx_symbols, const vec &channel,
370  double N0, Soft_Method method) const
371 {
372  vec out;
373  demodulate_soft_bits(rx_symbols, channel, N0, out, method);
374  return out;
375 }
376 
377 
378 // ----------------------------------------------------------------------
379 // PAM_c
380 // ----------------------------------------------------------------------
381 
382 void PAM_c::set_M(int Mary)
383 {
384  M = Mary;
385  k = levels2bits(M);
386  it_assert(pow2i(k) == M, "PAM_c::set_M(): M is not a power of 2");
387 
388  symbols.set_size(M, false);
389  bits2symbols.set_size(M, false);
390  bitmap = graycode(k);
391  double average_energy = (sqr(M) - 1) / 3.0;
392  scaling_factor = std::sqrt(average_energy);
393 
394  for (int i = 0; i < M; i++) {
395  symbols(i) = ((M - 1) - i * 2) / scaling_factor;
396  bits2symbols(bin2dec(bitmap.get_row(i))) = i;
397  }
398 
400 
401  setup_done = true;
402 }
403 
404 
405 void PAM_c::demodulate_bits(const cvec &signal, bvec &out) const
406 {
407  it_assert_debug(setup_done, "PAM_c::demodulate_bits(): Modulator not ready.");
408  int est_symbol;
409  out.set_size(k*signal.size(), false);
410 
411  for (int i = 0; i < signal.size(); i++) {
412  est_symbol = round_i((M - 1) - (std::real(signal(i)) * scaling_factor
413  + (M - 1)) / 2);
414  if (est_symbol < 0)
415  est_symbol = 0;
416  else if (est_symbol > (M - 1))
417  est_symbol = M - 1;
418  out.replace_mid(i*k, bitmap.get_row(est_symbol));
419  }
420 }
421 
422 bvec PAM_c::demodulate_bits(const cvec &signal) const
423 {
424  bvec temp(signal.size());
425  demodulate_bits(signal, temp);
426  return temp;
427 }
428 
429 
430 void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
431  vec &soft_bits, Soft_Method method) const
432 {
433  it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
434  double P0, P1, d0min, d1min, temp;
435  vec metric(M);
436 
437  soft_bits.set_size(k * rx_symbols.size());
438 
439  if (method == LOGMAP) {
440  for (int l = 0; l < rx_symbols.size(); l++) {
441  for (int j = 0; j < M; j++) {
442  metric(j) = std::exp(-sqr(std::real(rx_symbols(l) - symbols(j)))
443  / N0);
444  }
445  for (int i = 0; i < k; i++) {
446  P0 = P1 = 0;
447  for (int j = 0; j < (M >> 1); j++) {
448  P0 += metric(S0(i, j));
449  P1 += metric(S1(i, j));
450  }
451  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
452  }
453  }
454  }
455  else { // method == APPROX
456  for (int l = 0; l < rx_symbols.size(); l++) {
457  for (int j = 0; j < M; j++) {
458  metric(j) = sqr(std::real(rx_symbols(l) - symbols(j)));
459  }
460  for (int i = 0; i < k; i++) {
461  d0min = d1min = std::numeric_limits<double>::max();
462  for (int j = 0; j < (M >> 1); j++) {
463  temp = metric(S0(i, j));
464  if (temp < d0min) { d0min = temp; }
465  temp = metric(S1(i, j));
466  if (temp < d1min) { d1min = temp; }
467  }
468  soft_bits(l*k + i) = (-d0min + d1min) / N0;
469  }
470  }
471  }
472 }
473 
474 vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, double N0,
475  Soft_Method method) const
476 {
477  vec out;
478  demodulate_soft_bits(rx_symbols, N0, out, method);
479  return out;
480 }
481 
482 
483 void PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
484  double N0, vec &soft_bits,
485  Soft_Method method) const
486 {
487  it_assert_debug(setup_done, "PAM_c::demodulate_soft_bits(): Modulator not ready.");
488  double P0, P1, d0min, d1min, temp;
489  vec metric(M);
490 
491  soft_bits.set_size(k * rx_symbols.size());
492 
493  if (method == LOGMAP) {
494  for (int l = 0; l < rx_symbols.size(); l++) {
495  for (int j = 0; j < M; j++) {
496  metric(j) = std::exp(-sqr(std::real(rx_symbols(l)
497  - channel(l) * symbols(j))) / N0);
498  }
499  for (int i = 0; i < k; i++) {
500  P0 = P1 = 0;
501  for (int j = 0; j < (M >> 1); j++) {
502  P0 += metric(S0(i, j));
503  P1 += metric(S1(i, j));
504  }
505  soft_bits(l*k + i) = trunc_log(P0) - trunc_log(P1);
506  }
507  }
508  }
509  else { // method == APPROX
510  for (int l = 0; l < rx_symbols.size(); l++) {
511  for (int j = 0; j < M; j++) {
512  metric(j) = sqr(std::real(rx_symbols(l) - channel(l) * symbols(j)));
513  }
514  for (int i = 0; i < k; i++) {
515  d0min = d1min = std::numeric_limits<double>::max();
516  for (int j = 0; j < (M >> 1); j++) {
517  temp = metric(S0(i, j));
518  if (temp < d0min) { d0min = temp; }
519  temp = metric(S1(i, j));
520  if (temp < d1min) { d1min = temp; }
521  }
522  soft_bits(l*k + i) = (-d0min + d1min) / N0;
523  }
524  }
525  }
526 }
527 
528 vec PAM_c::demodulate_soft_bits(const cvec &rx_symbols, const cvec &channel,
529  double N0, Soft_Method method) const
530 {
531  vec out;
532  demodulate_soft_bits(rx_symbols, channel, N0, out, method);
533  return out;
534 }
535 
536 
537 // ----------------------------------------------------------------------
538 // PAM
539 // ----------------------------------------------------------------------
540 
541 void PAM::set_M(int Mary)
542 {
543  M = Mary;
544  k = levels2bits(M);
545  it_assert(pow2i(k) == M, "PAM::set_M(): M is not a power of 2");
546 
547  symbols.set_size(M, false);
548  bits2symbols.set_size(M, false);
549  bitmap = graycode(k);
550  double average_energy = (sqr(M) - 1) / 3.0;
551  scaling_factor = std::sqrt(average_energy);
552 
553  for (int i = 0; i < M; i++) {
554  symbols(i) = ((M - 1) - i * 2) / scaling_factor;
555  bits2symbols(bin2dec(bitmap.get_row(i))) = i;
556  }
557 
559 
560  setup_done = true;
561 }
562 
563 
564 void PAM::demodulate_bits(const vec &signal, bvec &out) const
565 {
566  it_assert_debug(setup_done, "PAM::demodulate_bits(): Modulator not ready.");
567  int est_symbol;
568  out.set_size(k*signal.size(), false);
569 
570  for (int i = 0; i < signal.size(); i++) {
571  est_symbol = round_i((M - 1) - (signal(i) * scaling_factor + (M - 1)) / 2);
572  if (est_symbol < 0)
573  est_symbol = 0;
574  else if (est_symbol > (M - 1))
575  est_symbol = M - 1;
576  out.replace_mid(i*k, bitmap.get_row(est_symbol));
577  }
578 }
579 
580 bvec PAM::demodulate_bits(const vec &signal) const
581 {
582  bvec temp(signal.size());
583  demodulate_bits(signal, temp);
584  return temp;
585 }
586 
587 } // namespace itpp
SourceForge Logo

Generated on Fri Mar 21 2014 17:14:13 for IT++ by Doxygen 1.8.1.2