{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "\\tableofcontents\n", "% These TeX commands run at the start to remove section numbering\n", "\\renewcommand{\\thesection}{\\hspace*{-1.0em}}\n", "\\renewcommand{\\thesubsection}{\\hspace*{-1.0em}}\n", "\\renewcommand{\\thesubsubsection}{\\hspace*{-1.0em}}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pylab inline\n", "#%matplotlib qt\n", "import sk_dsp_comm.sigsys as ss\n", "import scipy.signal as signal\n", "from IPython.display import Audio, display\n", "from IPython.display import Image, SVG" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pylab.rcParams['savefig.dpi'] = 100 # default 72\n", "#pylab.rcParams['figure.figsize'] = (6.0, 4.0) # default (6,4)\n", "#%config InlineBackend.figure_formats=['png'] # default for inline viewing\n", "%config InlineBackend.figure_formats=['svg'] # SVG inline viewing\n", "#%config InlineBackend.figure_formats=['pdf'] # render pdf figs for LaTeX" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import scipy.special as special\n", "import sk_dsp_comm.digitalcom as dc\n", "import sk_dsp_comm.fec_conv as fec" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Convolutional Coding" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rate 1/2 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A convolutional encoder object can be created with the `fec.FECConv` method. The rate of the object will be determined by the number of generator polynomials used. Right now, only rate 1/2 and rate 1/3 are supported, so 2 or three generator polynomials can be used. The following table shows ideal rate 1/2 generator polynomials. These are also included in the docstring. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Table 1: Weight spectra $c_k$ for bounding the codedrate 1/2 BEP**.\n", "\n", "| CL |Polynomials |$D_{free}$|$d_f$|$d_f+1$|$d_f+2$|$d_f+3$|$d_f+4$|$d_f+5$|$d_f+6$|$d_f+7$|\n", "|:----:|:--------------------------------:|:-------:|:---:|:-----:|:-----:|:-----:|-------|-------|-------|-------|\n", "|3 |(5,7) = ('101','111') |5 |1 |4 |12 |32 |80 |192 |488 |1024 |\n", "|4 |(15,17) = ('1101','1111') |6 |2 |7 |18 |49 |130 |333 |836 |2069 |\n", "|5 |(23,35) = ('10011','11101') |7 |4 |12 |20 |72 |225 |500 |1324 |3680 |\n", "|6 |(53,75) = ('101011','111101') |8 |2 |36 |32 |62 |332 |701 |2342 |5503 |\n", "|7 |(133,171) = ('1011011','1111001') |10 |36 |0 |211 |0 |1404 |0 |11633 |0 |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition to the generator polynomials, you can specify a decision depth for the object. This will determine how many state transitions will be used for the traceback. The following shows how to create a rate 1/2 `fec_conv` object with contraint length 3 and decision depth 10." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cc1 = fec.FECConv(('111','101'),10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `trellis_plot()` method can be used to see the state transitions of the `fec_conv` object." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cc1.trellis_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Rate 1/2 Hard Decision Decoding" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we would like to know the theoretical bit error probability bounds of our convolutional encoding/decoding setup. We can do this using the `fec.conv_Pb_bound` method. The method takes the rate, degrees of freedom, $c_k$ values, SNR, hard or soft decisions, and order M for an MPSK modulation scheme as arguments. It returns the BEP. The following shows theoretical bounds for rate 1/2 encoding/decoding BPSK system. Compare with Ziemer pg 667." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Weight Structure Bounds BEP" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/2,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_half_3_hard = fec.conv_Pb_bound(1/2,5,[1, 4, 12, 32, 80, 192, 448, 1024],SNRdB,0)\n", "Pb_s_half_5_hard = fec.conv_Pb_bound(1/2,7,[4, 12, 20, 72, 225, 500, 1324, 3680],SNRdB,0)\n", "Pb_s_half_7_hard = fec.conv_Pb_bound(1/2,10,[36, 0, 211, 0, 1404, 0, 11633, 0],SNRdB,0)\n", "Pb_s_half_9_hard = fec.conv_Pb_bound(1/2,12,[33, 0, 281, 0, 2179, 0, 15035, 0],SNRdB,0)\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_half_3_hard,'--')\n", "semilogy(SNRdB,Pb_s_half_5_hard,'--')\n", "semilogy(SNRdB,Pb_s_half_7_hard,'--')\n", "semilogy(SNRdB,Pb_s_half_9_hard,'--')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Hard Decision Rate 1/2 Coding Theory Bounds')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/2, K=3, Hard',\\\n", " 'R=1/2, K=5, Hard', 'R=1/2, K=7, Hard',\\\n", " 'R=1/2, K=9, Hard'),loc='upper right')\n", "grid();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### BEP Simulation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we can determine our BEP bounds, we can test the actual encoder/decoder using dummy binary data. The following code creates a rate 1/2 fec_conv object. It then generates dummy binary data and encodes the data using the `conv_encoder` method. This method takes an array of binary values, and an initial state as the input and returns the encoded bits and states. We then adds nois to the encoded data according to the set $E_b/N_0$ to simulate a noisy channel. The data is then decoded using the `viterbi_decoder` method. This method takes the array of noisy data and a decision metric. If the hard decision metric is selected, then we expect binary input values from around 0 to around 1. The method then returns the decoded binary values. Then the bit errors are counted. Once at least 100 bit errors are counted, the bit error probability is calculated. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N_bits_per_frame = 10000\n", "EbN0 = 4\n", "total_bit_errors = 0\n", "total_bit_count = 0\n", "cc1 = fec.FECConv(('11101','10011'),25)\n", "# Encode with shift register starting state of '0000'\n", "state = '0000'\n", "while total_bit_errors < 100:\n", " # Create 100000 random 0/1 bits\n", " x = randint(0,2,N_bits_per_frame)\n", " y,state = cc1.conv_encoder(x,state)\n", " # Add channel noise to bits, include antipodal level shift to [-1,1]\n", " yn_soft = dc.cpx_awgn(2*y-1,EbN0-3,1) # Channel SNR is 3 dB less for rate 1/2\n", " yn_hard = ((sign(yn_soft.real)+1)/2).astype(int)\n", " z = cc1.viterbi_decoder(yn_hard,'hard')\n", " # Count bit errors\n", " bit_count, bit_errors = dc.bit_errors(x,z)\n", " total_bit_errors += bit_errors\n", " total_bit_count += bit_count\n", " print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))\n", "print('*****************************************************')\n", "print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "y[:100].astype(int)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The simulated BEP can then be compared to the theoretical bounds that were shown earlier. Some values were simulated for the constraint length 3 and constraint length 5 cases." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/2,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_half_3_hard = fec.conv_Pb_bound(1/2,5,[1, 4, 12, 32, 80, 192, 448, 1024],SNRdB,0)\n", "Pb_s_half_5_hard = fec.conv_Pb_bound(1/2,7,[4, 12, 20, 72, 225, 500, 1324, 3680],SNRdB,0)\n", "Pb_s_half_7_hard = fec.conv_Pb_bound(1/2,10,[36, 0, 211, 0, 1404, 0, 11633, 0],SNRdB,0)\n", "Pb_s_half_9_hard = fec.conv_Pb_bound(1/2,12,[33, 0, 281, 0, 2179, 0, 15035, 0],SNRdB,0)\n", "Pb_s_half_5_hard_sim = array([3.36e-2,1.04e-2,1.39e-3,1.56e-04,1.24e-05])\n", "Pb_s_half_3_hard_sim = array([2.59e-02,1.35e-02,2.71e-03,6.39e-04,9.73e-05,7.71e-06])\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_half_3_hard,'y--')\n", "semilogy(SNRdB,Pb_s_half_5_hard,'g--')\n", "semilogy(SNRdB,Pb_s_half_7_hard,'--')\n", "semilogy(SNRdB,Pb_s_half_9_hard,'--')\n", "semilogy([3,4,5,6,7,8],Pb_s_half_3_hard_sim,'ys')\n", "semilogy([3,4,5,6,7],Pb_s_half_5_hard_sim,'gs')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Hard Decision Rate 1/2 Coding Measurements')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/2, K=3, Hard',\\\n", " 'R=1/2, K=5, Hard', 'R=1/2, K=7, Hard',\\\n", " 'R=1/2, K=9, Hard', 'R=1/2, K=3, Simulation',\\\n", " 'R=1/2, K=5, Simulation'),loc='lower left')\n", "grid();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can look at the surviving paths using the `traceback_plot` method." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cc1.traceback_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Soft Decision Decoding BEP Simulation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Soft decision decoding can also be done. In order to simulate the soft decision decoder, we can use the same setup as before, but now we specify 'soft' in the `viterbi_decoder` method. We also have to pick a quantization level when we do this. If we want 3-bit quantization we would specify that the quant_level=3. When we use soft decisions we have to scale our noisy received values to values on $[0,2^{n}-1]$. So for a three-bit quantizaiton, we would scale to values on $[0,7]$. This helps the system to get better distance metrics for all possible paths in the decoder, thus improving the BEP. The following shows how to simulate soft decisions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N_bits_per_frame = 10000\n", "EbN0 = 2\n", "total_bit_errors = 0\n", "total_bit_count = 0\n", "cc1 = fec.FECConv(('11101','10011'),25)\n", "# Encode with shift register starting state of '0000'\n", "state = '0000'\n", "while total_bit_errors < 100:\n", " # Create 100000 random 0/1 bits\n", " x = randint(0,2,N_bits_per_frame)\n", " y,state = cc1.conv_encoder(x,state)\n", " # Add channel noise to bits, include antipodal level shift to [-1,1]\n", " yn = dc.cpx_awgn(2*y-1,EbN0-3,1) # Channel SNR is 3dB less for rate 1/2\n", " # Scale & level shift to three-bit quantization levels [0,7]\n", " yn = (yn.real+1)/2*7\n", " z = cc1.viterbi_decoder(yn.real,'soft',quant_level=3)\n", " # Count bit errors\n", " bit_count, bit_errors = dc.bit_errors(x,z)\n", " total_bit_errors += bit_errors\n", " total_bit_count += bit_count\n", " print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))\n", "print('*****************************************************')\n", "print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/3,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_third_3 = fec.conv_Pb_bound(1/3,8,[3, 0, 15],SNRdB,1)\n", "Pb_s_third_4 = fec.conv_Pb_bound(1/3,10,[6, 0, 6, 0],SNRdB,1)\n", "Pb_s_third_5 = fec.conv_Pb_bound(1/3,12,[12, 0, 12, 0, 56],SNRdB,1)\n", "Pb_s_third_6 = fec.conv_Pb_bound(1/3,13,[1, 8, 26, 20, 19, 62],SNRdB,1)\n", "Pb_s_third_7 = fec.conv_Pb_bound(1/3,14,[1, 0, 20, 0, 53, 0, 184],SNRdB,1)\n", "Pb_s_third_8 = fec.conv_Pb_bound(1/3,16,[1, 0, 24, 0, 113, 0, 287, 0],SNRdB,1)\n", "Pb_s_half = fec.conv_Pb_bound(1/2,7,[4, 12, 20, 72, 225],SNRdB,1)\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_third_3,'--')\n", "semilogy(SNRdB,Pb_s_third_4,'--')\n", "semilogy(SNRdB,Pb_s_third_5,'g')\n", "semilogy(SNRdB,Pb_s_third_6,'--')\n", "semilogy(SNRdB,Pb_s_third_7,'--')\n", "semilogy(SNRdB,Pb_s_third_8,'--')\n", "#semilogy(SNRdB,Pb_s_half,'--')\n", "semilogy([0,1,2,3,4,5],[9.08e-02,2.73e-02,6.52e-03,\\\n", " 8.94e-04,8.54e-05,5e-6],'gs')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Soft Decision Rate 1/2 Coding Measurements')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/3, K=3, Soft',\\\n", " 'R=1/3, K=4, Soft','R=1/3, K=5, Soft',\\\n", " 'R=1/3, K=6, Soft','R=1/3, K=7, Soft',\\\n", " 'R=1/3, K=8, Soft','R=1/3, K=5, Sim', \\\n", " 'Simulation'),loc='upper right')\n", "grid();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The decoder can also do unquantized soft decisions. This is done by specifying 'unquant' for the metric type. The system will then expect floating point numbers on $[0,1]$ at the decoder input." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Rate 1/3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rate 1/3 convolution encoding/decoding can be done very similarly to the rate 1/2 code. The difference when instantiating, is that the rate 1/3 uses 3 generator polynmials instead of 2. The following table shows ideal generator polynomials at different constraint lengths for rate 1/3 convolutional codes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Table 2: Weight spectra $c_k$ for bounding the coded rate 1/3 BEP**.\n", "\n", "\n", "| CL |Polynomials |$d_{free}$|$d_f$|$d_f+1$|$d_f+2$|$d_f+3$|$d_f+4$|$d_f+5$|$d_f+6$|$d_f+7$|\n", "|:----:|:-------------------------------------------------:|:--------:|:---:|:-----:|:-----:|:-----:|-------|-------|-------|-------|\n", "|3 |(7,7,5) = ('111','111','101') |8 |3 |0 |15 |0 |58 |0 |201 |0 |\n", "|4 |(15,13,11) = ('1111','1101','1011') |10 |6 |0 |6 |0 |58 |0 |118 |0 |\n", "|5 |(31,27,21) = ('11111','11011','10101') |12 |12 |0 |12 |0 |56 |0 |320 |0 |\n", "|6 |(61,43,39) = ('111101','101011','100111') |13 |1 |8 |26 |20 |19 |62 |86 |204 |\n", "|7 |(121,101,91) = ('1111001','1100101','1011011') |14 |1 |0 |20 |0 |53 |0 |184 |0 |\n", "|8 |(247,217,149) = ('11110111','11011001','10010101') |16 |1 |0 |24 |0 |113 |0 |287 |0 |" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cc2 = fec.FECConv(('111','111','101'),10)\n", "cc2.trellis_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Rate 1/3 Hard Decision Decoding" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Weight Structure Bounds BEP\n", "Compare with Ziemer pg 668." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/3,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_third_3_hard = fec.conv_Pb_bound(1/3,8,[3, 0, 15, 0, 58, 0, 201, 0],SNRdB,0)\n", "Pb_s_third_4_hard = fec.conv_Pb_bound(1/3,10,[6, 0, 6, 0, 58, 0, 118, 0],SNRdB,0)\n", "Pb_s_third_5_hard = fec.conv_Pb_bound(1/3,12,[12, 0, 12, 0, 56, 0, 320, 0],SNRdB,0)\n", "Pb_s_third_6_hard = fec.conv_Pb_bound(1/3,13,[1, 8, 26, 20, 19, 62, 86, 204],SNRdB,0)\n", "Pb_s_third_7_hard = fec.conv_Pb_bound(1/3,14,[1, 0, 20, 0, 53, 0, 184],SNRdB,0)\n", "Pb_s_third_8_hard = fec.conv_Pb_bound(1/3,16,[1, 0, 24, 0, 113, 0, 287, 0],SNRdB,0)\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_third_3_hard,'--')\n", "#semilogy(SNRdB,Pb_s_third_4_hard,'--')\n", "semilogy(SNRdB,Pb_s_third_5_hard,'--')\n", "#semilogy(SNRdB,Pb_s_third_6_hard,'--')\n", "semilogy(SNRdB,Pb_s_third_7_hard,'--')\n", "#semilogy(SNRdB,Pb_s_third_8_hard,'--')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Hard Decision Rate 1/3 Coding Theory Bounds')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/3, K=3, Hard',\\\n", " #'R=1/3, K=4, Hard', 'R=1/3, K=5, Hard',\\\n", " #'R=1/3, K=6, Hard', 'R=1/3, K=7, Hard',\\\n", " #'R=1/3, K=7, Hard'),loc='upper right')\n", " 'R=1/3, K=5, Hard', 'R=1/3, K=7, Hard'),\\\n", " loc='upper right')\n", "grid();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### BEP Simulation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N_bits_per_frame = 10000\n", "EbN0 = 3\n", "total_bit_errors = 0\n", "total_bit_count = 0\n", "cc1 = fec.FECConv(('11111','11011','10101'),25)\n", "# Encode with shift register starting state of '0000'\n", "state = '0000'\n", "while total_bit_errors < 100:\n", " # Create 100000 random 0/1 bits\n", " x = randint(0,2,N_bits_per_frame)\n", " y,state = cc1.conv_encoder(x,state)\n", " # Add channel noise to bits, include antipodal level shift to [-1,1]\n", " yn_soft = dc.cpx_awgn(2*y-1,EbN0-10*log10(3),1) # Channel SNR is 10*log10(3) dB less\n", " yn_hard = ((sign(yn_soft.real)+1)/2).astype(int)\n", " z = cc1.viterbi_decoder(yn_hard.real,'hard')\n", " # Count bit errors\n", " bit_count, bit_errors = dc.bit_errors(x,z)\n", " total_bit_errors += bit_errors\n", " total_bit_count += bit_count\n", " print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))\n", "print('*****************************************************')\n", "print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/3,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_third_3_hard = fec.conv_Pb_bound(1/3,8,[3, 0, 15, 0, 58, 0, 201, 0],SNRdB,0)\n", "Pb_s_third_5_hard = fec.conv_Pb_bound(1/3,12,[12, 0, 12, 0, 56, 0, 320, 0],SNRdB,0)\n", "Pb_s_third_7_hard = fec.conv_Pb_bound(1/3,14,[1, 0, 20, 0, 53, 0, 184],SNRdB,0)\n", "Pb_s_third_5_hard_sim = array([8.94e-04,1.11e-04,8.73e-06])\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_third_3_hard,'r--')\n", "semilogy(SNRdB,Pb_s_third_5_hard,'g--')\n", "semilogy(SNRdB,Pb_s_third_7_hard,'k--')\n", "semilogy(array([5,6,7]),Pb_s_third_5_hard_sim,'sg')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Hard Decision Rate 1/3 Coding Measurements')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/3, K=3, Hard',\\\n", " 'R=1/3, K=5, Hard', 'R=1/3, K=7, Hard',\\\n", " ),loc='upper right')\n", "grid();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cc1.traceback_plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Soft Decision Decoding BEP Simulation\n", "Here we use 3-bit quantization soft decoding." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "N_bits_per_frame = 10000\n", "EbN0 = 2\n", "total_bit_errors = 0\n", "total_bit_count = 0\n", "cc1 = fec.FECConv(('11111','11011','10101'),25)\n", "# Encode with shift register starting state of '0000'\n", "state = '0000'\n", "while total_bit_errors < 100:\n", " # Create 100000 random 0/1 bits\n", " x = randint(0,2,N_bits_per_frame)\n", " y,state = cc1.conv_encoder(x,state)\n", " # Add channel noise to bits, include antipodal level shift to [-1,1] \n", " yn = dc.cpx_awgn(2*y-1,EbN0-10*log10(3),1) # Channel SNR is 10*log10(3) dB less\n", " # Translate to [0,7]\n", " yn = (yn.real+1)/2*7\n", " z = cc1.viterbi_decoder(yn,'soft',quant_level=3)\n", " # Count bit errors\n", " bit_count, bit_errors = dc.bit_errors(x,z)\n", " total_bit_errors += bit_errors\n", " total_bit_count += bit_count\n", " print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))\n", "print('*****************************************************')\n", "print('Bits Received = %d, Bit errors = %d, BEP = %1.2e' %\\\n", " (total_bit_count, total_bit_errors,\\\n", " total_bit_errors/total_bit_count))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "SNRdB = arange(0,12,.1)\n", "Pb_uc = fec.conv_Pb_bound(1/3,7,[4, 12, 20, 72, 225],SNRdB,2)\n", "Pb_s_third_3 = fec.conv_Pb_bound(1/3,8,[3, 0, 15, 0, 58, 0, 201, 0],SNRdB,1)\n", "#Pb_s_third_4 = fec.conv_Pb_bound(1/3,10,[6, 0, 6, 0, 58, 0, 118, 0],SNRdB,1)\n", "Pb_s_third_5 = fec.conv_Pb_bound(1/3,12,[12, 0, 12, 0, 56, 0, 320, 0],SNRdB,1)\n", "#Pb_s_third_6 = fec.conv_Pb_bound(1/3,13,[1, 8, 26, 20, 19, 62, 86, 204],SNRdB,1)\n", "Pb_s_third_7 = fec.conv_Pb_bound(1/3,14,[1, 0, 20, 0, 53, 0, 184, 0],SNRdB,1)\n", "#Pb_s_third_8 = fec.conv_Pb_bound(1/3,16,[1, 0, 24, 0, 113, 0, 287, 0],SNRdB,1)\n", "figure(figsize=(5,5))\n", "semilogy(SNRdB,Pb_uc)\n", "semilogy(SNRdB,Pb_s_third_3,'--')\n", "#semilogy(SNRdB,Pb_s_third_4,'--')\n", "semilogy(SNRdB,Pb_s_third_5,'g')\n", "#semilogy(SNRdB,Pb_s_third_6,'--')\n", "semilogy(SNRdB,Pb_s_third_7,'r--')\n", "#semilogy(SNRdB,Pb_s_third_8,'--')\n", "#semilogy(SNRdB,Pb_s_half,'--')\n", "semilogy([0,1,2,3,4,5],[9.08e-02,2.73e-02,6.52e-03,\\\n", " 8.94e-04,8.54e-05,5e-6],'gs')\n", "axis([0,12,1e-7,1e0])\n", "title(r'Soft Decision Rate 1/3 Coding Measurements')\n", "xlabel(r'$E_b/N_0$ (dB)')\n", "ylabel(r'Symbol Error Probability')\n", "legend(('Uncoded BPSK','R=1/3, K=3, Soft',\\\n", " #'R=1/3, K=4, Soft','R=1/3, K=5, Soft',\\\n", " 'R=1/3, K=5, Soft','R=1/3, K=7, Soft',\\\n", " #'R=1/3, K=8, Soft','R=1/2, K=5, Soft', \\\n", " 'R-1/3, K=5, Simulation'),loc='upper right')\n", "grid();" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.6" } }, "nbformat": 4, "nbformat_minor": 2 }