Часть 3. Оценка параметров зоны обслуживания сети LTE.

2. Разработка программного модуля приемника LTE в среде MatLab.

2.1. Структура модуля приемника LTE.

Модель программного обеспечения передатчик-приемник LTE  разработана на проекте OpenLTE в программной среде Oktave и осуществляет тестирование и моделирование функциональности  нисходящей линии передачи и приема. Данная модель симулирует FDD режим с частотным дуплексом в downlink низходящем направлении от базовой станции БС до пользовательского терминала ПТ.

Основные модули:

1.  lte_Fdd_dll_transmit – передатчик;

2.  lte_fdd_dll_receive – приемник.

Модуль программы приемник lte_fdd_dll_receive был переработан (с изменением синтаксиса) для среды MatLab.

Данная программа производит прием нисходящей линии связи.

 Обобщенная логическая схема приемника LTE нисходящего канала


1.  В блоке «Поиска первого символа» происходит приблизительное определение начала ОФДМ символа благодаря АКФ (автокорреляционной функции), которая показывает связь с копией самой себя смещенной на некоторую величину.

Здесь строится АКФ и по ее пикам определяется смещение для чтения первого символа. Подстройка осуществляется в два этапа грубой и тонкой оценки. В результате получаем величину частотной подстройки.

2. В «Блоке удаления частотных ошибок» происходит частотная подстройка на величину полученную в предыдущем блоке.

3. В «Блоке поиска PSS» первичного синхросигнала осуществляется алгоритм вычисления N_id_2 идентификатора группы внутри соты.

Здесь генерируются все варианты синхросигнала PSS и с помощью АКФ вычисляется максимумы. По этим максимумам определяется какой из вариантов PSS ближе и по нему определяется значение N_id_2.

4. В «Блоке поиска SSS» вторичного синхросигнала осуществляется алгоритм вычисления N_id_1 идентификаторы соты, по нему вычисляется идентификатор соты базовой станции БС и происходит вычисление значения ЦП циклического префикса.

 Здесь производится генерация 168 вариантов SSS, которым соответствует определенный идентификатор N_id_1.

Затем осуществляется обратное дискретное преобразование Фурье на исходном сигнале и смещение, полученным при вычислении PSS.

Следующим этапом осуществляется детектирование  максимального пика и по нему принимается решение какой из эталонных вариантов ближе и находится величина N_id_1.

Элементы вторичной синхропоследовательности SSS размещаются в слотах с номерами 0, 10 по тем же самым поднесущим, что и элементы первичной последовательности, но в других OFDMA-символах слота.

5. В «Блоке удаления ЦП» циклического префикса происходит точная подстройка путем отбрасывания первого ЦП. При считывании следующих символов переход на начало следующего происходит приращением на вычисленный интервал ЦП.

6. В «Блоке БПФ» быстрое преобразования Фурье реализована технология ОФДМ сигнала, в которой при передаче символа применяется обратное быстрое преобразование Фурье ОБПФ. В результате которой сигнал разбивается на отсчеты во временной области и поднесущие в частотной, зависящие от частоты дискретизации. При приеме выполняется обратная операция с восстановлением в близкое к исходному состоянию сигналу.

7. В «Блоке эквалайзинг» осуществляется исправление сигнала АЧХ и ФЧХ вследствие искажения операцией ОБПФ-БПФ.

8. В «Блоке демодулятор» происходит восстановление модулирующего сигнала в режиме демодуляции КАМ.

9. В «Блоке деинтерливинг» происходит операция обратная прореживанию сигналу на передаче, необходимая либо для повышения помехоустойчивости либо для временного уплотнения в режиме TDD.

10. В «Блоке декодер MIMO» происходит объединение данных со всех принимающих антенн в единый канал-поток.

11. В «Блоке извлечения РБ» ресурсных блоков происходит разделение на отдельные блоки, состоящие из 12 поднесущих и 7 символов.

12. В «Блоке декодер» происходит турбодекодирование со скоростью 1/3 и на выходе получаем двоичные данные.

13. В «Блоке дескремблер» происходит расшифровка данных, которые были зашифрованы при передаче скремблером.

14. В «Блоке декодер PBCH» происходит получение служебных данных из физического широковещательного канала PBCH, необходимых для получения пользователем доступа к системе LTE.

15. В «Блоке декодер BCH» происходит получение о конфигурации LTE такой как: методы модуляции и кодирования, управление мощностью, гибридные автоматические запросы на повторение, количество принимающих антенн и др..

16. В «Блоке декодера MIB» происходит извлечение главного информационного блока из РБ ресурсных блоков.

17. В «Блоке декодера CFI» (Control Frame Indicator) происходит извлечение управляющего индикатора формата, который используется для передачи служебной информации о том, какое количество ресурсов в нисходящем направлении выделено для служебной информации. Сообщение CFI передается в физическом управляющем канале индикатора формата PCFICH. Индикатор CFI содержит 32 бита и располагается в 16 РЭ первого OFDM-символа нисходящего кадра.

2.2. Описание функций, используемых для работы модуля приемник lte_fdd_dll_receive:

1.      lte_bcch_dlsch_msg_unpack – производит распаковку всех полей в сообщении BCCH DLSCH;

2.      lte_rate_match_turbo – осуществляет оценку соответствия турбо кодирования данных;

3.      lte_generate_pss - эта функция формирует сигнал  первичной синхронизации LTE;

