diff --git "a/\320\240\320\240\320\233/\320\240\320\240\320\2332.py" "b/\320\240\320\240\320\233/\320\240\320\240\320\2332.py" new file mode 100644 index 0000000000000000000000000000000000000000..2de5bb2b0456bad474e6b2eea6a4c3c8abc13446 --- /dev/null +++ "b/\320\240\320\240\320\233/\320\240\320\240\320\2332.py" @@ -0,0 +1,148 @@ +import random +import numpy as np + +import matplotlib.pyplot as plt + +def bb_scrambler(data_bits): + state = [1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0] + scrambled = [] + for bit in data_bits: + feedback_bit = state[-1] ^ state[-2] + # print(feedback_bit) + state.pop() # Удаляем последний Р±РёС‚ + state.insert(0, feedback_bit) # Вставляем новый Р±РёС‚ РІ начало + # print(state) + scrambled.append(bit ^ feedback_bit) # получаем Р±Рё С‚ скремблированной последовательности + return scrambled + +def test_bb_scrambler(): + data_bits = [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1] + scrambled = bb_scrambler(data_bits) + descrambled = bb_scrambler(scrambled) + print("Рсходные биты - ", data_bits) + print("Скремблированные биты - ", scrambled) + print("Дескремблированные биты - ", descrambled) + print(data_bits == descrambled) + +# test_bb_scrambler() + +def bit_interleaver(bits, rows, cols): + total = rows * cols + if len(bits) != total: + raise ValueError(f"Длина РІС…РѕРґРЅРѕРіРѕ потока должна быть равна {total} Р±РёС‚, получено {len(bits)}") + matrix = np.array(bits).reshape((rows, cols), order='F') + interleaved = matrix.flatten(order='C') + return interleaved.tolist() + +def bit_deinterleaver(interleaved_bits, rows, cols): + total = rows * cols + if len(interleaved_bits) != total: + raise ValueError(f"Длина РІС…РѕРґРЅРѕРіРѕ потока должна быть равна {total} Р±РёС‚, получено {len(interleaved_bits)}") + matrix = np.array(interleaved_bits).reshape((rows, cols), order='C') + deinterleaved = matrix.flatten(order='F') + return deinterleaved.tolist() + +def test_bit_deinterleaver(): + # 8PSK, нормальный кадр (64,800 Р±РёС‚), 3 столбца. + cols = 3 + rows = 64800 // cols + total_bits = rows * cols + + original_bits = np.random.randint(0, 2, total_bits).tolist() # генерируем случайную последовательность для теста + interleaved = bit_interleaver(original_bits, rows, cols) # инетрливинг + recovered = bit_deinterleaver(interleaved, rows, cols) # дкеинетрливинг + if (recovered == original_bits): + print("Данные переданы корректно") + else: + print("Данные переданы некорректно") + print("Первые 30 исходных битов: ", original_bits[:30]) + print("Первые 30 после интерливера: ", interleaved[:30]) + print("Первые 30 после деинтерливера:", recovered[:30]) + +# test_bit_deinterleaver() + +def psk8_mapper(bits): + if len(bits) % 3 != 0: + raise ValueError("Длина битовой последовательности должна быть кратна 3!") + + # Созвездие 8PSK (нормированное РЅР° среднюю мощность = 1) + constellation = { + (0, 0, 1): np.exp(0j), # 0В° + (0, 0, 0): np.exp(1j * np.pi / 4), # 45В° + (1, 0, 0): np.exp(1j * np.pi / 2), # 90В° + (1, 1, 0): np.exp(3j * np.pi / 4), # 135В° + (0, 1, 0): np.exp(1j * np.pi), # 180В° + (0, 1, 1): np.exp(5j * np.pi / 4), # 225В° + (1, 1, 1): np.exp(3j * np.pi / 2), # 270В° + (1, 0, 1): np.exp(7j * np.pi / 4) # 315В° + } + + # РќРѕСЂРјРёСЂРѕРІРєР° мощности (чтобы средняя мощность = 1) + norm_factor = np.sqrt(np.mean(np.abs(list(constellation.values())) ** 2)) + constellation = {k: v / norm_factor for k, v in constellation.items()} + + # Группируем биты РїРѕ 3 Рё сопоставляем СЃ символами + symbols = [] + for i in range(0, len(bits), 3): + triplet = tuple(bits[i:i + 3]) + # print(triplet) + symbols.append(constellation[triplet]) + + return np.array(symbols) + + +def psk8_demapper(symbols, noise_variance=0.1): + # Возможные точки созвездия 8PSK (нормированные) + constellation = [ + np.exp(0j), np.exp(1j * np.pi / 4), np.exp(1j * np.pi / 2), + np.exp(3j * np.pi / 4), np.exp(1j * np.pi), np.exp(5j * np.pi / 4), + np.exp(3j * np.pi / 2), np.exp(7j * np.pi / 4) + ] + bit_groups = [ + [0, 0, 1], [0, 0, 0], [1, 0, 0], [1, 1, 0], + [0, 1, 0], [0, 1, 1], [1, 1, 1], [1, 0, 1] + ] + llrs = [] + for y in symbols: + # Вычисляем расстояния РґРѕ всех точек созвездия + distances = np.abs(y - constellation) ** 2 + + # Для каждого бита (b0, b1, b2) вычисляем LLR + for bit_idx in range(3): # 3 бита РЅР° СЃРёРјРІРѕР» + # Находим минимальное расстояние для бита=0 Рё бита=1 + min_dist_bit0 = np.min([dist for i, dist in enumerate(distances) if bit_groups[i][bit_idx] == 0]) + min_dist_bit1 = np.min([dist for i, dist in enumerate(distances) if bit_groups[i][bit_idx] == 1]) + # LLR = (расстояние для 1) - (расстояние для 0) + llr = (min_dist_bit1 - min_dist_bit0) / noise_variance + if (llr>0): + llrs.append(0) + else: + llrs.append(1) + return llrs + + +def test_psk8_mapper_demapper(): + # Входная битовая последовательность (должна быть кратна 3) + input_bits = np.random.randint(0, 2, 60).tolist() + + # Преобразуем РІ символы 8PSK + symbols = psk8_mapper(input_bits) + + print("Биты:", input_bits) + # print("Символы 8PSK:", symbols) + + decoded_bits = psk8_demapper(symbols) + print("Декодированные биты:", decoded_bits) # Должны совпадать СЃ input_bits + print(input_bits == decoded_bits) + + plt.figure(figsize=(6, 6)) + plt.plot(np.real(symbols), np.imag(symbols), 'o', label='Mapped Symbols', alpha=0.5) + plt.xlabel('In-phase') + plt.ylabel('Quadrature') + plt.title('8PSK Constellation') + plt.legend() + plt.grid(True) + plt.axis('equal') + plt.show() + +test_psk8_mapper_demapper() \ No newline at end of file