comm.LinearEqualizer

Компенсируйте модулируемые сигналы с помощью линейной фильтрации

Описание

comm.LinearEqualizer Система object™ использует линию задержки касания линейного фильтра со взвешенной суммой, чтобы компенсировать модулируемые сигналы, переданные через дисперсионный канал. Объект эквалайзера адаптивно настраивает веса касания на основе выбранного алгоритма. Для получения дополнительной информации см. Алгоритмы.

Компенсировать модулируемые сигналы с помощью линейного фильтра:

  1. Создайте comm.LinearEqualizer объект и набор его свойства.

  2. Вызовите объект с аргументами, как будто это была функция.

Чтобы узнать больше, как Системные объекты работают, смотрите то, Что Системные объекты?

Создание

Описание

пример

lineq = comm.LinearEqualizer создает линейный Системный объект эквалайзера, чтобы адаптивно компенсировать сигнал.

пример

lineq = comm.LinearEqualizer(Name,Value) свойства наборов с помощью одной или нескольких пар "имя-значение". Например, comm.LinearEqualizer('Algorithm','RLS') конфигурирует объект эквалайзера обновить веса касания с помощью алгоритма рекурсивных наименьших квадратов (RLS). Заключите каждое имя свойства в кавычки.

Свойства

развернуть все

Если в противном случае не обозначено, свойства являются ненастраиваемыми, что означает, что вы не можете изменить их значения после вызова объекта. Объекты блокируют, когда вы вызываете их, и release функция разблокировала их.

Если свойство является настраиваемым, можно изменить его значение в любое время.

Для получения дополнительной информации об изменении значений свойств смотрите Разработку системы в MATLAB Используя Системные объекты.

Адаптивный алгоритм использовал для эквализации в виде одного из этих значений:

Типы данных: char | string

Количество эквалайзера касается в виде положительного целого числа. Количество касаний эквалайзера должно быть больше или быть равно значению InputSamplesPerSymbol свойство.

Типы данных: double

Размер шага используется адаптивным алгоритмом в виде положительной скалярной величины. Увеличение размера шага уменьшает время сходимости эквалайзера, но заставляет эквалайзер выходные оценки быть менее устойчивым.

Совет

Чтобы определить максимальный позволенный размер шага, используйте maxstep объектная функция.

Настраиваемый: да

Зависимости

Чтобы включить это свойство, установите Алгоритм на 'LMS' или 'CMA'.

Типы данных: double

Упущение фактора, используемого адаптивным алгоритмом в виде скаляра в области значений (0, 1]. Уменьшение фактора упущения уменьшает время сходимости эквалайзера, но заставляет эквалайзер выходные оценки быть менее устойчивым.

Настраиваемый: да

Зависимости

Чтобы включить это свойство, установите Алгоритм на 'RLS'.

Типы данных: double

Начальная матрица обратной корреляции в виде скаляра или N Taps-by-NTaps матрица. Касания N равны значению свойства NumTaps. Если вы задаете InitialInverseCorrelationMatrix как скаляр, a, эквалайзер устанавливает начальную матрицу обратной корреляции на времена a единичная матрица: a (eye(Касания N)).

Зависимости

Чтобы включить это свойство, установите Алгоритм на 'RLS'.

Типы данных: double

Сигнальное созвездие в виде вектора. Значением по умолчанию является сгенерированное использование созвездия QPSK этого кода: pskmod(0:3,4,pi/4).

Типы данных: double

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

Типы данных: double

Задержка входного сигнала выборок относительно времени сброса эквалайзера в виде неотрицательного целого числа. Если входной сигнал является вектором из длины, больше, чем 1, то входная задержка относительно запуска входного вектора. Если входной сигнал является скаляром, то входная задержка относительно первого вызова Системного объекта и к первому вызову Системного объекта после вызова release или reset объектная функция.

Типы данных: double

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

Типы данных: double

Включите учебный вход управления в виде логического 0 ложь) или 1 TRUE). Установка этого свойства к true включает входной tf флага обучения эквалайзера.

Типы данных: логический

Обновите веса касания если не обучение в виде логического 1 TRUE) или 0 ложь). Если это свойство установлено в true, Системный объект использует направленный режим решения, чтобы обновить веса касания эквалайзера. Если это свойство установлено в false, Системный объект сохраняет веса касания эквалайзера неизменными после обучения.

Типы данных: логический

Источник адаптирует запрос весов касания в виде одного из этих значений:

  • 'Property' — Задайте это значение, чтобы использовать свойство AdaptWeights управлять, когда Системный объект адаптирует веса касания.

  • 'Input port' — Задайте это значение, чтобы использовать aw введите, чтобы управлять, когда Системный объект адаптирует веса касания.

Зависимости

Чтобы включить это свойство, установите Алгоритм на 'CMA'.

Типы данных: char | string

Адаптируйте веса касания в виде логического 1 TRUE) или 0 ложь). Если это свойство установлено в true, Системный объект обновляет веса касания эквалайзера. Если это свойство установлено в false, Системный объект сохраняет веса касания эквалайзера неизменными.

Зависимости

Чтобы включить это свойство, установите AdaptWeightsSource на 'Property' и набор AdaptAfterTraining к true.

Типы данных: логический

Источник для начальных весов касания в виде

  • 'Auto' — Инициализируйте веса касания к специфичным для алгоритма значениям по умолчанию, как описано в свойстве InitialWeights.

  • 'Property' — Инициализируйте веса касания с помощью значения свойства InitialWeights.

Типы данных: char | string

Начальные веса касания, используемые адаптивным алгоритмом в виде скаляра или вектора. Значением по умолчанию является 0 когда свойство Algorithm установлено в 'LMS' или 'RLS'. Значением по умолчанию является [0;0;1;0;0] когда свойство Algorithm установлено в 'CMA'.

Если вы задаете InitialWeights как вектор, длина вектора должна быть равна значению свойства NumTaps. Если вы задаете InitialWeights как скаляр, эквалайзер использует скалярное расширение, чтобы создать вектор из длины NumTaps со всем набором значений к InitialWeights.

Зависимости

Чтобы включить это свойство, установите InitialWeightsSource на 'Property'.

