Skip to content

Commit 0464d6b

Browse files
committed
Add example for convolutional codes
1 parent b4ac80f commit 0464d6b

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Authors: CommPy contributors
2+
# License: BSD 3-Clause
3+
4+
import math
5+
6+
import matplotlib.pyplot as plt
7+
import numpy as np
8+
9+
import commpy.channelcoding.convcode as cc
10+
import commpy.channels as chan
11+
import commpy.links as lk
12+
import commpy.modulation as mod
13+
import commpy.utilities as util
14+
15+
# =============================================================================
16+
# Convolutional Code 1: G(D) = [1+D^2, 1+D+D^2]
17+
# Standard code with rate 1/2
18+
# =============================================================================
19+
20+
# Number of delay elements in the convolutional encoder
21+
memory1 = np.array(2, ndmin=1)
22+
23+
# Generator matrix
24+
g_matrix1 = np.array((0o5, 0o7), ndmin=2)
25+
26+
# Create trellis data structure
27+
trellis1 = cc.Trellis(memory1, g_matrix1)
28+
29+
# =============================================================================
30+
# Convolutional Code 2: G(D) = [[1, 0, 0], [0, 1, 1+D]]; F(D) = [[D, D], [1+D, 1]]
31+
# RSC with rate 2/3
32+
# =============================================================================
33+
34+
# Number of delay elements in the convolutional encoder
35+
memory2 = np.array((1, 1))
36+
37+
# Generator matrix & feedback matrix
38+
g_matrix2 = np.array(((1, 0, 0), (0, 1, 3)))
39+
feedback = np.array(((2, 2), (3, 1)))
40+
41+
# Create trellis data structure
42+
trellis2 = cc.Trellis(memory2, g_matrix2, feedback, 'rsc')
43+
44+
# =============================================================================
45+
# Basic example using homemade counting and hard decoding
46+
# =============================================================================
47+
48+
# Traceback depth of the decoder
49+
tb_depth = None # Default value is 5 times the number or memories
50+
51+
for trellis in (trellis1, trellis2):
52+
for i in range(10):
53+
# Generate random message bits to be encoded
54+
message_bits = np.random.randint(0, 2, 1000)
55+
56+
# Encode message bits
57+
coded_bits = cc.conv_encode(message_bits, trellis)
58+
59+
# Introduce bit errors (channel)
60+
coded_bits[np.random.randint(0, 1000)] = 0
61+
coded_bits[np.random.randint(0, 1000)] = 0
62+
coded_bits[np.random.randint(0, 1000)] = 1
63+
coded_bits[np.random.randint(0, 1000)] = 1
64+
65+
# Decode the received bits
66+
decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth)
67+
68+
num_bit_errors = util.hamming_dist(message_bits, decoded_bits[:len(message_bits)])
69+
70+
if num_bit_errors != 0:
71+
print(num_bit_errors, "Bit Errors found!")
72+
elif i == 9:
73+
print("No Bit Errors :)")
74+
75+
# =============================================================================
76+
# Complete example using commpy features. Example with code 1
77+
# =============================================================================
78+
79+
# Modem : QPSK
80+
modem = mod.QAMModem(4)
81+
82+
# AWGN channel
83+
channels = chan.SISOFlatChannel(None, (1+0j, 0j))
84+
85+
# SNR range to test
86+
SNRs = np.arange(0, 6) + 10 * math.log10(modem.num_bits_symbol)
87+
88+
89+
# Modulation function
90+
def modulate(bits):
91+
return modem.modulate(cc.conv_encode(bits, trellis1, 'cont'))
92+
93+
94+
# Demodulation function
95+
def demode(msg):
96+
return modem.demodulate(msg, 'hard')
97+
98+
99+
# Receiver function (no process required as there are no fading)
100+
def receiver(y, h, constellation, noise_var):
101+
return modem.demodulate(y, 'hard')
102+
103+
104+
# Decoder function
105+
def decoder(msg):
106+
return cc.viterbi_decode(msg, trellis1)
107+
108+
109+
# Build model from parameters
110+
code_rate = trellis1.k / trellis1.n
111+
model = lk.LinkModel(modulate, channels, receiver,
112+
modem.num_bits_symbol, modem.constellation, modem.Es,
113+
decoder, code_rate)
114+
115+
# Test
116+
BERs = lk.link_performance(model, SNRs, 10000, 600, 5000, code_rate)
117+
plt.semilogy(SNRs, BERs, 'o-')
118+
plt.grid()
119+
plt.xlabel('Signal to Noise Ration (dB)')
120+
plt.ylabel('Bit Error Rate')
121+
plt.show()

0 commit comments

Comments
 (0)