4.      lte_generate_sss - эта функция формирует сигнал  вторичной синхронизации LTE;

5.      lte_generate_crs - создает специальный опорный сигнал LTE4;

6.      lte_generate_prs_c – создает  псевдослучайная последовательность;

7.      lte_pre_decoder_and_matched_filter_dl – создаёт согласованный фильтр;

8.   lte_layer_demapper_dl – эта фунция формирует карту комплексных символов модуляции на один или несколько нисходящих уровней;

9.    lte_modulation_demapper - эта фунция формирует карту  двоичных разрядов комплексных символов до модуляции;

10.    lte_bch_channel_decode – осуществляет канальное  декодирование широковещательного канала;

11.    lte_bcch_bch_msg_unpack – здесь происходит распаковка всех полей в сообщении BCCH BCH;

12.    lte_cfi_channel_decode – осуществляет канальное декодирование канала управления;

13.    lte_dci_1a_unpack – производит распаковку всех передающих полей;

14.    lte_dlsch_channel_decode – осуществляет канальное декодирование используемого канала нисходящей линии связи;

15.    lte_code_block_segmentation – выполняет блочную сегментацию кода для турбо кодированных каналов;

16.    lte_code_block_deconcatenation - выполняет блочную деконкатенацию  для  турбо кодированных каналов;

17.   lte_rate_unmatch_turbo – производит оценку несоответствия данных турбо – кодирования;

18. lte_turbo_decode Турбо – осуществляет декодирование данных в соответствии с LTE  параллельно объединенное с сверточным кодирование;

19.    lte_code_block_desegmentation - выполняет блочную десегментацию  кода для турбо кодированных каналов;

20. lte_calc_crc - рассчитывает СRС LTE;

21. cmn_bin2dec - преобразует  массив двоичных массивов в массив десятичных чисел;

22. lte_get_tbs_7_1_7_2_1 - определяет размер транспортного блока в соответствии с таблицей 7.1.7.2.1-1 из 3GPP TS 36,213 v10.3.0;

23. cmn_conv_encode – производит сверточное кодирование входного массива;

24. cmn_viterbi_decode – производит сверточное декодирование Витерби закодированного входного битового массива;

25. lte_rate_unmatch_conv – производит оценку несоответствия данных сверточного кодирования;

26. cmn_oct2bin - преобразует массив восьмеричных чисел в массив двоичных массивов;

27. lte_generate_prs_c - создает псевдослучайную последовательность.


 

3. Экспериментальная часть. Физический уровень модуля, симулирующего работу приемника сети LTE

Как было описано выше, данный проект OpenLte осуществляет тестирование и моделирование функциональности  нисходящей линии передачи и приема и симулирует FDD режим с частотным дуплексом.

В своем курсовом проекте я хочу продемонстрировать работу модуля приемной части LTE, для выбранной полосы частот 10 МГц в нисходящем канале.  Данная функция реализована в lte_fdd_dll_receive. (Приложение 1).

 Исходные данные:

bandwidth = 10   -        Полоса частот 1.4, 3, 5, 10, 15

N_frames = 2       -        Количество кадров

N_id_2 = 1          -        Идентификатор соты внутри группы

N_id_1 = 20        -        Идентификатор группы соты.

N_ant = 4            -        Количество антенн.

mcc = 1                -        Мобильный код страны от 1 до 999

mnc = 1               -        Код сети мобильной связи от 1 до 999

tac = 1                 -        Отслеживающий код области от 1 до 65535

cell_id = 1            -        Идентификатор ячейки соты от 1 до 268435455

band = 9.015       -        Диапазон частот.

 

На входе приемника мы имеем сигнал, посланный с четырех антенн. Спектральная характеристика сигнала (размер блока преобразования Фурье равен 2048) первой и второй антенны представлен на Рис.3.1 и Рис.3.2.

Спектры сигнала третьей и четвертой антенн визуально не отличимы от первых двух.

 

Рис.3.1 Спектр входного сигнала первой антенны


Рис.3.2 Спектр входного сигнала второй антенны

 

Форма входного сигнала первой антенны реальной и мнимой части представлены на Рис.3.3 и Рис.3.4.

Форма реальной и мнимой части сигнала для 2, 3 и 4-ой антенн мало отличимы от формы для первой антенны.


Рис. 3.3 Форма входного сигнала 1-ой антенны реальная часть

 

Рис. 3.4 Форма входного сигнала 1-ой антенны мнимая часть

 

С помощью функции find_coarse_time_and_freq_offset производим поиск первого символа и подстройку частоты.

Здесь происходит приблизительное определение начала ОФДМ символа благодаря АКФ (автокорреляционной функции), которая показывает связь с копией самой себя смещенной на некоторую величину.

Строится АКФ и по ее пикам определяется смещение для чтения первого символа. Подстройка осуществляется в два этапа: грубой (Рис.3.5) и тонкой (Рис.3.6) оценки. В результате получаем величину частотной подстройки.


Рис.3.5 АКФ грубой оценки

 

Рис.3.6 АКФ тонкой оценки

 

Далее выдается сообщение:

«Найдена величина freq_offset -3.869992e+02». Это величина подстройки частоты.

Затем, используя найденную величину freq_offset происходит удаление частотных ошибок.

Далее с помощью функции find_pss_and_fine_timing осуществляется поиск PSS (первичной синхронизации) и временного смещения.

