Exemplo n.º 1
0
    def test_conv_encode_viterbi_decode(self):
        niters = 10
        blocklength = 1000

        for i in range(niters):
            msg = randint(0, 2, blocklength)

            coded_bits = conv_encode(msg, self.trellis_1)
            decoded_bits = viterbi_decode(coded_bits.astype(float),
                                          self.trellis_1, 15)
            assert_array_equal(decoded_bits[:-2], msg)

            coded_bits = conv_encode(msg, self.trellis_1)
            coded_syms = 2.0 * coded_bits - 1
            decoded_bits = viterbi_decode(coded_syms, self.trellis_1, 15,
                                          'unquantized')
            assert_array_equal(decoded_bits[:-2], msg)

            coded_bits = conv_encode(msg, self.trellis_2)
            decoded_bits = viterbi_decode(coded_bits.astype(float),
                                          self.trellis_2, 15)
            assert_array_equal(decoded_bits[:-2], msg)

            coded_bits = conv_encode(msg, self.trellis_2)
            coded_syms = 2.0 * coded_bits - 1
            decoded_bits = viterbi_decode(coded_syms, self.trellis_2, 15,
                                          'unquantized')
            assert_array_equal(decoded_bits[:-2], msg)
Exemplo n.º 2
0
 def commpy_decode_batch(self,y):
     u_hat0 = cc.viterbi_decode(y[0], self.trellisNSC, self.tb_depth,'unquantized')
     u_hat = np.empty(shape=[y.shape[0],len(u_hat0)],dtype=np.int8)
     u_hat[0] = u_hat0
     for i in range(len(y)-1):
         u_hat[i+1] = cc.viterbi_decode(y[i+1], self.trellisNSC, self.tb_depth,'unquantized')
     return u_hat
Exemplo n.º 3
0
    def test_conv_encode_viterbi_decode(self):
        niters = 10
        blocklength = 1000

        for i in xrange(niters):
            msg = randint(0, 2, blocklength)
            
            coded_bits = conv_encode(msg, self.trellis_1)
            decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_1, 15)
            assert_array_equal(decoded_bits[:-2], msg)
            
            coded_bits = conv_encode(msg, self.trellis_2)
            decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_2, 15)
            assert_array_equal(decoded_bits[:-2], msg)
Exemplo n.º 4
0
    def decode(self, encoded: np.ndarray) -> np.ndarray:
        """
        Use the configured trellis to perform vitirbi decoding algorithm on the received encoded bits.

        :param encoded: array of bits encoded then received
        :return: array of decoded message bits that were originally encoded (with probability varying by signal noise)
        """
        # decode the probable bits from the encoded string
        decoded = cc.viterbi_decode(encoded,
                                    self._trellis,
                                    decoding_type='hard')

        # return the bytes from the decoded bits
        message = np.packbits(decoded, bitorder='big')

        # detect message length and truncate
        message_length = int.from_bytes(message[0:LENGTH_SIZE],
                                        byteorder='big',
                                        signed=False)
        if message_length > len(message) - LENGTH_SIZE:
            raise RuntimeError('Invalid message-length tag')
        message = message[LENGTH_SIZE:LENGTH_SIZE + message_length]

        logging.info(
            'Decoded {} convolution coded parity bits into {}-byte message'.
            format(len(encoded), message_length))
        return message
Exemplo n.º 5
0
def conv_decoder(coded_bits):
    generator_matrix = np.array([[05, 07]])
    M = np.array([2])
    trellis = cc.Trellis(M, generator_matrix)
    tb_depth = 5 * (M.sum() + 1)
    return 2 * cc.viterbi_decode(
        ((coded_bits + 1) / 2).astype(float), trellis, tb_depth) - 1