Типы данных: double

Коснитесь периода обновления веса в символах в виде положительного целого числа. Эквалайзер обновляет веса касания после обработки этого количества символов.

Типы данных: double

Использование

Описание

пример

y = lineq(x,tsym) компенсирует входной сигнал x при помощи учебных символов tsym. Выход является компенсируемыми символами. Чтобы включить этот синтаксис, установите свойство Algorithm на 'LMS' или 'RLS'.

пример

y = lineq(x,tsym,tf) также задает учебный флаг tf. Системный объект запускает обучение когда tf изменения от false к true (в возрастающем ребре). Системный объект обучается до всех символов в tsym обрабатываются. Вход tsym проигнорирован когда tf false. Чтобы включить этот синтаксис, установите свойство Algorithm на 'LMS' или 'RLS' и свойство TrainingFlagInputPort к true.

пример

y = lineq(x) компенсирует входной сигнал x. Чтобы включить этот синтаксис, установите свойство Algorithm на 'CMA'.

пример

y = lineq(x,aw) также задает, адаптирует флаг aw весов. Если aw true, Системный объект адаптирует веса касания эквалайзера. Если aw false, Системный объект сохраняет веса неизменными. Чтобы включить этот синтаксис, установите свойство Algorithm на 'CMA' и свойство AdaptWeightsSource к 'Input port'.

пример

[y,err] = lineq(___) также возвращает сигнал ошибки err использование входных параметров от любого из предыдущих синтаксисов.

пример

[y,err,weights] = lineq(___) также возвращает weights, веса касания от последнего обновления веса касания, с помощью входных параметров от любого из предыдущих синтаксисов.

Входные параметры

развернуть все

Входной сигнал в виде вектор-столбца. Длина вектора входного сигнала должна быть равна целочисленному кратному значение свойства InputSamplesPerSymbol. Для получения дополнительной информации смотрите, что Касание Символа Располагает с интервалами.

Типы данных: double
Поддержка комплексного числа: Да

Учебные символы в виде вектор-столбца длины, меньше чем или равной длине входа x. Вход tsym проигнорирован когда tf false.

Зависимости

Чтобы включить этот аргумент, установите свойство Algorithm на 'LMS' или 'RLS'.

Типы данных: double
Поддержка комплексного числа: Да

Учебный флаг в виде логического 1 TRUE) или 0 ложь). Системный объект запускает обучение когда tf изменения от false к true (в возрастающем ребре). Системный объект обучается до всех символов в tsym обрабатываются. Вход tsym проигнорирован когда tf false.

Зависимости

Чтобы включить этот аргумент, установите свойство Algorithm на 'LMS' или 'RLS' и свойство TrainingFlagInputPort к true.

Типы данных: логический

Адаптируйте флаг весов в виде логического 1 TRUE) или 0 ложь). Если aw true, Системный объект адаптирует веса. Если aw false, Системный объект сохраняет веса неизменными.

Зависимости

Чтобы включить этот аргумент, установите свойство Algorithm на 'CMA' и свойство AdaptWeightsSource к 'Input port'.

Типы данных: логический

Выходные аргументы

развернуть все

Компенсируемые символы, возвращенные как вектор-столбец, который имеет ту же длину как входной сигнал x.

Сигнал ошибки, возвращенный как вектор-столбец, который имеет ту же длину как входной сигнал x.

Коснитесь весов, возвращенных как вектор-столбец, который имеет элементы NumTaps. weights содержит веса касания от последнего обновления веса касания.

Функции объекта

Чтобы использовать объектную функцию, задайте Системный объект как первый входной параметр. Например, чтобы выпустить системные ресурсы Системного объекта под названием obj, используйте этот синтаксис:

release(obj)

развернуть все

isLockedОпределите, используется ли Системный объект
cloneСоздайте объект дублированной системы
infoХарактеристическая информация об объекте эквалайзера
maxstepМаксимальный размер шага для сходимости эквалайзера LMS
mmseweightsЛинейный эквалайзер MMSE касается весов
stepЗапустите алгоритм Системного объекта
releaseВысвободите средства и позвольте изменения в значениях свойств Системного объекта и введите характеристики
resetСбросьте внутренние состояния Системного объекта

Примеры

свернуть все

Создайте модулятор BPSK и Систему эквалайзера object™, задав линейный эквалайзер LMS, имеющий восемь касаний и размер шага 0,03.

bpsk = comm.BPSKModulator;
eqlms = comm.LinearEqualizer( ...
    'Algorithm','LMS', ...
    'NumTaps',8, ...
    'StepSize',0.03);

Измените ссылочный индекс касания эквалайзера.

eqlms.ReferenceTap = 4;

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

x = bpsk(randi([0 1],1000,1));
rxsig = conv(x,[1 0.8 0.3]);

Используйте maxstep найти максимальный разрешенный размер шага.

mxStep = maxstep(eqlms,rxsig)
mxStep = 0.1384

Компенсируйте полученный сигнал. Используйте первые 200 символов в качестве обучающей последовательности.

y = eqlms(rxsig,x(1:200));

Примените линейную эквализацию с помощью алгоритма наименьшее количество средних квадратичных (LMS), чтобы восстановиться, символы QPSK прошли через многопутевой канал AWGN.

Инициализируйте переменные симуляции.

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
chtaps = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];

Сгенерируйте модулируемые QPSK символы. Примените многопутевую фильтрацию канала и ухудшения AWGN к символам.

data = randi([0 M-1],numSymbols,1);
tx = pskmod(data,M,pi/4);
rx = awgn(filter(chtaps,1,tx),25,'measured');

Создайте линейный Системный объект эквалайзера и отобразите настройку по умолчанию. Настройте ссылочное касание к 1. Проверяйте максимальный разрешенный размер шага. Компенсируйте символы, которым повреждают.

eq = comm.LinearEqualizer
eq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [0.7071 + 0.7071i -0.7071 + 0.7071i ... ]
             ReferenceTap: 3
               InputDelay: 0
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: true
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

eq.ReferenceTap = 1;
mxStep = maxstep(eq,rx)
mxStep = 0.3154
[y,err,weights] = eq(rx,tx(1:numTrainingSymbols));