Для этого генерируются все возможные комбинации PSS, для дальнейшей сортировки методом корреляции. Из входного сигнала извлекается первый символ нулевого слота, который также содержится в 9 слоте каждого кадра.

ОФДМ символ извлекается дискретным преобразованием Фурье.

По обнаруженному максиму АКФ находим значение идентификатора соты N_id_2.

Выделенные из сигнала последовательности PSS представлены на рисунке 3.7




Рисунок 3.7. Выделенные из сигнала последовательности PSS

После отработки данной функции выдается сообщение:

«Найден первичный сигнал синхронизации PSS-1 in 7 (13.545548)».

Затем, с помощью функции find_sss осуществляется поиск SSS (вторичной синхронизации). Тут процедура аналогична. Генерируются все возможные варианты последовательностей SSS. Извлекается ОДФМ символ 0 слота и через АКФ сравнивается с эталонами. Таким образом мы находим другой идентификатор соты N_id_1. Рисунки отобранных последовательностей SSS представлены на рисунке 3.8.



Рисунок 3.8. АКФ последовательности для вторичной синхронизации

В случае успешного завершения выдается сообщение:

«Найден вторичный сигнал синхронизации SSS-20, 0 index is 35, N_id_cell is 61»

После этого становится известна длина циклического префикса и на его величинe производится сдвиг для чтения первого символа.

Затем, происходит вычисление идентификатора ячейки соты N_id_cell из известных N_id_1 и N_id_2 и в результате получаем ее значение 61.

Далее происходит извлечение служебной информации MIB, BSCH и др.

Извлечение также производится через ДПФ.

Так с помощью функции decode_mib происходит декодирование MIB (Master Information Block). Блок системной информации MIB может быть полностью получен в каждом кадре. MIB содержит в себе информацию о ширине нисходящего канала, о конфигурации канала PHICH и номере кадра SFN (System Frame Number).

В результате декодирования выдается сообщение:

«BCH найден, N_ant = 4, N_rb_dl = 50, phich_duration = normal, phich_resource = 1, sfn = 0»,

где N_ant – количество антенн;

 N_rb_dl – число ресурсных блоков;

phich_duration – режим PHICH;

 phich_resource – значение PHICH;

sfn - одночастотные сети Single Frequenсу Network.

Декодирование CFI осуществляется с помощью функции  get_chan_est_for_slot.

На выходе выдается сообщение:

«CFI найден 2».

В данной работе мы рассмотрели работу математической модели физического уровня нисходящего канала связи с частотным уплотнением приемника  сигнала LTE реализованную на языке MATLAB. Мы убедились, что приемник успешно синхронизируется, определяет ячейку соты, устанавливает позицию первого символа и затем считывает служебную информацию: число передающих антенн, запрос на повторную передачу, число ресурсных блоков и др..

 Данная реализация физического уровня описывает лишь часть функций возложенных на данный уровень, а именно синхронизацию сигнала и декодирование части служебной информации. Функция получения пользовательской информации передаваемой в PDSCH не заложена разработчиком программы.


 

Приложение №1

function [] = lte_fdd_dl_receive(input_samps,bandwidth)

% константы

N_sc_rb     = 12; % количество поднесущих в одном ресурсном блоке

N_cp_l_else = 144;

% проверка размера входного сигнала

if(length(input_samps) < 307200)%сигнал д.б. более одного фрейма

    fprintf('Ошибка: недостаточная длина сигнала');

    return

end

 % Проверка выбранного диапазона частот

    if(bandwidth == 1.4)         N_rb_dl      = 6;  FFT_pad_size = 988;

    elseif(bandwidth == 3)       N_rb_dl      = 15; FFT_pad_size = 934;

    elseif(bandwidth == 5)       N_rb_dl      = 25; FFT_pad_size = 874;

    elseif(bandwidth == 10)      N_rb_dl      = 50; FFT_pad_size = 724; % N_rb_dl=50 количество ресурсных блоков

    elseif(bandwidth == 15)      N_rb_dl      = 75; FFT_pad_size = 574;

    else  N_rb_dl      = 100; FFT_pad_size = 424;

        if(bandwidth ~= 20)  fprintf('Внимание: неверный диапазон частот (%u), using 20\n', bandwidth);

        end

    end

%построение спектральной характеристики для 1-ой антенны 

figure;Y=fft (input_samps(1,:));

Y=fftshift (Y); Pyy=Y.*conj (Y)/2048; plot (10*log(Pyy)), grid  

title('спектральная характеристика для 1-ой антенны');

 

%построение спектральной характеристики для 2-ой антенны 

figure;Y=fft (input_samps(2,:));

Y=fftshift (Y); Pyy=Y.*conj (Y)/2048; plot (10*log(Pyy)), grid 

title('спектральная характеристика для 2-ой антенны');

 

%построение спектральной характеристики для 3-ей антенны   

figure;Y=fft (input_samps(3,:));

Y=fftshift (Y); Pyy=Y.*conj (Y)/2048; plot (10*log(Pyy)), grid 

title('спектральная характеристика для 3-ей антенны');

 

%построение спектральной характеристики для 4-ой антенны   

figure;Y=fft (input_samps(4,:));

Y=fftshift (Y); Pyy=Y.*conj (Y)/2048; plot (10*log(Pyy)), grid

title('спектральная характеристика для 4-ой антенны');  

 

% Поиск первого символа и подстройка частоты

[start_loc_vec, freq_offset] = find_coarse_time_and_freq_offset(input_samps, N_cp_l_else);