def test_radio_encoder():
    """Online tool to visualize Encoder:
    http://www.ee.unb.ca/cgi-bin/tervo/viterbi.pl
    """
    # Create a fake packet
    packet = [0, 0, 1, 1]
    # Test convolution code encoder at different memory size
    EncoderTest = namedtuple('EncoderTest', ['trellis', 'wanted'])
    tests = [
        EncoderTest(
            None,  # default option (r= 1/2, k=3)  
            np.array([0, 0, 0, 0, 1, 1, 0, 1])),
        EncoderTest(build_trellis_structure(1, 2, constraint_len=4),
                    np.array([0, 0, 0, 0, 1, 1, 0, 1])),
        EncoderTest(build_trellis_structure(1, 3, constraint_len=4),
                    np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0])),
    ]
    for test in tests:
        tx = RadioTransmitter(0, 0, 'qpsk', test.trellis)
        # Test correctness of encoder
        got, _ = tx._simulate_radio_transmitter(packet)
        np.testing.assert_array_equal(got, test.wanted)

        # Test correctness of output message by decoding with Viterbi
        decoded = viterbi_decode(got, tx.trellis, 4)
        np.testing.assert_array_equal(packet, decoded)
    def turbo_compute((idx, x)):
        '''
        Compute Turbo Decoding in 1 iterations for one SNR point.
        '''
        np.random.seed()
        message_bits = np.random.randint(0, 2, args.block_len)

        coded_bits = cc.conv_encode(message_bits, trellis1)
        received = corrupt_signal(coded_bits,
                                  noise_type=args.noise_type,
                                  sigma=test_sigmas[idx],
                                  vv=args.v,
                                  radar_power=args.radar_power,
                                  radar_prob=args.radar_prob,
                                  denoise_thd=args.radar_denoise_thd)

        # make fair comparison between (100, 204) convolutional code and (100,200) RNN decoder, set the additional bit to 0
        received[-2 * int(M):] = 0.0

        decoded_bits = cc.viterbi_decode(received.astype(float),
                                         trellis1,
                                         tb_depth,
                                         decoding_type='unquantized')
        decoded_bits = decoded_bits[:-int(M)]
        num_bit_errors = hamming_dist(message_bits, decoded_bits)
        return num_bit_errors
Exemplo n.º 8
0
 def fec_decoder(self, data_in):
     memory = np.array([6])
     g_matrix = np.array([[91, 121]
                          ])  # G(D) = [1+D^2+D^3+D^5+D^6, 1+D+D^2+D^3+D^6]
     trellis = cc.Trellis(memory, g_matrix)
     data_out = cc.viterbi_decode(data_in,
                                  trellis,
                                  tb_depth=int(len(data_in) / 2))
     return data_out[:-6]
Exemplo n.º 9
0
def conv_decoder(coded_bits):
    generator_matrix = np.array([[05, 07]])
    M = np.array([2])
    trellis = cc.Trellis(M, generator_matrix)
    tb_depth = 5 * (M.sum() + 1)
    return cc.viterbi_decode(coded_bits.astype(float),
                             trellis,
                             tb_depth,
                             decoding_type='unquantized')
Exemplo n.º 10
0
    def convdecode(self, symbols):
	# better do only once:
        self.memory = np.array([2])
        self.g_matrix = np.array([[0o7, 0o5]])
        self.tr = Trellis(self.memory, self.g_matrix, 0, 'default')
	#
        x = list(chr(s+ord('0')) for s in symbols)
        bits = np.array(x)
        decoded = viterbi_decode(bits, self.tr, 15)
        return decoded
Exemplo n.º 11
0
 def decoder_soft(msg):
     msg_d = msg
     puncture_matrix = Wifi80211._get_puncture_matrix(coding[0], coding[1])
     if puncture_matrix:
         try:
             msg_d = cc.depuncturing(msg, puncture_matrix, math.ceil(len(msg) * coding[0] / coding[1] * 2))
         except IndexError as e:
             print(e)
             print("Decoded message size %d" % (math.ceil(len(msg) * coding[0] / coding[1] * 2)))
             print("Encoded message size %d" % len(msg))
             print("Coding %d/%d" % (coding[0], coding[1]))
     return cc.viterbi_decode(msg_d, trellis1, decoding_type='soft')
