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

Generated on Sat Jul 6 2013 10:54:22 for IT++ by Doxygen 1.8.2