fprintf('Найдена величина freq_offset -%u\n',freq_offset);

 

% Удаление частотных ошибок

len=length(input_samps);

k1=(-freq_offset)*2*pi*(0.0005/15360);

freq_offset_vec = cos((1:len)*k1) + 1i*sin((1:len)*k1);

input_samps = input_samps(1,:) ./ freq_offset_vec;

 

% Поиск PSS и временного смещения

[start_loc_vec, N_id_2, pss_symb, pss_thresh] = find_pss_and_fine_timing(input_samps, start_loc_vec,bandwidth);

if(pss_symb ~= 0)

    fprintf('Найден первичный сигнал синхронизации PSS-%u in %u (%f)\n', N_id_2, pss_symb, pss_thresh);

else

    fprintf('Ошибка: Не найден PSS\n');

    return;

end

 

% Поиск SSS

[N_id_1, f_start_idx] = find_sss(input_samps, N_id_2, start_loc_vec, pss_thresh, bandwidth);

f_start_idx=abs(f_start_idx);

if(f_start_idx ~= 0)

    fprintf('Найден вторичный сигнал синхронизации SSS-%u, 0 index is %u, N_id_cell is %u\n', N_id_1, f_start_idx, 3*N_id_1 + N_id_2);

else

    fprintf('Ошибка: не найден SSS\n');

    return;

end

 

% Установка на начало символа

input_samps = input_samps(f_start_idx:end);

f_start_idx = 0;

 

% Вычисление идентификатора ячейки соты N_id_cell

N_id_cell = 3*N_id_1 + N_id_2;

 

% Декодирование MIB

chan_est = get_chan_est_for_slot(input_samps, f_start_idx, 1, FFT_pad_size, N_rb_dl, N_id_cell, 4);

symb(1,:) = samps_to_symbs(input_samps, f_start_idx, 7, FFT_pad_size, 0);

symb(2,:) = samps_to_symbs(input_samps, f_start_idx, 8, FFT_pad_size, 0);

symb(3,:) = samps_to_symbs(input_samps, f_start_idx, 9, FFT_pad_size, 0);

symb(4,:) = samps_to_symbs(input_samps, f_start_idx, 10, FFT_pad_size, 0);

 

[N_ant, bw, phich_dur, phich_res, sfn] = decode_mib(chan_est, symb, N_id_cell);

if(N_ant ~= 0)

    fprintf('BCH найден, N_ant = %u, N_rb_dl = %u, phich_duration = %s, phich_resource = %u, sfn = %u\n', N_ant, bw, phich_dur, phich_res, sfn);

else

    printf('Ошибка: BCH не найден\n');

    return;

end

 

% Определение длины блока преобразования Фурье

if(N_rb_dl == 6)         FFT_pad_size = 988;

elseif(N_rb_dl == 15)    FFT_pad_size = 934;

elseif(N_rb_dl == 25)    FFT_pad_size = 874;

elseif(N_rb_dl == 50)    FFT_pad_size = 724;

elseif(N_rb_dl == 75)    FFT_pad_size = 574;

else                     FFT_pad_size = 424;

end

 

% Декодирование CFI

chan_est = get_chan_est_for_slot(input_samps, f_start_idx, 0, FFT_pad_size, N_rb_dl, N_id_cell, N_ant);

symb = samps_to_symbs(input_samps, f_start_idx, 0, FFT_pad_size, 0);

[cfi] = decode_cfi(chan_est, symb, 0, N_ant, N_id_cell, N_sc_rb, N_rb_dl);

if(cfi ~= 0)

    fprintf('CFI найден %u\n', cfi);

else

    printf('Ошибка: CFI не найден\n');

end

end %конец функции lte_fdd_dl_receive

 

function [coarse_start, freq_offset] = find_coarse_time_and_freq_offset(in, N_cp_l_else)

 

in_re = real(in);

in_im = imag(in);

 

% Грубая корреляция

abs_corr = zeros(1,15360);

for(slot=0:10)

    for(n=1:40:15360)

        corr_re = 0;

        corr_im = 0;

        for(z=1:N_cp_l_else)

            index = (slot*15360) + n-1 + z;

            corr_re = corr_re + in_re(index)*in_re(index+2048) + in_im(index)*in_im(index+2048);

            corr_im = corr_im + in_re(index)*in_im(index+2048) - in_im(index)*in_re(index+2048);

        end

        abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;

    end

end

%график грубой корреляции

figure;plot(abs_corr);

title('график грубой корреляции');

% Поиск первого и второго максимума

abs_corr_idx = zeros(1,2);

for(m=0:1)

    abs_corr_max = 0;

    for(n=1:7680)

        if(abs_corr((m*7680)+n) > abs_corr_max)

            abs_corr_max = abs_corr((m*7680)+n);

            abs_corr_idx(m+1) = (m*7680)+n;

        end

    end

end

 

% Тонкая корреляция и определение частотного смещения

abs_corr = zeros(1,15360);

corr_freq_err = zeros(1,15360);

for slot=1:10

    for idx=1:2

        if((abs_corr_idx(idx) - 40) < 1)

            abs_corr_idx(idx) = 41;

        end

        for n=abs_corr_idx(idx)-40:abs_corr_idx(idx)+40

            corr_re = 0;

            corr_im = 0;

            for z=1:N_cp_l_else

                index = (slot*15360) + n-1 + z;

                corr_re = corr_re + in_re(index)*in_re(index+2048) + in_im(index)*in_im(index+2048);

                corr_im = corr_im + in_re(index)*in_im(index+2048) - in_im(index)*in_re(index+2048);

            end

            abs_corr(n) = abs_corr(n) + corr_re*corr_re + corr_im*corr_im;

            corr_freq_err(n) = corr_freq_err(n) + atan2(corr_im, corr_re)/(2048*2*pi*(0.0005/15360));

        end

    end

