@@ -7,11 +7,11 @@ The main idea of the channel codes can be formulated as following thesises:
77- ** redundant bits** are added for * error detection* and * error correction* ;
88- some special algorithms (<u >coding schemes</u >) are used for this.
99
10- ![ ] ( https://raw.githubusercontent.com/kirlf/CSP/master/FEC/assets/FECmainidea1.png )
10+ < img src = " https://raw.githubusercontent.com/kirlf/CSP/master/FEC/assets/FECmainidea1.png " width = " 800 " />
1111
1212The fact how "further" a certain algorithm divides the code words among themselves, and determines how strongly it protects the signal from noise [ 1, p.23] .
1313
14- ![ ] ( https://habrastorage.org/webt/n7/o4/bs/n7o4bsf7_htlv10gsatc-yojbrq.png )
14+ < img src = " https://habrastorage.org/webt/n7/o4/bs/n7o4bsf7_htlv10gsatc-yojbrq.png " width = " 800 " />
1515
1616In the case of binary codes, the minimum distance between all existing code words is called ** Hamming distance** and is usually denoted ** dmin** :
1717
@@ -56,11 +56,18 @@ Main modeling routines:
5656- decode
5757- check the error correction
5858
59+ <img src =" https://habrastorage.org/webt/v3/v5/w2/v3v5w2gbwk34nzk_2qt25baoebq.png " width =" 500 " />
60+
5961``` python
6062import numpy as np
6163import commpy.channelcoding.convcode as cc
6264import commpy.modulation as modulation
6365
66+ def BER_calc (a , b ):
67+ num_ber = np.sum(np.abs(a - b))
68+ ber = np.mean(np.abs(a - b))
69+ return int (num_ber), ber
70+
6471N = 100000 # number of symbols per the frame
6572message_bits = np.random.randint(0 , 2 , N) # message
6673
@@ -91,14 +98,76 @@ Viterbi decoder parameters:
9198tb_depth = 5 * (m.sum() + 1 ) # traceback depth
9299```
93100
101+ Two oppitions of the Viterbi decoder will be tested:
102+ - * hard* (hard decision)
103+ - * unquatized* (soft decision)
104+
105+ Additionally, uncoded case will be considered.
106+
94107Simulation loop:
95108
96109``` python
97110EbNo = 5 # energy per bit to noise power spectral density ratio (in dB)
98111snrdB = EbNo + 10 * np.log10(k* rate) # Signal-to-Noise ratio (in dB)
99112noiseVar = 10 ** (- snrdB/ 10 ) # noise variance (power)
100113
114+ N_c = 10 # number of trials
115+
116+ BER_soft = np.empty((N_c,))
117+ BER_hard = np.empty((N_c,))
118+ BER_uncoded = np.empty((N_c,))
119+
120+ for cntr in range (N_c):
121+
122+ message_bits = np.random.randint(0 , 2 , N) # message
123+ coded_bits = cc.conv_encode(message_bits, trellis) # encoding
124+
125+ modulated = modem.modulate(coded_bits) # modulation
126+ modulated_uncoded = modem.modulate(message_bits) # modulation (uncoded case)
127+
128+ Es = np.mean(np.abs(modulated)** 2 ) # symbol energy
129+ No = Es/ ((10 ** (EbNo/ 10 ))* np.log2(M)) # noise spectrum density
130+
131+ noisy = modulated + np.sqrt(No/ 2 )* \
132+ (np.random.randn(modulated.shape[0 ])+ \
133+ 1j * np.random.randn(modulated.shape[0 ])) # AWGN
134+
135+ noisy_uncoded = modulated_uncoded + np.sqrt(No/ 2 )* \
136+ (np.random.randn(modulated_uncoded.shape[0 ])+ \
137+ 1j * np.random.randn(modulated_uncoded.shape[0 ])) # AWGN (uncoded case)
138+
139+ demodulated_soft = modem.demodulate(noisy, demod_type = ' soft' , noise_var = noiseVar) # demodulation (soft output)
140+ demodulated_hard = modem.demodulate(noisy, demod_type = ' hard' ) # demodulation (hard output)
141+ demodulated_uncoded = modem.demodulate(noisy_uncoded, demod_type = ' hard' ) # demodulation (uncoded case)
101142
143+ decoded_soft = cc.viterbi_decode(demodulated_soft, trellis, tb_depth, decoding_type = ' unquantized' ) # decoding (soft decision)
144+ decoded_hard = cc.viterbi_decode(demodulated_hard, trellis, tb_depth, decoding_type = ' hard' ) # decoding (hard decision)
145+
146+
147+ NumErr, BER_soft [cntr] = BER_calc(message_bits, decoded_soft[:- (L- 1 )]) # bit-error ratio (soft decision)
148+ NumErr, BER_hard [cntr] = BER_calc(message_bits, decoded_hard[:- (L- 1 )]) # bit-error ratio (hard decision)
149+ NumErr, BER_uncoded [cntr] = BER_calc(message_bits, demodulated_uncoded) # bit-error ratio (uncoded case)
150+
151+ mean_BER_soft = np.mean(BER_soft ) # averaged bit-error ratio (soft decision)
152+ mean_BER_hard = np.mean(BER_hard ) # averaged bit-error ratio (hard decision)
153+ mean_BER_uncoded = np.mean(BER_uncoded ) # averaged bit-error ratio (uncoded case)
154+
155+ print (" Soft decision:\n " + str (mean_BER_soft)+ " \n " )
156+ print (" Hard decision:\n " + str (mean_BER_hard)+ " \n " )
157+ print (" Uncoded message:\n " + str (mean_BER_uncoded)+ " \n " )
158+ ```
159+
160+ Outputs:
161+
162+ ``` python
163+ >> > Soft decision:
164+ >> > 0.0
165+ >> >
166+ >> > Hard decision:
167+ >> > 3.0000000000000004e-05
168+ >> >
169+ >> > Uncoded message:
170+ >> > 0.008782
102171```
103172
104173### Reference
0 commit comments