САМОСТОЯТЕЛЬНАЯ РАБОТА
«Радиомодем : процедура ARQ »
Статья 3.
Выполнили: студенты группы 9110 Городничев А.В, Воронин А.Е
Краткое описание задания:
Постановка
задачи:
1) Разработка и экспериментальное
исследование модели. Необходимо будет продемонстрировать процесс передачи текстового сообщения в
произвольном направлении с реализованным механизмом автоматического повтора
ранее переданных сообщений.
Анализ поставленной
задачи.
Для решения данной задачи сначала
необходимо вспомнить структуру передаваемого пакета (рис.2.) и изобразить
алгоритм передачи и приема текстовых файлов (рис.3.)
Рис.2. Структура передаваемого пакета.
Рис.3. Алгоритм передачи и приема текстовых файлов.
Исходя из этого, можно составить
программу, описывающий данный алгоритм.
Она состоит из нескольких частей:
1) initSettings.m – установка основных
параметров системы, таких как позиционность модуляции, размер кодового слова и
длина кодируемого сообщения, задается полином для службы проверки целостности
принятого сообщения и т.д.;
2)
transmit.m – реализация передатчика, в котором идет формирование
сообщения L2 и L1 уровня, то есть происходит реализация службы CRC-8, кодирования, с помощью кода БЧХ(255,207) и
модуляции 8-PSK;
3)
Receive_msg.m – реализация приемника. Здесь происходит обратный процесс, т.е.
демодуляция, декодирование. С помощью службы CRC-8 идет проверка целостности принятого сообщения и
извлекается информационная часть со всеми служебными полями;
4) test_unit.m – главный файл, в котором осуществляется тестирование модели. В нем реализован весь алгоритм передачи и приема. Здесь происходит чтение из файлов, запись в переменную, вычисление числа пакетов, необходимых для передачи, формирование сообщения L3 уровня. Далее сообщение отправляется на передатчик, после чего уходит в канал, который представлен в виде блока awgn, где накладывается шум заданной интенсивности. Пройдя через него, сигнал поступает на приемник, где из него извлекается необходимая информация и происходит ее обработка. В приемнике осуществляется проверка на ошибки каждого отдельного пакета. Если ошибок нет, то на передатчик отправляется сообщение ACK, которое служит сигналом для передатчика об успешной передачи пакета и необходимости передачи следующего пакета. Если ошибки есть, то на передатчик отправляется сообщение NACK, которое служит сигналом для передатчика об ошибочной передачи пакета и необходимости повторной передачи ошибочного пакета. Далее содержимое всех пакетов записывается в текстовую переменную, и из них собирается целостное сообщение.
Тексты программ:
1) initSettings.m
function set =
initSettings()
%% Инициализация основных
параметров модели
% Выбор файла для
передачи
set.FileName = 'SendText.txt';
% параметры модели
% позиционность модуляции -
8-PSK
set.mPos = 8;
% Параметры
помехоустойчивого кодека
% Для примера используется
линейный блоковый код БЧХ(255,223):
% Длина кодового слова n =
2^m-1 = 255 при m = 8
% Размер кодируемого блока
k = n-m = 207
set.m = 8;
set.n = 2^set.m-1; % Codeword
length = 255
% информационное поле физ.
уровня - полная длина передаваемого L2-сообщения
set.k = 207; % Message length = 223
% Параметры CRC
%CRC-8-CCIT, используется в ISDN Header Error Control and Cell Delineation ITU-T и т.п.
set.poly=[1 0 0 0 0 0 1 1 1];
[set.x set.y]=size(set.poly); %размерность полинома
% переменная, равная длине
информационной части L2-сообщения
set.length_msg_Lev2 = set.k -
set.y + 1;% сообщение состоит из 199 битов: "set.k - CRC"
% переменная, равная длине
передаваемого сообщения 3 уровня,
set.length_msg_Lev3 = 199;% расчетная длина L3-сообщения
2) transmit.m
function msgIQ = transmit(msgL3)
% msgL3 - сообщение в
бинарной форме
% установка параметров
модели
st=initSettings();
% ================== Канальный уровень ================================
% Формат сообщения (207 бита):
% поле "Data" (L3-сообщение) - 199 битов
% поле CRC - 8 битов
%
======================================================================
%% Подготовка к передаче сообщения
% сборка части L2-сообщения
msg_L20 = [msgL3];
% получение CRC кода
m = [msg_L20 zeros(1,st.y-1)]; %вставка нулей в поле CRC
[q r] = deconv(m,st.poly); % поиск частного и остатка от
деления
%информационной части на порождающий полином CRC кода
r = mod(abs(r),2);
CRC = r(st.length_msg_Lev2 +
1:end);%расчет CRC
% сборка сообщения
msg_L2 = [msg_L20 CRC];
%disp(['Длина поля Сообщение_L2: ',
num2str(length(msg_L2))]);
%disp(['Длина поля Cообщение L3-уровня: ',
num2str(length(msgL3))]);
%disp(['Длина поля CRC-8: ',
num2str(length(CRC))]);
%disp(['Длина сообщения
L2-уровня: ', num2str(length(msg_L2))]);
trx = msg_L2;
%disp([' ']);
% disp(['Структура
сообщения L1-уровня:']);
% ================== Физический уровень
================================
%% Помехоустойчивое кодирование
code_word = encode(trx,st.n,st.k,'bch/binary');
%disp(['Длина поля Cообщение L2-уровня: ',
num2str(length(msg_L2))]);
%disp(['Длина поля FEC: ', num2str(st.n-st.k)]);
% codeword имеет размер 255 битов
% disp(['Длина сообщения L1-уровня: ', num2str(length(code_word))]);
L1 = [code_word]';
%disp(['Длина поля Сообщение_L1: ', num2str(length(L1))]);
%% Модуляция
h = modem.pskmod(st.mPos);
% h - модем 8-PSK с
позиционностью mPos
% Требуется настроить остальные его параметры:
% Параметры модуляции
h.inputtype = 'bit';
h.SymbolOrder = 'gray';
h.PhaseOffset = 0;
% собственно модуляция
IQ_signal = modulate(h, L1);
msgIQ = IQ_signal;
3) Receive_msg.m
function [length_data, msgL3, errs] =
Receive_msg(rxIQ)
% установка параметров
модели
st = initSettings();
msgL3 = '';
errs = 0;
%% Параметры демодуляции
h = modem.pskdemod(st.mPos);
h.SymbolOrder = 'gray';
h.PhaseOffset = 0;
h.OutputType = 'bit';
% собственно демодуляция
s = demodulate(h,rxIQ);
%% Помехоустойчивое декодирование
received_mes_L1 = decode(s(1:st.n),st.n,st.k,'bch/binary');
% ==================
Канальный уровень
================================
%% декодирование
L2-сообщения
% Подготовка к проверке CRC
[q r]=deconv(received_mes_L1,st.poly);
%проверка остатка
r=mod(abs(r),2);
if r ==
zeros(1,length(received_mes_L1))'
detect=0;% ошибок нет
else
errs = errs + 1;
detect=1;%
обнаружены ошибки
end;
% Собственно принятое
сообщение
received_mes_L2 = received_mes_L1(1:st.length_msg_Lev2);
% % Преобразование в текстовый формат
length_data =
my_bi2de(received_mes_L2(1:7)','left_msb' );
% Извлечение принимаемого
сообщения (в двоичном виде)
if length_data < 13
msgL3 =
received_mes_L2(8:16*length_data + 7)';
else
length_data = 12;
msgL3 =
received_mes_L2(8:16*length_data + 7)';
end
4) test_unit.m
close all; %закрытие
всех диаграмм
clear; %очистка
рабочей области
clc; % очистка
командного окна
% тестовый модуль обмена
двоичными сообщениями
%% установка параметров
системы
st = initSettings();
tx_msg = [];
% Открытие для чтения и
получение идентификатора текстового файла
fid = fopen(st.FileName, 'r');
%Проверка на доступность
указанного файла
if (fid < 0)
disp('Файл с передаваемым сообщением не
найден. Завершение работы.');
return
end;
tx_msg = fscanf(fid, '%c'); %Копирование
текста из файла в текстовую переменную tx_msg
fclose (fid); %Закрытие
файла
%% подготовка сообщения и
формирование соответствующих ему IQ-символов
bin_msg = strtobin(tx_msg)'; %перевод
текста в двоичный код (16 бит на символ)
length_tx_msg = length(tx_msg); %длина
текста в символах
disp(['Количество
символов текста: ', num2str(length_tx_msg)]);
disp(['Количество бит: ', num2str(length_tx_msg*16)]);
%Определение необходимого
количества пакетов для передачи
if mod(length_tx_msg*16,192) == 0
M =
floor((length_tx_msg*16)/192);
else
M = floor(((length_tx_msg*16)/192)+1);
end
disp(['Количество
пакетов: ', num2str(M)]);
disp('
');
disp(['$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']);
disp(' ');
%начало передачи пакетов
i = 1;
for n = 1:100 % число
возможных повторных передач
% формат L3-сообщения:
% 7 бит – длина сообщения
% следующие 192 бита -
информационная часть или служебное сообщение;
% если сообщение меньше 192
бит, то оно дополняется нулями
%передача по 192 бита
информации, если в последнем пакете меньше 192 бит,
%то передается число бит
равное длине последнего пакета
if length_tx_msg*16 > 192*i
bin_msg_i = bin_msg((1+192*(i-1)):192*i);
else
bin_msg_i =
bin_msg((1+192*(i-1)):length_tx_msg*16);
end
%disp(['Длина поля иформации: ', num2str(length(bin_msg_i))]);
DATA = [bin_msg_i zeros(1, 192 - length(bin_msg_i))];
%disp(['Длина поля DATA: ', num2str(length(DATA))]);
Length = my_de2bi(length(bin_msg_i)/16, 'left_msb',7); %длина текста в двоичной форме
msg_L3 = [Length DATA];
%disp(['Длина поля Сообщение_L3: ', num2str(length(msg_L3))]);
% формирование блока
IQ-символов
% этот блок можно будет
загружать в цифровой передатчик для последующей
% передачи сообщения по
радиоканалу
trxIQ = transmit(msg_L3);
%% Наложение шума на блок
символов
% Здесь менять мощность
шума!!!!!
noise_sgn = awgn(trxIQ,10,'measured');
% отображение результата в
виде сигнально-кодового созвездия
figure(1);
plot(noise_sgn,'.');
hold all;
%приемная часть. Извлечение
из сообщения необходимой информации
[Length_msgg, msg, err] = Receive_msg(noise_sgn);
%Идет проверка на ошибки
if my_bi2de(err) == 1
%если ошибки есть, то приемный
терминал формирует пакет с NAKом
%и отправляет его передатчику.
disp(['Имеются ошибки. Повтор передачи
пакета']);
nak_msg = ['NAK']';
bin_nak =
strtobin(nak_msg)';
Length_nak =
my_de2bi(length(bin_nak)/16, 'left_msb',7);
DATA_nak = [Length_nak bin_nak
zeros(1,144)];
nak_L3 = [DATA_nak];
IQ = transmit(nak_L3);
noise_ch = awgn(IQ,20,'measured');
else
%если ошибок нет, то отправляется
ACK
disp(['Ошибки отсутствуют']);
ack_msg = ['ACK']';
bin_ack =
strtobin(ack_msg)';
Length_ack =
my_de2bi(length(bin_ack)/16, 'left_msb',7);
DATA_ack = [Length_ack bin_ack
zeros(1,144)];
ack_L3 = [DATA_ack];
IQ = transmit(ack_L3);
noise_ch = awgn(IQ,20,'measured');
end
%Здесь передающий терминал
принимает сообщение приемного терминала
[Length_msgg_arq, msg_arq, err_arq] = Receive_msg(noise_ch);
txt_arq = bintostr(msg_arq)';
disp(['Текстовое
сообщение_arq: ' txt_arq']);
ARQ = (my_bi2de(msg_arq,'left_msb'))';
%если он получает NAK, то
переменная не изменяется и повторяется передача
%того же пакета
if ARQ == 335011709003
i = i+0;
%магическое чилсо. Так выглядит
слово NAK после перевода в двоичнный,
%а потом в десятичный вид
else
% если все хорошо и пришел
ACK, то приемник обрабатывает пришедшее сообщение...
disp(['Длина
(символов): ' num2str(Length_msgg)]);
txt_msg = bintostr(msg)';
disp(['Текстовое
сообщение: ' txt_msg']);
disp('
');
disp(['$$$$$$$$$']);
disp(' ');
%переменная, в которую
сохраняются сообщения из принятых пакетов
MSG_TEXT(1+12*(i-1):12*(i-1)+Length_msgg) = txt_msg;
%... и передатчик начинает
передавать следующий пакет
i = i+1;
end
% как только число принятых
пакетов превысило число переданных,
%то цикл прерывается
if i> M
break
end
end
%вывод всего сообщения на
экран
disp(['Принятое
сообщение: ' MSG_TEXT]);
%Подсчет количества ошибок
в сообщении
error = 0;
for j = 1:length_tx_msg
a =
(my_bi2de((strtobin(tx_msg(j))'),'left_msb'))';
b =
(my_bi2de((strtobin(MSG_TEXT(j))'),'left_msb'))';
if a-b == 0
error = error + 0;
else
error = error + 1;
end
end
MSG_TEXT = [];
disp(['Колличество
ошибок: ', num2str(error)]);
disp('
');
disp('
');
disp(['$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']);
disp(['$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']);
disp('
');
disp('
');
end
Для тестирования программы сначала выведем
длины всех полей, чтобы убедится в соответствии предложенной структуре пакета.
Для этого необходимо дописать в программе test_unit.m строки:
disp(['Структура сообщения L3-уровня:']);
disp(['Длина поля Length: ',
num2str(length(Length))]);
disp(['Длина поля DATA: ', num2str(length(DATA))]);
disp(['Длина сообщения L3-уровня: ', num2str(length(msg_L3))]);
disp([' ']);
И в программе transmit.m:
disp(['Длина поля Cообщение L3-уровня: ', num2str(length(msgL3))]);
disp(['Длина поля CRC-8: ', num2str(length(CRC))]);
disp(['Длина сообщения L2-уровня: ', num2str(length(msg_L2))]);
disp([' ']);
disp(['Структура сообщения L1-уровня:']);
disp(['Длина поля Cообщение L2-уровня: ', num2str(length(msg_L2))]);
disp(['Длина поля FEC: ', num2str(st.n-st.k)]);
disp(['Длина сообщения L1-уровня: ', num2str(length(code_word))]);
Тогда получим следующий результат:
Структура сообщения L3-уровня:
Длина поля Length: 7
Длина поля DATA: 192
Длина сообщения L3-уровня: 199
Структура сообщения L3-уровня:
Длина поля
Сообщение L3-уровня: 199
Длина поля CRC-8:
Длина cообщения L2-уровня: 207
Структура сообщения L1-уровня:
Длина поля
Сообщение L2-уровня: 207
Длина поля FEC: 48
Длина cообщения L1-уровня: 255
Рис.4. Длины полей
передаваемого пакета.
Если сравнить с рис.2, то видно, что структура полностью совпадает.
Теперь запустим систему и посмотрим на ее работу.
При этом передавался текстовый файл
SendText.txt .
Рис.5. Содержимое
используемого текстового файла.
Тогда результат
работы программы будет выглядеть следующим образом:
а)
б)
Рис.6. Передача
сообщения терминалу 1. а) заголовок и первый пакет, б) восстановленное
сообщение.
Также приведем сигнально-кодовые созвездия
при передаче сообщения и при ОСШ = 20 дБ.
Рис.7. Сигнально-кодовые
созвездия при передаче сообщения при ОСШ
= 20 дБ.
При уменьшении ОСШ шум увеличивается на
столько, что символы могут попасть в область принятия решений соседних
символов, и тогда возникают ошибки. И тогда вступает в действие механизм ARQ.
ОСШ = 10 дБ
Рис.8. Сигнально-кодовые
созвездия при передаче сообщения при ОСШ
= 10 дБ.
Выводы:
В ходе выполнения работы были решены
задачи, поставленные в задании –спроектирована система передачи сообщения,
использующая модуляцию 8-PSK, с помехоустойчивым кодом, исправляющим не менее 6 ошибок. В
проделанной самостоятельной работе был разработан сценарий передачи данных от
терминала 1 к терминалу 2 и наоборот, и часть его реализована программно.
Используемая
литература :
1 http://omoled.ru/publications/view/360
2http://omoled.ru/publications/view/380
3 http://limonwifi.com/signal8.html
4 http://omoled.ru/publications/view/335
5 Скляр Б. Цифровая
связь. Теоретические основы и практическое применение. М.: Вильямс, 2003г.