Exemplo n.º 12
0
    def test_conv_encode_viterbi_decode(self):
        niters = 10
        blocklength = 1000

        for n in range(niters):
            msg = randint(0, 2, blocklength)

            # Previous tests
            for i in range(len(self.trellis)):
                coded_bits = conv_encode(msg, self.trellis[i])
                decoded_bits = viterbi_decode(coded_bits.astype(float),
                                              self.trellis[i], 15)
                assert_array_equal(decoded_bits[:len(msg)], msg)

                coded_bits = conv_encode(msg,
                                         self.trellis[i],
                                         termination='cont')
                decoded_bits = viterbi_decode(coded_bits.astype(float),
                                              self.trellis[i], 15)
                assert_array_equal(decoded_bits, msg)

                coded_bits = conv_encode(msg, self.trellis[i])
                coded_syms = 2.0 * coded_bits - 1
                decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15,
                                              'unquantized')
                assert_array_equal(decoded_bits[:len(msg)], msg)

                coded_bits = conv_encode(msg, self.trellis[i])
                coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2
                decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15,
                                              'soft')
                assert_array_equal(decoded_bits[:len(msg)], msg)

                coded_bits = conv_encode(msg,
                                         self.trellis[i],
                                         termination='cont')
                coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2
                decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15,
                                              'soft')
                assert_array_equal(decoded_bits, msg)

                coded_bits = conv_encode(msg, self.trellis[i])
                coded_syms = (2.0 * coded_bits - 1) * inf
                decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15,
                                              'soft')
                assert_array_equal(decoded_bits[:len(msg)], msg)

                coded = conv_encode(msg, self.trellis[i], termination='cont')
                coded_bits = coded.astype(float)
                coded_bits[coded_bits == 1.0] = inf
                coded_bits[coded_bits == 0.0] = -inf
                decoded_bits = viterbi_decode(coded_bits, self.trellis[i], 15,
                                              'soft')
                assert_array_equal(decoded_bits, msg)
Exemplo n.º 13
0
    def viterbi_decode(self, bits, signal=None):
        if signal is None:
            ht = False
            rate = 6
        else:
            ht, rate, mcs = signal.ht, signal.rate, signal.mcs

        if (not ht and rate in [9, 18, 36, 54]) or (ht and mcs in [2, 4, 6]):
            print '[PUNCTURE] 3/4'
            # 3/4
            new_bits = []
            for i in range(0, len(bits), 12):
                new_bits.extend(bits[i:i + 3])
                new_bits.extend([2, 2])
                new_bits.extend(bits[i + 3:i + 7])
                new_bits.extend([2, 2])
                new_bits.extend(bits[i + 7:i + 11])
                new_bits.extend([2, 2])
                new_bits.extend(bits[i + 11:i + 12])
            bits = new_bits
        elif (not ht and rate in [48]) or (ht and mcs in [5]):
            print '[PUNCTURE] 2/3'
            # 2/3
            new_bits = []
            for i in range(0, len(bits), 9):
                new_bits.extend(bits[i:i + 3])
                new_bits.append(2)
                new_bits.extend(bits[i + 3:i + 6])
                new_bits.append(2)
                new_bits.extend(bits[i + 6:i + 9])
                new_bits.append(2)
            bits = new_bits
        elif ht and mcs in [7]:
            print '[PUNCTURE] 5/6'
            # 5/6
            new_bits = []
            for i in range(0, len(bits), 6):
                new_bits.extend(bits[i:i + 3])
                new_bits.extend([2, 2])
                new_bits.extend(bits[i + 3:i + 5])
                new_bits.extend([2, 2])
                new_bits.append(bits[i + 5])
            bits = new_bits
        else:
            print '[NO PUNCTURE]'

        extended_bits = np.array([0] * 2 + bits + [0] * 12)
        trellis = cc.Trellis(np.array([7]), np.array([[0133, 0171]]))
        return list(cc.viterbi_decode(extended_bits, trellis,
                                      tb_depth=35))[:-7]
Exemplo n.º 14
0
def viterbi_decode_sequences(encoded_seqs, L, rate=1 / 2):
    """
  Given a list of convolutionally encoded sequences, uses the Viterbi
  algorithm on each element to decode it using a hard-decision boundary.
  The Trellis is generated as per the specified L and k.

  Returns a list of decoded elements.
  """
    decoded_seqs = [None for _ in range(len(encoded_seqs))]
    generator_matrix = gen_gmatrix(L, rate)
    memory = np.array([L - 1])
    trellis = cc.Trellis(memory, generator_matrix)

    for i, encoded_seq in enumerate(encoded_seqs):
        decoded_seq = cc.viterbi_decode(encoded_seq.astype(float), trellis)
        decoded_seqs[i] = decoded_seq

    return decoded_seqs