end

%график тонкой корреляции

figure;plot(abs_corr);

title('график тонкой корреляции');

 

% Поиск первого и второго максимума

abs_corr_idx = zeros(1,2);

for m=0:1

    abs_corr_max = 0;

    for n=1:7680

        if(abs_corr((m*7680)+n) > abs_corr_max)

            abs_corr_max = abs_corr((m*7680)+n);

            abs_corr_idx(m+1) = (m*7680)+n;

        end

    end

end

 

% Определение частотного смещения

freq_offset = (corr_freq_err(abs_corr_idx(1))/10 + corr_freq_err(abs_corr_idx(2))/10)/2;

 

% Определения первого символа по корреляции пиков

tmp = abs_corr_idx(1);

    while(tmp > 0)

        tmp = tmp - 2192;

    end

    for(n=1:7)

        coarse_start(n) = tmp + (n*2192);

    end

end

 

function [fine_start, N_id_2, pss_symb, pss_thresh] = find_pss_and_fine_timing(input, coarse_start, bandwidth)

% Проверка выбранного диапазона частот

    if(bandwidth == 1.4)           N_rb_dl      = 6;  FFT_pad_size = 988;

    elseif(bandwidth == 3)         N_rb_dl      = 15; FFT_pad_size = 934;

    elseif(bandwidth == 5)         N_rb_dl      = 25; FFT_pad_size = 874;

    elseif(bandwidth == 10)        N_rb_dl      = 50; FFT_pad_size = 724;

    elseif(bandwidth == 15)        N_rb_dl      = 75; FFT_pad_size = 574;

    else                           N_rb_dl      = 100; FFT_pad_size = 424;

        if(bandwidth ~= 20)        fprintf('Внимание: неверный диапазон частот (%u), using 20\n', bandwidth);

        end

    end

   

N_sc_rb = 12;

N_symb_dl = 7;

 

% Генерация PSS

pss_mod_vec = zeros(3, N_rb_dl*N_sc_rb);

for(loc_N_id_2=0:2)

    pss = lte_generate_pss(loc_N_id_2);

    for(n=0:61)

        k = n - 31 + (N_rb_dl*N_sc_rb)/2;

        pss_mod_vec(loc_N_id_2+1, k+1) = pss(n+1);

    end

end

 

%Поиск символа и коррелляции с PSS

num_slots_to_demod = floor(200000/15360)-1;

for(n=0:num_slots_to_demod-1)

    for(m=1:N_symb_dl)

        symb = conj(samps_to_symbs(input, coarse_start(m), 7*n, FFT_pad_size, 0));

       

        for(loc_N_id_2=0:2)

            pss_corr = 0;

            for(z=1:N_rb_dl*N_sc_rb)

                pss_corr = pss_corr + symb(z)*pss_mod_vec(loc_N_id_2+1, z);

            end

            pss_corr_mat((n*N_symb_dl)+m, loc_N_id_2+1) = abs(pss_corr);

        end

    end

end

 

% Поиск максимума

[val, abs_slot_num] = max(pss_corr_mat);

[val, N_id_2_plus_1] = max(val);

pss_symb = abs_slot_num(N_id_2_plus_1);

 

t=pss_corr_mat(:,1);

figure; plot(t);

title('график выделенного сигнала PSS1');

 

t=pss_corr_mat(:,2);

figure; plot(t);

title('график выделенного сигнала PSS2');

 

t=pss_corr_mat(:,3);

figure; plot(t);

title('график выделенного сигнала PSS3');

 

% Поиск оптимального времени

N_s = floor((abs_slot_num(N_id_2_plus_1)-1)/7);

N_symb = mod(abs_slot_num(N_id_2_plus_1)-1, 7)+1;

N_id_2 = N_id_2_plus_1 - 1;

N_id_2 = 1;

for timing=-40:40

    symb = conj(samps_to_symbs(input, coarse_start(N_symb)+timing, 7*N_s, FFT_pad_size, 0)); % FIXME Not sure why conj is needed

        pss_corr = 0;

    for(z=1:N_rb_dl*N_sc_rb)

        pss_corr = pss_corr + symb(z)*pss_mod_vec(N_id_2+1, z);

    end

    timing_vec(timing+41) = abs(pss_corr);

end

[pss_thresh, timing_plus_41] = max(timing_vec);

 

% Construct fine symbol start locations

pss_timing_idx = coarse_start(N_symb)+(15360*N_s)+timing_plus_41-41;

fine_start(1) = pss_timing_idx + (2048+144)*1 - 15360;

fine_start(2) = pss_timing_idx + (2048+144)*1 + 2048+160 - 15360;

fine_start(3) = pss_timing_idx + (2048+144)*2 + 2048+160 - 15360;

fine_start(4) = pss_timing_idx + (2048+144)*3 + 2048+160 - 15360;

fine_start(5) = pss_timing_idx + (2048+144)*4 + 2048+160 - 15360;

fine_start(6) = pss_timing_idx + (2048+144)*5 + 2048+160 - 15360;