Постройте созвездие которым повреждают и компенсируемых символов.

constell = comm.ConstellationDiagram('NumInputPorts',2);
constell(rx,y);

Постройте сигнал ошибки эквалайзера и вычислите величину вектора ошибок (EVM) компенсируемых символов.

plot(abs(err));
grid on;
xlabel('Symbols');
ylabel('|e|');
title('Equalizer Error Signal');

Figure contains an axes object. The axes object with title Equalizer Error Signal contains an object of type line.

errevm = comm.EVM;
evm = errevm(tx,y)
evm = 11.7710

Постройте веса касания эквалайзера.

subplot(3,1,1); 
stem(real(weights));
ylabel('real(weights)');
xlabel('Tap');
grid on;
axis([0 6 -0.5 1]);
title('Equalizer Tap Weights');
subplot(3,1,2); 
stem(imag(weights));
ylabel('imag(weights)');
xlabel('Tap');
grid on;
axis([0 6 -0.5 1]);
subplot(3,1,3); 
stem(abs(weights));
ylabel('abs(weights)');
xlabel('Tap');
grid on;
axis([0 6 -0.5 1]);

Figure contains 3 axes objects. Axes object 1 with title Equalizer Tap Weights contains an object of type stem. Axes object 2 contains an object of type stem. Axes object 3 contains an object of type stem.

Продемонстрируйте, что линейная эквализация при помощи алгоритма наименьшее количество средних квадратичных (LMS), чтобы восстановить символы QPSK прошла через канал AWGN. Примените различные планы подготовки эквалайзера и покажите ошибочную величину символа.

Системный Setup

Симулируйте модулируемую QPSK систему, удовлетворяющую AWGN. Передайте пакеты, состоявшие из 200 учебных символов и 1 800 случайных символов данных. Сконфигурируйте линейный эквалайзер LMS, чтобы восстановить пакетные данные.

M = 4;
numTrainSymbols = 200;
numDataSymbols = 1800;
SNR = 20;
trainingSymbols = pskmod(randi([0 M-1],numTrainSymbols,1),M,pi/4);
numPkts = 10;
lineq = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',5,'ReferenceTap',3,'StepSize',0.01);

Обучите эквалайзер в начале каждого пакета со сбросом

Используйте предварительно ожидаемые учебные символы при обработке каждого пакета. После обработки каждого пакета, сброс эквалайзер. Этот сброс обеспечивает эквалайзер, чтобы обучить касания без предыдущих знаний. Графики сигнала ошибки эквалайзера для первого, второго, и последнего пакета показывают более высокие ошибки символа в начале каждого пакета.

jj = 1;
figure
for ii = 1:numPkts
    b = randi([0 M-1],numDataSymbols,1);
    dataSym = pskmod(b,M,pi/4);
    packet = [trainingSymbols;dataSym];
    rx = awgn(packet,SNR);
    [~,err] = lineq(rx,trainingSymbols);
    reset(lineq)
    if (ii ==1 || ii == 2 ||ii == numPkts)
        subplot(3,1,jj)
        plot(abs(err))
        title(['Packet # ',num2str(ii)])
        xlabel('Symbols')
        ylabel('Error Magnitude')
        axis([0,length(packet),0,1])
        grid on;
        jj = jj+1;
    end
end

Figure contains 3 axes objects. Axes object 1 with title Packet # 1 contains an object of type line. Axes object 2 with title Packet # 2 contains an object of type line. Axes object 3 with title Packet # 10 contains an object of type line.

Обучите эквалайзер в начале каждого пакета без сброса

Процесс каждый пакет с помощью предварительно ожидаемых учебных символов. Не сбрасывайте эквалайзер после того, как каждый пакет будет обработан. Не сбрасывая после каждого пакета, эквалайзер сохраняет веса касания от учебных предшествующих пакетов. Графики сигнала ошибки эквалайзера для первого, второго, и последнего пакета показывают, что после начальной подготовки на первом пакете, последующие пакеты имеют меньше ошибок символа в начале каждого пакета.

release(lineq)
jj = 1;
figure
for ii = 1:numPkts
    b = randi([0 M-1],numDataSymbols,1);
    dataSym = pskmod(b,M,pi/4);
    packet = [trainingSymbols;dataSym];
    channel = 1;
    rx = awgn(packet*channel,SNR);
    [~,err] = lineq(rx,trainingSymbols);
    if (ii ==1 || ii == 2 ||ii == numPkts)
        subplot(3,1,jj)
        plot(abs(err))
        title(['Packet # ',num2str(ii)])
        xlabel('Symbols')
        ylabel('Error Magnitude')
        axis([0,length(packet),0,1])
        grid on;
        jj = jj+1;
    end
end

Figure contains 3 axes objects. Axes object 1 with title Packet # 1 contains an object of type line. Axes object 2 with title Packet # 2 contains an object of type line. Axes object 3 with title Packet # 10 contains an object of type line.

Обучайте эквалайзер периодически

Системы с сигналами, удовлетворяющими изменяющимся во времени каналам, требуют, чтобы периодическое обучение эквалайзера обеспечить соединило изменения канала. Задайте систему, которая имеет 200 символов обучения каждым 1 800 символам данных. Между обучением эквалайзер не обновляет веса касания. Процессы эквалайзера 200 символов на пакет.

Rs = 1e6;
fd = 20;
spp = 200; % Symbols per packet
b = randi([0 M-1],numDataSymbols,1);
dataSym = pskmod(b,M,pi/4);
packet = [trainingSymbols; dataSym];
stream = repmat(packet,10,1);
tx = (0:length(stream)-1)'/Rs;
channel = exp(1i*2*pi*fd*tx);
rx = awgn(stream.*channel,SNR);

Установите AdaptAfterTraining свойство к false чтобы остановить эквалайзер касаются обновлений веса после учебной фазы.

release(lineq)
lineq.AdaptAfterTraining = false
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [0.7071 + 0.7071i -0.7071 + 0.7071i ... ]
             ReferenceTap: 3
               InputDelay: 0
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: false
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

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

[y,err] = lineq(rx,trainingSymbols);