Exemplo n.º 15
0
def conv_decoder(codeword_bits, trellis, tb_depth):
	return cc.viterbi_decode(codeword_bits.astype(float), trellis, tb_depth, decoding_type = 'unquantized')
Exemplo n.º 16
0
        if NType == 'iid':
            noise = test_sigmas[idx] * np.random.standard_normal(
                coded_bits.shape)  # Define noise

            uu = np.sqrt(0.5) * np.random.standard_normal(coded_bits.shape)
            vv = np.sqrt(0.5) * np.random.standard_normal(coded_bits.shape)
            rayleigh_coeff = np.sqrt(uu**2 + vv**2)

            received = rayleigh_coeff * (2 * coded_bits -
                                         1) + noise  # Modulation plus noise

#        print('received: ')
#        print(received)

        decoded_bits = cc.viterbi_decode(received.astype(float),
                                         trellis,
                                         tb_depth,
                                         decoding_type='unquantized')

        received_odd = received[::2]  # first, third, fifth, etc
        received_even = received[1::2]  # second, fourth, sixth, etc
        _, map_decoded_bits = commpy.channelcoding.map_decode(
            sys_symbols=received_odd.astype(float),
            non_sys_symbols=received_even.astype(float),
            trellis=trellis,
            noise_variance=test_sigmas[idx]**2,
            L_int=np.zeros(received_odd.shape),
            mode='decode')
        #        print('decoded_bits: ')
        #        print(decoded_bits)

        num_bit_errors = hamming_dist(message_bits, decoded_bits[:-int(M)])
Exemplo n.º 17
0
for trellis in (trellis1, trellis2, trellis3):
    for i in range(10):
        # Generate random message bits to be encoded
        message_bits = np.random.randint(0, 2, 1000)

        # Encode message bits
        coded_bits = cc.conv_encode(message_bits, trellis)

        # Introduce bit errors (channel)
        coded_bits[np.random.randint(0, 1000)] = 0
        coded_bits[np.random.randint(0, 1000)] = 0
        coded_bits[np.random.randint(0, 1000)] = 1
        coded_bits[np.random.randint(0, 1000)] = 1

        # Decode the received bits
        decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis,
                                         tb_depth)

        num_bit_errors = util.hamming_dist(message_bits,
                                           decoded_bits[:len(message_bits)])

        if num_bit_errors != 0:
            print(num_bit_errors, "Bit Errors found!")
        elif i == 9:
            print("No Bit Errors :)")

# ==================================================================================================
# Complete example using Commpy features and compare hard and soft demodulation. Example with code 1
# ==================================================================================================

# Modem : QPSK
modem = mod.QAMModem(4)
Exemplo n.º 18
0
# g_matrix = array([[ 109	 , 79]]) # G(D) = [1+D^2, 1+D+D^2]
memory = array([3])
g_matrix = array([[ 109 , 79]]) # G(D) = [1+D^2, 1+D+D^2]
trellis = cc.Trellis(memory, g_matrix)
# a='111101011'
# message_bits = np.array(list(a))
# coded_bits = cc.conv_encode(message_bits, trellis, code_type='default', puncture_matrix=None)
# print(coded_bits)

bit_num = 8414
print(bit_num)
num_bin  = '{:016b}'.format(bit_num)
num_bits = [ ]
for i in  num_bin:
	if i =='0':
		num_bits.append(0)
	elif i == '1':
		num_bits.append(1)

num_encoded = cc.conv_encode(num_bits, trellis, code_type='default', puncture_matrix=None)
print(num_encoded)
# coded_bits = np.array([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0])
# print(coded_bits)
ans = cc.viterbi_decode(num_encoded, trellis, tb_depth=None, decoding_type='hard')
print(ans)
# print(str(message_bits))
# ans = np.array2string(np.random.randint(0,2,10000))
# ans+= '\n'
# print (ans)
# output_file = open("INPUT.txt", "w")
# output_file.write(ans)
Exemplo n.º 19
0
def decoder_hard(msg):
    return cc.viterbi_decode(msg, trellis1)
