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
35namespace itpp
36{
37
39//MSVC explicitely instantiate required template while building the shared library
40template class ITPP_EXPORT Modulator<double>;
41template class ITPP_EXPORT Modulator<std::complex<double> >;
43
44// ----------------------------------------------------------------------
45// QAM
46// ----------------------------------------------------------------------
47
48void 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
81void 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
105bvec 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
117void 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
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
151void 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
167bvec 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
179void 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
194vec 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
203void 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
219vec 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
232void 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
240cvec 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
248void 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
256bvec 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
264void 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
275vec 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
284void 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
297vec 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
310void 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
318vec BPSK::modulate_bits(const bvec &bits) const
319{
320 vec out(bits.size());
321 modulate_bits(bits, out);
322 return out;
323}
324
325
326void 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
334bvec BPSK::demodulate_bits(const vec &signal) const
335{
336 bvec out(signal.size());
337 demodulate_bits(signal, out);
338 return out;
339}
340
341
342void 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
353vec 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
362void 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
374vec 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
387void 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
410void 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
427bvec 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
435void 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
479vec 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
488void 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
533vec 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
546void 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
569void 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
585bvec 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
virtual void demodulate_soft_bits(const cvec &rx_symbols, double N0, vec &soft_bits, Soft_Method method=LOGMAP) const
Soft demodulator for AWGN channel.
Definition: modulator.cpp:264
void modulate_bits(const bvec &bits, cvec &output) const
Modulate bits into BPSK symbols in complex domain.
Definition: modulator.cpp:232
void demodulate_bits(const cvec &signal, bvec &output) const
Demodulate noisy BPSK symbols in complex domain into bits.
Definition: modulator.cpp:248
void modulate_bits(const bvec &bits, vec &output) const
Modulate bits into BPSK symbols in complex domain.
Definition: modulator.cpp:310
virtual void demodulate_soft_bits(const vec &rx_symbols, double N0, vec &soft_bits, Soft_Method method=LOGMAP) const
Soft demodulator for AWGN channel.
Definition: modulator.cpp:342
void demodulate_bits(const vec &signal, bvec &output) const
Demodulate noisy BPSK symbols in complex domain into bits.
Definition: modulator.cpp:326
bmat bitmap
Bit to symbol mapping table (size: M x k)
Definition: modulator.h:241
Vec< std::complex< double > > symbols
Corresponding modulation symbols (size: M)
Definition: modulator.h:245
int k
Number of bits per modulation symbol.
Definition: modulator.h:237
ivec bits2symbols
Bit to symbol mapping in decimal form (size: M)
Definition: modulator.h:243
imat S1
Matrix where row k contains the constellation points with '1' in bit position k.
Definition: modulator.h:251
int M
Number of modulation symbols.
Definition: modulator.h:239
void calculate_softbit_matrices()
This function calculates the soft bit mapping matrices S0 and S1.
Definition: modulator.h:530
imat S0
Matrix where row k contains the constellation points with '0' in bit position k.
Definition: modulator.h:248
virtual void demodulate_soft_bits(const cvec &rx_symbols, double N0, vec &soft_bits, Soft_Method method=LOGMAP) const
Soft demodulator for AWGN channels.
Definition: modulator.cpp:435
void set_M(int M)
Set the size of the signal constellation.
Definition: modulator.cpp:387
void demodulate_bits(const cvec &signal, bvec &output) const
Hard demodulation of PAM symbols in complex domain to bits.
Definition: modulator.cpp:410
double scaling_factor
Scaling factor used to normalize the average energy to 1.
Definition: modulator.h:1080
void set_M(int M)
Set the size of the signal constellation.
Definition: modulator.cpp:546
double scaling_factor
Scaling factor used to normalize the average energy to 1.
Definition: modulator.h:1123
void demodulate_bits(const vec &signal, bvec &output) const
Hard demodulation of PAM symbols in complex domain to bits.
Definition: modulator.cpp:569
void set_M(int M)
Change the size of the signal constellation.
Definition: modulator.cpp:117
void demodulate_bits(const cvec &signal, bvec &bits) const
Hard demodulation of bits.
Definition: modulator.cpp:151
double scaling_factor
Scaling factor of square QAM constellation (sqrt((M-1)*2/3))
Definition: modulator.h:607
void demodulate_bits(const cvec &signal, bvec &bits) const
Hard demodulation of bits.
Definition: modulator.cpp:81
int L
The square-root of M.
Definition: modulator.h:605
void set_M(int M)
Change the size of the signal constellation.
Definition: modulator.cpp:48
virtual void demodulate_soft_bits(const cvec &rx_symbols, double N0, vec &soft_bits, Soft_Method method=LOGMAP) const
Soft demodulator for AWGN channel.
Definition: modulator.cpp:179
void set_size(int size, bool copy=false)
Set length of vector. if copy = true then keeping the old values.
Definition: vec.h:663
Binary arithmetic (boolean) class.
Definition: binary.h:57
Definitions of some specific functions useful in communications.
Elementary mathematical functions - header file.
#define it_assert_debug(t, s)
Abort if t is not true and NDEBUG is not defined.
Definition: itassert.h:107
#define it_assert(t, s)
Abort if t is not true.
Definition: itassert.h:94
double trunc_log(double x)
Truncated natural logarithm function.
Definition: log_exp.h:115
int pow2i(int x)
Calculate two to the power of x (2^x); x is integer.
Definition: log_exp.h:53
int levels2bits(int n)
Calculate the number of bits needed to represent n different values (levels).
Definition: log_exp.h:92
bmat graycode(int m)
Generate Gray code of blocklength m.
Definition: commfunc.cpp:39
bool is_even(int x)
Return true if x is an even integer.
Definition: misc.h:122
vec sqr(const cvec &data)
Absolute square of elements.
Definition: elem_math.cpp:36
Soft_Method
Soft demodulation methods.
Definition: modulator.h:47
@ LOGMAP
Log-MAP full calculation.
Definition: modulator.h:48
Mat< bin > bmat
bin matrix
Definition: mat.h:508
One- and two-dimensional modulators - header file.
itpp namespace
Definition: itmex.h:37
ITPP_EXPORT int round_i(double x)
Round to nearest integer.
const double m_2pi
Constant 2*Pi.
Definition: misc.h:106
ITPP_EXPORT int bin2dec(const bvec &inbvec, bool msb_first=true)
Convert a bvec to decimal int with the first bit as MSB if msb_first == true.
const Array< T > concat(const Array< T > &a, const T &e)
Append element e to the end of the Array a.
Definition: array.h:486
int gray_code(int x)
Convert to Gray Code.
Definition: converters.h:421
const double pi
Constant Pi.
Definition: misc.h:103
Definitions of special vectors and matrices.
SourceForge Logo

Generated on Tue Jan 24 2023 00:00:00 for IT++ by Doxygen 1.9.6