figure
subplot(2,1,1)
plot(tx, unwrap(angle(channel)))
xlabel('Time (sec)')
ylabel('Channel Angle (rad)')
title('Angular Error Over Time')
subplot(2,1,2)
plot(abs(err))
xlabel('Symbols')
ylabel('Error Magnitude')
grid on
title('Time-Varying Channel Without Retraining')

Figure contains 2 axes objects. Axes object 1 with title Angular Error Over Time contains an object of type line. Axes object 2 with title Time-Varying Channel Without Retraining contains an object of type line.

scatterplot(y)

Figure Scatter Plot contains an axes object. The axes object with title Scatter plot contains an object of type line. This object represents Channel 1.

Установите TrainingInputPort свойство к true сконфигурировать эквалайзер, чтобы переобучить касания, когда сообщено trainFlag входной параметр. Эквалайзер обучается только когда trainFlag true. После каждых 2 000 символов эквалайзер переобучает касания и сохраняет, соединяют изменения канала. Постройте угловую погрешность от канала, сигнала ошибки эквалайзера и сигнального созвездия. Когда канал варьируется, эквалайзер, выход удаляет эффекты канала. Выходное созвездие не вращается из синхронизирующих и битовых ошибок, уменьшаются.

release(lineq)
lineq.TrainingFlagInputPort = true;
symbolCnt = 0;
numPackets = length(rx)/spp;
trainFlag = true;
trainingPeriod = 2000;
eVec = zeros(size(rx));
yVec = zeros(size(rx));
for p=1:numPackets
    [yVec((p-1)*spp+1:p*spp,1),eVec((p-1)*spp+1:p*spp,1)] = ...
        lineq(rx((p-1)*spp+1:p*spp,1),trainingSymbols,trainFlag);
    symbolCnt = symbolCnt + spp;
    if symbolCnt >= trainingPeriod
        trainFlag = true;
        symbolCnt = 0;
    else
        trainFlag = false;
    end
end
figure
subplot(2,1,1)
plot(tx, unwrap(angle(channel)))
xlabel('t (sec)')
ylabel('Channel Angle (rad)')
title('Angular Error Over Time')
subplot(2,1,2)
plot(abs(eVec))
xlabel('Symbols')
ylabel('Error Magnitude')
grid on
title('Time-Varying Channel With Retraining')

Figure contains 2 axes objects. Axes object 1 with title Angular Error Over Time contains an object of type line. Axes object 2 with title Time-Varying Channel With Retraining contains an object of type line.

scatterplot(yVec)

Figure Scatter Plot contains an axes object. The axes object with title Scatter plot contains an object of type line. This object represents Channel 1.

Симулируйте систему с задержкой между переданными символами и полученными выборками. Типичные системы имеют фильтры передатчика и приемника, которые приводят к задержке. Эта задержка должна составляться, чтобы синхронизировать систему. В этом примере системная задержка введена без передачи, и получите фильтры. Линейная эквализация, с помощью алгоритма наименьшее количество средних квадратичных (LMS), восстанавливает символы QPSK.

Инициализируйте переменные симуляции.

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
mpChan = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];
systemDelay = dsp.Delay(20);
snr = 24;

Сгенерируйте модулируемые QPSK символы. Примените многопутевую фильтрацию канала, системную задержку и AWGN к переданным символам.

data = randi([0 M-1],numSymbols,1);
tx = pskmod(data,M,pi/4); % OQPSK
delayedSym = systemDelay(filter(mpChan,1,tx));
rx = awgn(delayedSym,snr,'measured');

Создайте эквалайзер и Системные объекты EVM. Системный объект эквалайзера задает линейный эквалайзер, который использует LMS-алгоритм.

lineq = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',9,'ReferenceTap',5);
evm = comm.EVM('ReferenceSignalSource', ...
    'Estimated from reference constellation');

Компенсируйте, не настраивая входную задержку

Компенсируйте полученные символы.

[y1,err1,wts1] = lineq(rx,tx(1:numTrainingSymbols,1));

Найдите задержку между полученными символами и переданными символами при помощи finddelay функция.

rxDelay = finddelay(tx,rx)
rxDelay = 20

Отобразите информацию об эквалайзере. Значение задержки указывает на задержку, введенную эквалайзером. Вычислите общую задержку как сумму rxDelay и задержка эквалайзера.

eqInfo = info(lineq)
eqInfo = struct with fields:
    Latency: 4

totalDelay = rxDelay + eqInfo.Latency;

Пока эквалайзер, выход сходится, коэффициент ошибок символа, не высок. Постройте вывод ошибок, err1, определить, когда компенсируемый выход сходится.

plot(abs(err1))
xlabel('Symbols')
ylabel('Error Magnitude')
title('Equalizer Error Signal')

Figure contains an axes object. The axes object with title Equalizer Error Signal contains an object of type line.

График показывает чрезмерные ошибки вне этих 1 000 периодов подготовки символов. Когда демодуляция символов и вычислительных ошибок символа, с учетом не сходившегося выхода и системной задержки между эквалайзером выход и переданными символами, пропускает первые 2 000 символов.

dataRec1 = pskdemod(y1(2000+totalDelay:end),M,pi/4);
symErrWithDelay = symerr(data(2000:end-totalDelay),dataRec1)
symErrWithDelay = 5999
evmWithDelay = evm(y1)
evmWithDelay = 29.5795

Коэффициент ошибок и EVM высоки, потому что задержка приема не составлялась в Системном объекте эквалайзера.

Настройте входную задержку эквалайзера

Компенсируйте принятые данные при помощи значения задержки, чтобы установить InputDelay свойство. Поскольку InputDelay ненастраиваемое свойство, необходимо выпустить lineq Системный объект, чтобы реконфигурировать InputDelay свойство. Компенсируйте полученные символы.

release(lineq)
lineq.InputDelay = rxDelay
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'LMS'
                  NumTaps: 9
                 StepSize: 0.0100
            Constellation: [0.7071 + 0.7071i -0.7071 + 0.7071i ... ]
             ReferenceTap: 5
               InputDelay: 20
    InputSamplesPerSymbol: 1
    TrainingFlagInputPort: false
       AdaptAfterTraining: true
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