Exemplo n.º 20
0
 def commpy_decode_sequence(self,y):
     return cc.viterbi_decode(y, self.trellisNSC, self.tb_depth,'unquantized')
Exemplo n.º 21
0
def decode(v):  # demodulate and decode
    idx = 0

    # Decode the Bit Length
    print('Bit Length Packet...')
    idx = find_header(v, idx)
    start_point = idx
    ans = []  # received bit list
    for i in range(
            2 * (16 + memory_len)
    ):  # 32 bit for bit_len info (add mempry_len due to conv code prop)
        bit = v[idx:idx + bit_len]
        weight0 = get_weight(signal_zero, bit)
        weight1 = get_weight(signal_one, bit)
        if weight0 >= weight1: ans.append(0)
        else: ans.append(1)
        idx += bit_len
    # print(ans)

    # decode bit length info by Veterbi Algorithm
    ans = np.array(ans)
    ans = cc.viterbi_decode(ans, trellis, tb_depth=None,
                            decoding_type='hard')[:-memory_len]
    num_decoded = ''
    for i in range(len(ans)):
        if ans[i] == 1:
            num_decoded += '1'
        elif ans[i] == 0:
            num_decoded += '0'
    #Print encoded and decoded  bit num
    # print('bit num endoded info: ', num_decoded)
    bit_num = int(num_decoded, 2)
    print('The num of bits will be received is: ', bit_num)

    # Decode Text Part
    ans = []
    packet_num = 0
    for j in range(bit_num):

        if j % packet_size == 0:  # if a new packet begin
            idx += 3 * bit_len
            packet_num += 1
            print('\nText info packet', packet_num)
            idx = find_header(v, idx)  # Re-synchronize

        bit = v[idx:idx + bit_len]
        weight0 = get_weight(signal_zero, bit)
        weight1 = get_weight(signal_one, bit)
        if weight0 >= weight1: ans.append(0)
        else: ans.append(1)
        # ans.append(weight1)
        idx += bit_len
    end_point = idx

    # decode by Veterbi Algorithm
    ans = np.array(ans)
    ans = cc.viterbi_decode(ans, trellis, tb_depth=None,
                            decoding_type='hard')[:-memory_len]
    text_decoded = ''
    for i in range(len(ans)):
        if ans[i] == 1:
            text_decoded += '1'
        elif ans[i] == 0:
            text_decoded += '0'

    if test:
        f = open("INPUT.txt", 'r')
        context = f.readlines()
        f.close()
        if (len(context) != 1):
            print("wrong input file")
            exit()
        text = context[0]
        print('\nTransimission time: ',
              (end_point - start_point) / sd.default.samplerate, 's')
        print('Receive encoded bit num: ', bit_num)
        print('Receive decoded bit num: ', len(text_decoded))
        print('Actual send bit', len(text))
        err = 0
        err_list = []
        for i in range(min(len(text_decoded), len(text))):
            if text[i] != text_decoded[i]:
                err += 1
                err_list.append(i)
        print("Total error bit num : ", err)
        print('Acuuracy rate :', 1 - err / len(text))
        print('Error list:', err_list, '\n')

        output_file = open("OUTPUT.txt", "w")
        output_file.write(text_decoded)

    else:
        output_file = open("OUTPUT.txt", "w")
        output_file.write(text_decoded)


# ############################################
# Abandon as of now
# # include repeat
# 	else:
# 		print('Begin to decode the first packet....')
# 		ans_list = []
# 		bit_num = 0
# 		max_power = 0
# 		last_power = 0
# 		while True:
# 			bit = v[idx : idx + bit_len]
# 			power = np.dot(preamble, v[idx : idx + 5 * bit_len])
# 			energy  = np.linalg.norm(bit)
# 			# print (energy)
# 			# print(power)
# 			if power < last_power and last_power == max_power and last_power > 15*energy and power > 0 :
# 				 # print('Received bit num',bit_num-1)
# 				ans = ans[:-1]
# 				break
# 			last_power = power
# 			max_power = max(max_power,power)
# 			weight0 = sum(signal_zero * bit)
# 			weight1 = sum(signal_one * bit)
# 			# print ('0 weight: ', weight0)
# 			# print('1 weight:', weight1)
# 			ans_list.append([weight0,weight1])
# 			idx += bit_len
# 			bit_num += 1