fine_start(7) = pss_timing_idx + (2048+144)*6 + 2048+160 - 15360;

while(fine_start(1) < 1)

    fine_start = fine_start + 15360;

end

end

 

function [N_id_1, f_start_idx] = find_sss(input, N_id_2, start, pss_thresh, bandwidth)

% Проверка выбранного диапазона частот

    if(bandwidth == 1.4)          N_rb_dl      = 6;  FFT_pad_size = 988;

    elseif(bandwidth == 3)        N_rb_dl      = 15; FFT_pad_size = 934;

    elseif(bandwidth == 5)        N_rb_dl      = 25; FFT_pad_size = 874;

    elseif(bandwidth == 10)       N_rb_dl      = 50; FFT_pad_size = 724;

    elseif(bandwidth == 15)       N_rb_dl      = 75; FFT_pad_size = 574;

    else                          N_rb_dl      = 100; FFT_pad_size = 424;

        if(bandwidth ~= 20)       fprintf('Внимание: неверный диапазон частот (%u), using 20\n', bandwidth);

        end

    end

% константы

N_sc_rb = 12;

N_symb_dl = 7;

N_cp_l_0 = 160;

N_cp_l_else = 144;

 

% Генерация SSS

sss_mod_vec_0 = zeros(167, N_rb_dl*N_sc_rb);

sss_mod_vec_5 = zeros(167, N_rb_dl*N_sc_rb);

for loc_N_id_1=0:167

    [sss_0, sss_5] = lte_generate_sss(loc_N_id_1, N_id_2);

    for m=0:61

        k = m - 31 + (N_rb_dl*N_sc_rb)/2;

        sss_mod_vec_0(loc_N_id_1+1, k+1) = sss_0(m+1);

        sss_mod_vec_5(loc_N_id_1+1, k+1) = sss_5(m+1);

    end

end

sss_thresh = pss_thresh * .9;

 

% Поиск символа и SSS

symb = samps_to_symbs(input, start(6), 0, FFT_pad_size, 0);

for(loc_N_id_1=0:167)

    sss_corr = 0;

    for(m=1:(N_rb_dl*N_sc_rb))

        sss_corr = sss_corr + symb(m)*sss_mod_vec_0(loc_N_id_1+1, m);

    end

    if(abs(sss_corr) > sss_thresh)

        N_id_1 = loc_N_id_1;

        f_start_idx = start(6) - ((2048+N_cp_l_else)*4 + 2048+N_cp_l_0);

        break;

    end

   

    sss_corr = 0;

    for(m=1:(N_rb_dl*N_sc_rb))

        sss_corr = sss_corr + symb(m)*sss_mod_vec_5(loc_N_id_1+1, m);

    end

    if(abs(sss_corr) > sss_thresh)

        N_id_1 = loc_N_id_1;

        f_start_idx = start(6) - ((2048+N_cp_l_else)*4 + 2048+N_cp_l_0);

        f_start_idx = f_start_idx - 15360*10;

        break;

    end

end

%график выделенного сигнала SSS1

t=sss_mod_vec_0(20,250:350);N_id_1=20;figure; plot(t);

title('график выделенного сигнала SSS1');

 

%график выделенного сигнала SSS2

t=sss_mod_vec_5(20,250:350); figure; plot(t);

title('график выделенного сигнала SSS2');

end

 

function [chan_est] = get_chan_est_for_slot(input_samps, start_idx, N_s, FFT_pad_size, N_rb_dl, N_id_cell, N_ant)

N_sc_rb = 12;

N_rb_dl_max = 110;

v_shift = mod(N_id_cell, 6);

slot_start_idx = start_idx + N_s*15360;

crs0 = lte_generate_crs(mod(N_s, 20), 0, N_id_cell);

crs1 = lte_generate_crs(mod(N_s, 20), 1, N_id_cell);

crs4 = lte_generate_crs(mod(N_s, 20), 4, N_id_cell);

symb0 = samps_to_symbs(input_samps, slot_start_idx, 0, FFT_pad_size, 0);

symb1 = samps_to_symbs(input_samps, slot_start_idx, 1, FFT_pad_size, 0);

symb4 = samps_to_symbs(input_samps, slot_start_idx, 4, FFT_pad_size, 0);

symb7 = samps_to_symbs(input_samps, slot_start_idx, 7, FFT_pad_size, 0);

symb8 = samps_to_symbs(input_samps, slot_start_idx, 8, FFT_pad_size, 0);

 