[y2,err2,wts2] = lineq(rx,tx(1:numTrainingSymbols,1));

Постройте веса касания и компенсируемую ошибочную величину. Диаграмма стебель-листья показывает, что веса касания эквалайзера до и после системной задержки удалены. 2D график показывает более медленную сходимость эквалайзера для задержанного сигнала по сравнению с сигналом с удаленной задержкой.

subplot(2,1,1)
stem([real(wts1),real(wts2)])
xlabel('Taps')
ylabel('Tap Weight Real')
legend('rxDelayed','rxDelayRemoved')
grid on
subplot(2,1,2)
stem([imag(wts1),imag(wts2)])
xlabel('Taps')
ylabel('Tap Weight Imaginary')
legend('rxDelayed','rxDelayRemoved')
grid on

Figure contains 2 axes objects. Axes object 1 contains 2 objects of type stem. These objects represent rxDelayed, rxDelayRemoved. Axes object 2 contains 2 objects of type stem. These objects represent rxDelayed, rxDelayRemoved.

figure
plot([abs(err1),abs(err2)])
xlabel('Symbols')
ylabel('Error Magnitude')
legend('rxDelayed','rxDelayRemoved')
grid on

Figure contains an axes object. The axes object contains 2 objects of type line. These objects represent rxDelayed, rxDelayRemoved.

Постройте вывод ошибок компенсируемых сигналов, rxDelayed и rxDelayRemoved. Для сигнала, которому удалили задержку, эквалайзер сходится во время 1 000 периодов подготовки символа. Когда демодуляция символов и вычислительных ошибок символа, с учетом не сходившегося выхода и системной задержки между эквалайзером выход и переданными символами, пропускает первые 500 символов. Реконфигурирование эквалайзера с учетом системной задержки включает лучшую эквализацию сигнала и уменьшает ошибки символа и EVM.

eqInfo = info(lineq)
eqInfo = struct with fields:
    Latency: 4

totalDelay = rxDelay + eqInfo.Latency;
dataRec2 = pskdemod(y2(500+totalDelay:end),M,pi/4);
symErrDelayRemoved = symerr(data(500:end-totalDelay),dataRec2)
symErrDelayRemoved = 0
evmDelayRemoved = evm(y2(500+totalDelay:end))
evmDelayRemoved = 9.4435

Восстановите символы QPSK с линейным эквалайзером при помощи постоянного алгоритма модуля (CMA) и основанного на EVM обучения касаний. При использовании слепых алгоритмов эквалайзера, таких как CMA, обучают касания эквалайзера при помощи AdaptWeights свойство запуститься и остановить обучение. Функции помощника используются, чтобы сгенерировать графики и применить коррекцию фазы.

Инициализируйте системные переменные.

rng(123456);
M = 4; % QPSK
numSymbols = 100;
numPackets = 5000;
raylChan = comm.RayleighChannel( ...
    'PathDelays',[0 1], ...
    'AveragePathGains',[0 -12], ...
    'MaximumDopplerShift',1e-5);
SNR = 50;
adaptWeights = true;

Создайте эквалайзер и Системные объекты EVM. Системный объект эквалайзера задает линейный эквалайзер при помощи CMA адаптивный алгоритм. Вызовите функцию помощника, чтобы инициализировать графики фигуры.

lineq = comm.LinearEqualizer( ...
    'Algorithm','CMA', ...
    'NumTaps',5, ...
    'ReferenceTap',3, ...
    'StepSize',0.03, ...
    'AdaptWeightsSource','Input port')
lineq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'CMA'
                  NumTaps: 5
                 StepSize: 0.0300
            Constellation: [0.7071 + 0.7071i -0.7071 + 0.7071i ... ]
             ReferenceTap: 3
    InputSamplesPerSymbol: 1
       AdaptWeightsSource: 'Input port'
     InitialWeightsSource: 'Auto'
       WeightUpdatePeriod: 1

info(lineq)
ans = struct with fields:
    Latency: 2

evm = comm.EVM('ReferenceSignalSource', ...
    'Estimated from reference constellation');
[errPlot,evmPlot,scatSym,adaptState] = ...
    initFigures(numPackets,lineq);

Цикл эквализации

Реализовывать цикл эквализации:

  1. Сгенерируйте пакеты данных о PSK.

  2. Примените Релеевское замирание и AWGN к данным о передаче.

  3. Примените эквализацию к принятым данным и коррекцию фазы к эквалайзеру выход.

  4. Оцените EVM и переключите adaptWeights отметьте к true или false на основе уровня EVM.

  5. Обновите графики фигуры.

for p=1:numPackets
    data = randi([0 M-1],numSymbols,1);
    tx = pskmod(data,M,pi/4);
    rx = awgn(raylChan(tx),SNR);
    rxDelay = finddelay(rx,tx);
    [y,err,wts] = lineq(rx,adaptWeights);
    y = phaseCorrection(y);
    evmEst = evm(y);
    adaptWeights = (evmEst > 20);
    
    updateFigures(errPlot,evmPlot,scatSym,adaptState, ...
        wts,y(end),evmEst,adaptWeights,p,numPackets)
end

Figure contains 4 axes objects. Axes object 1 with title Tap Weight Magnitude contains an object of type stem. Axes object 2 with title Scatter Plot contains an object of type line. Axes object 3 with title Adapt Weights Signal contains an object of type line. Axes object 4 with title EVM contains an object of type line.

rxDelay
rxDelay = 0

Графики фигуры показывают, что, когда EVM варьируется, переключатели эквалайзера в и из направленного на решение режима адаптации веса.

Функции помощника

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

function [errPlot,evmPlot,scatter,adaptState] = ...
    initFigures(numPkts,lineq)
yVec = nan(numPkts,1);
evmVec = nan(numPkts,1);
wVec = zeros(lineq.NumTaps,1);
adaptVec = nan(numPkts,1);

figure
subplot(2,2,1)
evmPlot = stem(wVec);
grid on; axis([1 lineq.NumTaps 0 1.8])
xlabel('Taps');
ylabel('|Weights|');
title('Tap Weight Magnitude')