# 		print('\nLooking for the scond packet...')
# 		n = idx + 10*bit_len
# 		power = np.dot(preamble, v[n: n + 5 * bit_len])
# 		 # according to the device

# 		# find the header
# 		while power < threshold:
# 			power = np.dot(preamble, v[n: n + 5 * bit_len])
# 			n += 1
# 		print("first step :",n)
# 		max_power = 0
# 		header = n
# 		for i in range(1, 1):
# 			curr_power = np.dot(preamble, v[n + i: n + i + 5 * bit_len])
# 			if curr_power > max_power:
# 				max_power = curr_power
# 				header = n + i
# 		print("second step :",header)
# 		idx =  header + bit_len * 5 # pass the preamble

# 		print('Begin to decode the second packet....')
# 		first_bit_num = bit_num -2
# 		bit_num = 0
# 		max_power = 0
# 		last_power = 0
# 		while True:
# 			if bit_num > first_bit_num:
# 				break
# 			bit = v[idx : idx + bit_len]
# 			power = np.dot(preamble, v[idx : idx + 5 * bit_len])
# 			energy  = np.linalg.norm(bit)
# 			# print (energy)
# 			# print(power)
# 			if power < last_power and last_power == max_power and last_power > 15*energy and power > 0 :
# 				ans = ans[:-1]
# 				break
# 			last_power = power
# 			max_power = max(max_power,power)
# 			weight0 = sum(signal_zero * bit)
# 			weight1 = sum(signal_one * bit)
# 			ans_list[bit_num][0]+= weight0
# 			ans_list[bit_num][1]+= weight1
# 			idx += bit_len
# 			bit_num += 1

# 		for i in range(bit_num):

# 			if ans_list[i][0] >= ans_list[i][1]:
# 				ans.append(0)
# 			else:
# 				ans.append(1)
# 		ans = np.array(ans)
# 		ans = cc.viterbi_decode(ans, trellis, tb_depth=None, decoding_type='hard')[:-2]
# 		text_decoded = ''
# 		for i in range(len(ans)):
# 			if ans[i] == 1:
# 				text_decoded +='1'
# 			elif ans[i] == 0:
# 				text_decoded +='0'

# 		if test:
# 			f = open("INPUT.txt", 'r')
# 			context = f.readlines()
# 			f.close()
# 			if (len(context) != 1):
# 				print("wrong input file")
# 				exit()
# 			text = context[0]
# 			print(text_decoded)
# 			print(text)
# 			print('Receive bit num: ',bit_num)
# 			print('Text bit num', len(text))
# 			err = 0
# 			err_list = []
# 			for i in range(len(text)):
# 				if text[i] != text_decoded[i]:
# 					err += 1
# 					err_list.append(i)
# 			print("total error : ", err)
# 			print('error rate :' , err/bit_num)
# 			print('error list:', err_list)
# 		else:

# 			print('Receive bit num: ',bit_num)
# 			print('Decode as below: ')
# 			print(ans)
# 			output_file = open("OUTPUT.txt", "w")
# 			output_file.write(ans)
Exemplo n.º 22
0
def decoder_soft(msg):
    return cc.viterbi_decode(msg, trellis1, decoding_type='soft')
Exemplo n.º 23
0
# Traceback depth of the decoder
tb_depth = 5*(M.sum() + 1)

for i in range(10):
    # Generate random message bits to be encoded
    message_bits = np.random.randint(0, 2, 1000)

    # Encode message bits
    coded_bits = cc.conv_encode(message_bits, trellis)

    # Introduce bit errors (channel)
    #coded_bits[4] = 0
    #coded_bits[7] = 0

    # Decode the received bits
    decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth)

    num_bit_errors = hamming_dist(message_bits, decoded_bits[:-M])
    #num_bit_errors = 1

    if num_bit_errors !=0:
        #print(num_bit_errors, "Bit Errors found!")
        #print(message_bits)
        #print(decoded_bits[tb_depth+3:])
        #print(decoded_bits)
        break
    else:
        print("No Bit Errors :)")

#print("==== Message Bits ===")
#print(message_bits)