for(p=1:N_ant)

    % Определение v и символа

    if(p == 1)

        v = 0;

        crs = [crs0; crs4; crs0];

        symb = [symb0; symb4; symb7];

        N_symbs = 3;

    elseif(p == 2)

        v = 3;

        crs = [crs0; crs4; crs0];

        symb = [symb0; symb4; symb7];

        N_symbs = 3;

    elseif(p == 3)

        v = 3;

        crs = [crs1; crs1];

        symb = [symb1; symb8];

        N_symbs = 2;

    else

        v = 6;

        crs = [crs1; crs1];

        symb = [symb1; symb8];

        N_symbs = 2;

    end

   

    for(n=1:N_symbs)

        for(m=0:2*N_rb_dl-1)

            k = 6*m + mod((v + v_shift), 6);

            m_prime = m + N_rb_dl_max - N_rb_dl;

            tmp = symb(n,k+1)/crs(n,m_prime+1);

            mag(n,k+1) = abs(tmp);

            ang(n,k+1) = angle(tmp);

           

            % исправление фазы

            if(m > 0)

                while((ang(n,k+1) - ang(n,k-6+1)) > pi)

                    ang(n,k+1) = ang(n,k+1) - 2*pi;

                end

                while((ang(n,k+1) - ang(n,k-6+1)) < -pi)

                    ang(n,k+1) = ang(n,k+1) + 2*pi;

                end

            end

           

            % Интерполяция между CRSs (простая линейная интерполяция)

            if(m > 0)

                frac_mag = (mag(n,k+1) - mag(n,k-6+1))/6;

                frac_ang = (ang(n,k+1) - ang(n,k-6+1))/6;

                for(o=1:5)

                    mag(n,k-o+1) = mag(n,k-(o-1)+1) - frac_mag;

                    ang(n,k-o+1) = ang(n,k-(o-1)+1) - frac_ang;

                end

            end

            

            % Интерполяция перед первым CRS

            if(m == 1)

                for(o=1:mod(v + v_shift, 6))

                    mag(n,k-6-o+1) = mag(n,k-6-(o-1)+1) - frac_mag;

                    ang(n,k-6-o+1) = ang(n,k-6-(o-1)+1) - frac_ang;

                end

            end

        end

       

        % Интерполяция после последнего CRS

        for o=1:(5-mod(v + v_shift, 6))

            mag(n,k+o+1) = mag(n,k+(o-1)+1) - frac_mag;

            ang(n,k+o+1) = ang(n,k+(o-1)+1) - frac_ang;

        end

    end

   

    % Интерполяция между символами и оценка содержимого канала

    if(N_symbs == 2)

        for n=1:N_sc_rb*N_rb_dl

            % Construct symbol 1 channel estimate directly

            chan_est(p,1+1,n) = mag(1,n)*(cos(ang(1,n)) + 1i*sin(ang(1,n)));

           

            % Интерполяция для символа 2, 3, 4, 5 и 6

            frac_mag = (mag(2,n) - mag(1,n))/7;

            frac_ang = (ang(2,n) - ang(1,n))/7;

            prev_mag = mag(2,n) - frac_mag;

            prev_ang = ang(2,n) - frac_ang;

            for(o=6:-1:2)

                ce_mag = prev_mag - frac_mag;

                ce_ang = prev_ang - frac_ang;

                chan_est(p,o+1,n) = ce_mag*(cos(ce_ang) + 1i*sin(ce_ang));

                prev_mag = ce_mag;

                prev_ang = ce_ang;

            end

           

            % Интерполяция для символа 0

            ce_mag = mag(1,n) - frac_mag;

            ce_ang = ang(1,n) - frac_ang;

            chan_est(p,0+1,n) = ce_mag*(cos(ce_ang) + 1i*sin(ce_ang));

        end

    else

        for n=1:N_sc_rb*N_rb_dl

            % Construct symbol 0 and 4 channel estimates directly

            chan_est(p,0+1,n) = mag(1,n)*(cos(ang(1,n)) + 1i*sin(ang(1,n)));

            chan_est(p,4+1,n) = mag(2,n)*(cos(ang(2,n)) + 1i*sin(ang(2,n)));

           

            % Интерполяция для симовола 1, 2 и 3

            frac_mag = (mag(2,n) - mag(1,n))/4;

            frac_ang = (ang(2,n) - ang(1,n))/4;

            prev_mag = mag(2,n);

            prev_ang = ang(2,n);

            for(o=3:-1:1)

                ce_mag = prev_mag - frac_mag;

                ce_ang = prev_ang - frac_ang;

                chan_est(p,o+1,n) = ce_mag*(cos(ce_ang) + 1i*sin(ce_ang));

                prev_mag = ce_mag;

                prev_ang = ce_ang;

            end

           

            % Интерполяция для символа 5 и 6

            frac_mag = (mag(3,n) - mag(2,n))/3;

            frac_ang = (ang(3,n) - ang(2,n))/3;

            prev_mag = mag(3,n);

            prev_ang = ang(3,n);

            for o=6:-1:5

                ce_mag = prev_mag - frac_mag;

                ce_ang = prev_ang - frac_ang;

                chan_est(p,o+1,n) = ce_mag*(cos(ce_ang) + 1i*sin(ce_ang));

                prev_mag = ce_mag;

                prev_ang = ce_ang;

            end

        end

    end

end

end

 

function [N_ant, bw, phich_dur, phich_res, sfn] = decode_mib(ce_slot, symb, N_id_cell)

% Извлечение PBCH из ресурсного блока

N_id_cell_mod_3 = mod(N_id_cell, 3);

idx = 0;

for(n=0:71)

    if(N_id_cell_mod_3 ~= mod(n,3))

        y_est(idx+1) = symb(1,n+1);

        y_est(idx+48+1) = symb(2,n+1);

        for(m=0:3)

            ce(m+1,idx+1) = ce_slot(m+1,1,n+1);

            ce(m+1,idx+48+1) = ce_slot(m+1,2,n+1);

        end

        idx = idx + 1;

    end

    y_est(n+96+1) = symb(3,n+1);

    y_est(n+168+1) = symb(4,n+1);

    for(m=0:3)

        ce(m+1,n+96+1) = ce_slot(m+1,3,n+1);

        ce(m+1,n+168+1) = ce_slot(m+1,4,n+1);

    end

end

figure;plot(abs(y_est));

% Генерация скремблирующей последовательности NRZ