subplot(2,2,2)
scatter = plot(yVec, '.');
axis square;
axis([-1.2 1.2 -1.2 1.2]);
grid on
xlabel('In-phase');
ylabel('Quadrature');
title('Scatter Plot');
subplot(2,2,3)
adaptState = plot(adaptVec);
grid on;
axis([0 numPkts -0.2 1.2])
ylabel('Training');
xlabel('Symbols');
title('Adapt Weights Signal')
subplot(2,2,4)
errPlot = plot(evmVec);
grid on;
axis([1 numPkts 0 100])
xlabel('Symbols');
ylabel('EVM (%)');
title('EVM')
end

Эта функция помощника обновляет фигуры.

function updateFigures(errPlot,evmPlot,scatSym, ...
    adaptState,w,y,evmEst,adaptWts,p,numFrames)
persistent yVec evmVec adaptVec

if p == 1
    yVec = nan(numFrames,1);
    evmVec = nan(numFrames,1);
    adaptVec = nan(numFrames,1);
end

yVec(p) = y;
evmVec(p) = evmEst;
adaptVec(p) = adaptWts;

errPlot.YData = abs(evmVec);
evmPlot.YData = abs(w);
scatSym.XData = real(yVec);
scatSym.YData = imag(yVec);
adaptState.YData = adaptVec;
drawnow limitrate
end

Эта функция помощника применяет коррекцию фазы.

function y = phaseCorrection(y)
a = angle(y((real(y) > 0) & (imag(y) > 0)));
a(a < 0.1) = a(a < 0.1) + pi/2;
theta = mean(a) - pi/4;
y = y * exp(-1i*theta);
end

Восстановите символы QPSK в исчезающих средах с линейным эквалайзером, с помощью алгоритма наименьшее количество средних квадратичных (LMS). Используйте reset возразите функции, чтобы компенсировать независимые пакеты. Используйте функции помощника, чтобы сгенерировать графики. Этот пример также показывает основанную на символе обработку и основанную на системе координат обработку.

Настройка

Инициализируйте системные переменные, создайте Системный объект эквалайзера и инициализируйте фигуры графика.

M = 4; % QPSK
numSym = 1000;
numTrainingSym = 100;
numPackets = 5;
numTaps = 9;
ttlNumSym = numSym + numTrainingSym;
raylChan = comm.RayleighChannel( ...
    'PathDelays',[0 1], ...
    'AveragePathGains',[0 -9], ...
    'MaximumDopplerShift',0, ...
    'PathGainsOutputPort',true);
SNR = 35;
rxVec = zeros(ttlNumSym,numPackets);
txVec = zeros(ttlNumSym,numPackets);
yVec = zeros(ttlNumSym,1);
eVec = zeros(ttlNumSym,1);

lineq1 = comm.LinearEqualizer( ...
    'Algorithm','LMS', ...
    'NumTaps',numTaps, ...
    'ReferenceTap',5, ...
    'StepSize',0.01, ...
    'TrainingFlagInputPort',true);

[errPlot,wStem,hStem,scatPlot] = initFigures(ttlNumSym,lineq1, ...
    raylChan.AveragePathGains);

Основанная на символе обработка

Для основанной на символе обработки обеспечьте один символ во входе эквалайзера. Сбросьте состояние эквалайзера и канал после обработки каждого пакета.

for p = 1:numPackets
    trainingFlag = true;
    for q=1:ttlNumSym
        data = randi([0 M-1],1,1);
        tx = pskmod(data,M,pi/4);
        [xc,pg] = raylChan(tx);
        rx = awgn(xc,25);
        [y,err,wts] = lineq1(rx,tx,trainingFlag);       

Отключите обучение после обработки numTrainingSym учебные символы.

        if q == numTrainingSym
            trainingFlag = false;
        end        
        updateFigures(errPlot,wStem,hStem,scatPlot,err, ...
            wts,y,pg,q,ttlNumSym);
        txVec(q,p) = tx;
        rxVec(q,p) = rx;
    end 

После обработки каждого пакета сброс Системный объект канала, чтобы получить новую реализацию канала касается и Системный объект эквалайзера, чтобы восстановить набор по умолчанию весов касания.

    reset(raylChan)
    reset(lineq1)
end

Figure contains 4 axes objects. Axes object 1 with title Tap Weight Magnitude contains an object of type stem. Axes object 2 with title Channel Path Gain Magnitude contains an object of type stem. Axes object 3 with title Error Magnitude contains an object of type line. Axes object 4 with title Scatter Plot contains an object of type line.

Основанная на пакете обработка

Для основанной на пакете обработки обеспечьте один пакет во входе эквалайзера. Каждый пакет содержит ttlNumSym символы. Поскольку учебная длительность меньше пакетной длины, вы не должны задавать вход начинать-обучения.

yVecPkt = zeros(ttlNumSym,numPackets);
errVecPkt = zeros(ttlNumSym,numPackets);
wgtVecPkt = zeros(numTaps,numPackets);
lineq2 = comm.LinearEqualizer('Algorithm','LMS', ...
    'NumTaps',9,'ReferenceTap',6,'StepSize',0.01);
for p = 1:numPackets
    [yVecPkt(:,p),errVecPkt(:,p),wgtVecPkt(:,p)] = ...
        lineq2(rxVec(:,p),txVec(1:numTrainingSym,p));
    for q=1:ttlNumSym
        updateFigures(errPlot,wStem,hStem,scatPlot, ...
            errVecPkt(q,p),wgtVecPkt(:,p), ...
            yVecPkt(q,p),pg,q,ttlNumSym);
    end

После обработки каждого пакета сброс Системный объект канала, чтобы получить новую реализацию канала касается и Системный объект эквалайзера, чтобы восстановить набор по умолчанию весов касания.

    reset(raylChan)
    reset(lineq2)
end

Figure contains 4 axes objects. Axes object 1 with title Tap Weight Magnitude contains an object of type stem. Axes object 2 with title Channel Path Gain Magnitude contains an object of type stem. Axes object 3 with title Error Magnitude contains an object of type line. Axes object 4 with title Scatter Plot contains an object of type line.

