|
3 | 3 |
|
4 | 4 | from itertools import product
|
5 | 5 |
|
6 |
| -from numpy import zeros, identity, arange, concatenate, log2, array, inf |
| 6 | +from numpy import zeros, identity, arange, concatenate, log2, log10, array, inf, sqrt, sin, pi |
7 | 7 | from numpy.random import seed
|
8 | 8 | from numpy.testing import run_module_suite, assert_allclose, dec, assert_raises, assert_array_equal
|
| 9 | +from scipy.special import erf |
9 | 10 |
|
10 |
| -from commpy.channels import MIMOFlatChannel |
| 11 | +from commpy.channels import MIMOFlatChannel, SISOFlatChannel |
11 | 12 | from commpy.links import *
|
12 | 13 | from commpy.modulation import QAMModem, mimo_ml, bit_lvl_repr, max_log_approx, PSKModem, Modem
|
13 | 14 | from commpy.utilities import signal_power
|
14 | 15 |
|
15 | 16 |
|
| 17 | +def Qfunc(x): |
| 18 | + return 0.5 - 0.5 * erf(x / sqrt(2)) |
| 19 | + |
| 20 | + |
16 | 21 | @dec.slow
|
17 | 22 | def test_bit_lvl_repr():
|
18 | 23 | # Set seed
|
@@ -124,8 +129,33 @@ def do_custom(self, modem):
|
124 | 129 | pass
|
125 | 130 |
|
126 | 131 |
|
| 132 | +@dec.slow |
127 | 133 | class TestModulateHardDemodulate(ModemTestcase):
|
128 | 134 |
|
| 135 | + @staticmethod |
| 136 | + def check_BER(modem, EbN0dB, BERs_expected): |
| 137 | + seed(8071996) |
| 138 | + model = LinkModel(modem.modulate, |
| 139 | + SISOFlatChannel(fading_param=(1 + 0j, 0)), |
| 140 | + lambda y, _, __, ___: modem.demodulate(y, 'hard'), |
| 141 | + modem.num_bits_symbol, modem.constellation, modem.Es) |
| 142 | + BERs = model.link_performance(EbN0dB + 10 * log10(log2(modem.m)), 5e5, 400, 720) |
| 143 | + assert_allclose(BERs, BERs_expected, atol=1e-4, rtol=.1, |
| 144 | + err_msg='Wrong BER for {}-PSK modulation'.format(modem.m)) |
| 145 | + |
| 146 | + def do_qam(self, modem): |
| 147 | + EbN0dB = arange(8, 25, 4) |
| 148 | + nb_pam = sqrt(modem.m) |
| 149 | + BERs_expected = 2 * (1 - 1 / nb_pam) / log2(nb_pam) * \ |
| 150 | + Qfunc(sqrt(3 * log2(nb_pam) / (nb_pam ** 2 - 1) * (2 * 10 ** (EbN0dB / 10)))) |
| 151 | + self.check_BER(modem, EbN0dB, BERs_expected) |
| 152 | + |
| 153 | + def do_psk(self, modem): |
| 154 | + EbN0dB = arange(15, 25, 4) |
| 155 | + SERs_expected = 2 * Qfunc(sqrt(2 * modem.num_bits_symbol * 10 ** (EbN0dB / 10)) * sin(pi / modem.m)) |
| 156 | + BERs_expected = SERs_expected / modem.num_bits_symbol |
| 157 | + self.check_BER(modem, EbN0dB, BERs_expected) |
| 158 | + |
129 | 159 | def do(self, modem):
|
130 | 160 | for bits in product(*((0, 1),) * modem.num_bits_symbol):
|
131 | 161 | assert_array_equal(bits, modem.demodulate(modem.modulate(bits), 'hard'),
|
|
0 commit comments