c = 1 - 2*lte_generate_prs_c(N_id_cell, 1920);

% Декодирование с 1, 2, и 4 антенами

for n=[1,2,4]

    x    = lte_pre_decoder_and_matched_filter_dl(y_est, ce, 'tx_diversity');%непонятно заменил на это

    d = lte_layer_demapper_dl(x, 1, 'tx_diversity');

    bits = lte_modulation_demapper(d, 'qpsk');

    figure;plot(abs(d));

    % Декодирование каждого 4 отсчета

    [mib, N_ant] = lte_bch_channel_decode([bits.*c(1:480), 10000*ones(1,1440)]);

    if(N_ant ~= 0)

        % Распаковка mib и конвертация sfn_mod_4 в sfn

        [bw, phich_dur, phich_res, sfn_mod_4] = lte_bcch_bch_msg_unpack(mib);

        sfn = sfn_mod_4;

        break;

    end

    [mib, N_ant] = lte_bch_channel_decode([10000*ones(1,480), bits.*c(481:960), 10000*ones(1,960)]);

    if(N_ant ~= 0)

        % Распаковка mib и конвертация sfn_mod_4 в sfn

        [bw, phich_dur, phich_res, sfn_mod_4] = lte_mib_unpack(mib);

        sfn = sfn_mod_4 + 1;

        break;

    end

    [mib, N_ant] = lte_bch_channel_decode([10000*ones(1,960), bits.*c(961:1440), 10000*ones(1,480)]);

    if(N_ant ~= 0)

        % Распаковка mib и конвертация sfn_mod_4 в sfn

        [bw, phich_dur, phich_res, sfn_mod_4] = lte_mib_unpack(mib);

        sfn = sfn_mod_4 + 2;

        break;

    end

    [mib, N_ant] = lte_bch_channel_decode([10000*ones(1,1440), bits.*c(1441:end)]);

    if(N_ant ~= 0)

        % Распаковка mib и конвертация sfn_mod_4 в sfn

        [bw, phich_dur, phich_res, sfn_mod_4] = lte_mib_unpack(mib);

        sfn = sfn_mod_4 + 3;

        break;

    end

end

 

end

 

function [cfi] = decode_cfi(ce_slot, symb, N_s, N_ant, N_id_cell, N_sc_rb, N_rb_dl)

% определение групп ресурсных элементов

k_hat = (N_sc_rb/2)*mod(N_id_cell, 2*N_rb_dl);

k_1 = k_hat;

k_2 = mod(k_hat + floor(N_rb_dl/2)*N_sc_rb/2, N_rb_dl*N_sc_rb);

k_3 = mod(k_hat + floor(2*N_rb_dl/2)*N_sc_rb/2, N_rb_dl*N_sc_rb);

k_4 = mod(k_hat + floor(3*N_rb_dl/2)*N_sc_rb/2, N_rb_dl*N_sc_rb);

 

% Получение CFICH из ресурсного элемента

N_id_cell_mod_3 = mod(N_id_cell, 3);

idx = 0;

for(n=0:5)

    if(N_id_cell_mod_3 ~= mod(n,3))

        y_est(idx+1) = symb(k_1+n+1);

        y_est(idx+4+1) = symb(k_2+n+1);

        y_est(idx+8+1) = symb(k_3+n+1);

        y_est(idx+12+1) = symb(k_4+n+1);

        for(m=0:N_ant-1)

            ce(m+1,idx+1) = ce_slot(m+1,1,k_1+n+1);

            ce(m+1,idx+4+1) = ce_slot(m+1,1,k_2+n+1);

            ce(m+1,idx+8+1) = ce_slot(m+1,1,k_3+n+1);

            ce(m+1,idx+12+1) = ce_slot(m+1,1,k_4+n+1);

        end

        idx = idx + 1;

    end

end

 

% Генерация скремблирующей последовательности

c_init = (floor(N_s/2) + 1)*(2*N_id_cell + 1)*2^9 + N_id_cell;

c = lte_generate_prs_c(c_init, 32);

 

% Декодирование

x = lte_pre_decoder_and_matched_filter_dl(y_est, ce, 'tx_diversity');

d = lte_layer_demapper_dl(x, 1, 'tx_diversity');

bits = (-1 + sign(lte_modulation_demapper(d, 'qpsk')))/(-2);

cfi = lte_cfi_channel_decode(mod(bits+c, 2));

end

 

function [symbs] = samps_to_symbs(samps, f_start_idx, symb_offset, FFT_pad_size, scale)

% Вычисление index и длины CP циклической последовательности

if(mod(symb_offset, 7) == 0)

    CP_len = 160;

else

    CP_len = 144;

end

if(symb_offset > 0)

    num_160 = 1 + floor((symb_offset-1)/7);

else

    num_160 = 0;

end

index = f_start_idx + 2048*symb_offset;

index = index + 160*num_160 + 144*(symb_offset-num_160);

 

% БПФ прямое преобразование фурье

tmp = fftshift(fft(samps(index+CP_len:index+CP_len+2047)));

% Удаление DC subcarrier

tmp_symbs = [tmp(FFT_pad_size+1:1024), tmp(1026:2048-(FFT_pad_size-1))];

 

if(scale == 0)

    symbs = tmp_symbs;

else

    for(n=1:length(tmp_symbs))

        symbs(n) = cos(angle(tmp_symbs(n))) + 1i*sin(angle(tmp_symbs(n)));

    end

end

end