Функции помощника

Функция помощника инициализирует фигуры.

function [errPlot,wStem,hStem,scatPlot] = ...
    initFigures(ttlNumSym,lineq,pg)
yVec = nan(ttlNumSym,1);
eVec = nan(ttlNumSym,1);
wVec = zeros(lineq.NumTaps,1);
figure;
subplot(2,2,1);
wStem = stem(wVec);
axis([1 lineq.NumTaps 0 1.8]);
grid on;
xlabel('Taps');
ylabel('|Weights|');
title('Tap Weight Magnitude');
subplot(2,2,2);
hStem = stem([0 abs(pg) 0]);
grid on;
xlabel('Taps');
ylabel('|Path Gain|');
title('Channel Path Gain Magnitude');
subplot(2,2,3);
errPlot = plot(eVec);
axis([1 ttlNumSym 0 1.2]);
grid on;
xlabel('Symbols');
ylabel('|Error Magnitude|');
title('Error Magnitude');
subplot(2,2,4);
scatPlot = plot(yVec,'.');
axis square;
axis([-1.2 1.2 -1.2 1.2]);
grid on;
xlabel('In-phase');
ylabel('Quadrature');
title(sprintf('Scatter Plot'));
end

Эта функция помощника обновляет фигуры.

function updateFigures(errPlot,wStem,hStem,scatPlot, ...
    err,wts,y,pg,p,ttlNumSym)
persistent yVec eVec
if p == 1
    yVec = nan(ttlNumSym,1);
    eVec = nan(ttlNumSym,1);
end
yVec(p) = y;
eVec(p) = abs(err);
errPlot.YData = abs(eVec);
wStem.YData = abs(wts);
hStem.YData = [0 abs(pg) 0];
scatPlot.XData = real(yVec);
scatPlot.YData = imag(yVec);
drawnow limitrate
end

Используйте линейный эквалайзер в неадаптивном режиме. Используйте mmseweights возразите функции, чтобы вычислить решение для минимальной среднеквадратической ошибки (MMSE) и использовать веса, возвращенные в качестве набора весов касания для линейного эквалайзера.

Инициализируйте переменные симуляции.

M = 4; % QPSK
numSymbols = 10000;
numTrainingSymbols = 1000;
chtaps = [1 0.5*exp(1i*pi/6) 0.1*exp(-1i*pi/8)];
EbN0 = 20;

Сгенерируйте модулируемые символы QPSK. Примените задержанную многопутевую фильтрацию канала и ухудшения AWGN к символам.

data = randi([0 M-1], numSymbols, 1);
tx = pskmod(data, M, pi/4);
rx = awgn(filter(chtaps,1,tx),25,'measured');

Создайте линейный Системный объект эквалайзера, сконфигурированный, чтобы использовать алгоритм CMA, установить AdaptWeights свойство к false, и InitialWeightsSource свойство к Property. Вычислите веса MMSE. Установите начальные веса касания на расчетные веса MMSE. Компенсируйте символы, которым повреждают.

eq = comm.LinearEqualizer( ...
    'Algorithm','CMA', ...
    'AdaptWeights',false, ...
    'InitialWeightsSource','Property')
eq = 
  comm.LinearEqualizer with properties:

                Algorithm: 'CMA'
                  NumTaps: 5
                 StepSize: 0.0100
            Constellation: [0.7071 + 0.7071i -0.7071 + 0.7071i ... ]
    InputSamplesPerSymbol: 1
       AdaptWeightsSource: 'Property'
             AdaptWeights: false
     InitialWeightsSource: 'Property'
           InitialWeights: [5x1 double]
       WeightUpdatePeriod: 1

wgts = mmseweights(eq,chtaps,EbN0)
wgts = 5×1 complex

   0.0005 - 0.0068i
   0.0103 + 0.0117i
   0.9694 - 0.0019i
  -0.3987 + 0.2186i
   0.0389 - 0.1756i

eq.InitialWeights = wgts;
[y,err,weights] = eq(rx);

Постройте созвездие которым повреждают и компенсируемых символов.

constell = comm.ConstellationDiagram('NumInputPorts',2);
constell(rx,y);

Постройте сигнал ошибки эквалайзера и вычислите величину вектора ошибок компенсируемых символов.

plot(abs(err));
grid on;
xlabel('Symbols');
ylabel('|e|');

Figure contains an axes object. The axes object contains an object of type line.

errevm = comm.EVM;
evm = errevm(tx,y)
evm = 140.6177

Постройте веса касания эквалайзера.

subplot(3,1,1);
stem(real(weights));
ylabel('real(weights)');
xlabel('Tap');
grid on;
axis([1 8 -0.5 1]);
line([eq.NumTaps+0.5 eq.NumTaps+0.5],[-0.5 1], ...
    'Color','r','LineWidth',1);
title('Equalizer Tap Weights');
subplot(3,1,2);
stem(imag(weights));
ylabel('imag(weights)');
xlabel('Tap');
grid on;
axis([1 8 -0.5 1]);
line([eq.NumTaps+0.5 eq.NumTaps+0.5],[-0.5 1], ...
    'Color','r','LineWidth',1);
subplot(3,1,3);
stem(abs(weights));
ylabel('abs(weights)');
xlabel('Tap');
grid on;
axis([1 8 -0.5 1]);
line([eq.NumTaps+0.5 eq.NumTaps+0.5], ...
    [-0.5 1],'Color','r','LineWidth',1);

Figure contains 3 axes objects. Axes object 1 with title Equalizer Tap Weights contains 2 objects of type stem, line. Axes object 2 contains 2 objects of type stem, line. Axes object 3 contains 2 objects of type stem, line.

Продемонстрируйте, что линейная эквализация при помощи алгоритма наименьшее количество средних квадратичных (LMS), чтобы восстановить символы QPSK прошла через канал AWGN. Обработайте выборку выборкой сигнала.

Системный Setup

Симулируйте модулируемую QPSK систему, удовлетворяющую AWGN. Передайте пакеты, состоявшие из 200 учебных символов и 1 800 случайных символов данных. Сконфигурируйте линейный эквалайзер LMS, чтобы восстановить пакетные данные.

M = 4;
numTrainSymbols = 200;
numDataSymbols = 1800;
SNR = 20;
trainingSymbols = ...
    pskmod(randi([0 M-1],numTrainSymbols,1),M,pi/4);
numPkts = 10;
lineq = comm.LinearEqualizer( ...
    'Algorithm','LMS', ...
  'NumTaps',5, ...
  'ReferenceTap',3, ...
  'StepSize',0.01, ...
  'TrainingFlagInputPort',true);

Основной цикл

Используйте предварительно ожидаемые учебные символы при обработке каждого пакета. После обработки каждого пакета, сброс эквалайзер. Этот сброс обеспечивает эквалайзер, чтобы обучить касания без предыдущих знаний. Компенсируйте полученную выборку выборкой сигнала. Для каждого пакета используйте первые 200 символов для обучения.

subPlotCnt = 1;
figure
for ii = 1:numPkts
  b = randi([0 M-1],numDataSymbols,1);
  dataSym = pskmod(b,M,pi/4);
  packet = [trainingSymbols;dataSym];
  rx = awgn(packet,SNR);
  y = zeros(numDataSymbols+numTrainSymbols,1);
  err = zeros(numDataSymbols+numTrainSymbols,1);
  for jj = 1:numDataSymbols+numTrainSymbols
    if jj <= numTrainSymbols
      [y(jj),err(jj)] = ...
          lineq(rx(jj),trainingSymbols(jj),true);
    else
      [y(jj),err(jj)] = lineq(rx(jj),1i,false);
    end
  end
  reset(lineq)
  
  if (ii ==1 || ii == 2 ||ii == numPkts)
    subplot(3,1,subPlotCnt)
    plot(abs(err))
    title(['Packet # ',num2str(ii)])
    xlabel('Symbols')
    ylabel('Error Magnitude')
    axis([0,length(packet),0,1])
    grid on;
    subPlotCnt = subPlotCnt+1;
  end
end

Figure contains 3 axes objects. Axes object 1 with title Packet # 1 contains an object of type line. Axes object 2 with title Packet # 2 contains an object of type line. Axes object 3 with title Packet # 10 contains an object of type line.

Продемонстрируйте, что линейная эквализация при помощи алгоритма наименьшее количество средних квадратичных (LMS), чтобы восстановить символы QPSK прошла через канал AWGN. Обработайте пакет, который имеет учебные символы вначале в нескольких передачах. Сравните результаты с эквализацией, обрабатывающей полный пакет в одной передаче.

Системный Setup

Симулируйте модулируемую QPSK систему, удовлетворяющую AWGN. Передайте пакеты, состоявшие из 200 учебных символов и 1 800 случайных символов данных. Сконфигурируйте линейный эквалайзер LMS, чтобы восстановить пакетные данные.

M = 4;
numTrainSymbols = 200;
numDataSymbols = 1800;
SNR = 20;
trainingSymbols = ...
    pskmod(randi([0 M-1],numTrainSymbols,1),M,pi/4);
b = randi([0 M-1],numDataSymbols,1);
dataSym = pskmod(b,M,pi/4);
packet = [trainingSymbols;dataSym];
rx = awgn(packet,SNR);
lineq = comm.LinearEqualizer( ...
    'Algorithm','LMS', ...
    'NumTaps',5, ...
    'ReferenceTap',3, ...
    'StepSize',0.01);

Пакет процесса в одной передаче

Используйте предварительно ожидаемые учебные символы при обработке каждого пакета. После обработки каждого пакета, сброс эквалайзер. Этот сброс обеспечивает эквалайзер, чтобы обучить касания без предыдущих знаний. Компенсируйте полученную выборку выборкой сигнала. Для каждого пакета используйте первые 200 символов для обучения.

subPlotCnt = 1;
figure
[y1,err1] = lineq(rx,trainingSymbols);
reset(lineq)

plot(abs(err1))
title("Single Pass Processing")
xlabel('Symbols')
ylabel('Error Magnitude')
axis([0,length(packet),0,1])
grid on;

Figure contains an axes object. The axes object with title Single Pass Processing contains an object of type line.

Пакет процесса в нескольких передачах

Используйте предварительно ожидаемые учебные символы при обработке каждого пакета. После обработки каждого пакета, сброс эквалайзер. Этот сброс обеспечивает эквалайзер, чтобы обучить касания без предыдущих знаний. Компенсируйте полученную выборку выборкой сигнала. Для каждого пакета используйте первые 200 символов для обучения.

lineq = comm.LinearEqualizer( ...
    'Algorithm','LMS', ...
    'NumTaps',5, ...
    'ReferenceTap',3, ...
    'StepSize',0.01, ...
    'TrainingFlagInputPort',true);

frameLen = 100;
numFrames = (numDataSymbols+numTrainSymbols) / frameLen;

figure
y2 = zeros(numDataSymbols+numTrainSymbols,1);
err2 = zeros(numDataSymbols+numTrainSymbols,1);
idx = 1:frameLen;
symbolCnt = 0;
for jj = 1:numFrames
    if symbolCnt < numTrainSymbols
        [y2(idx),err2(idx)] = ...
            lineq(rx(idx),trainingSymbols(idx),true);
    else
        [y2(idx),err2(idx)] = ...
            lineq(rx(idx),1i*ones(frameLen,1),false);
    end
    idx = idx + frameLen;
    symbolCnt = symbolCnt + frameLen;
end
reset(lineq)

plot(abs(err2))
title("Multipass Processing")
xlabel('Symbols')
ylabel('Error Magnitude')
axis([0,length(packet),0,1])
grid on;

Figure contains an axes object. The axes object with title Multipass Processing contains an object of type line.

Результаты эквализации с помощью одной передачи и многопроходного соответствия подходов.

outputsEqual = isequal(y1,y2)
outputsEqual = logical
   1

errorsEqual = isequal(err1,err2)
errorsEqual = logical
   1

Больше о

развернуть все

Алгоритмы

развернуть все

Расширенные возможности

Генерация кода C/C++
Генерация кода C и C++ с помощью MATLAB® Coder™.

Введенный в R2019a