Квадратурная амплитудная модуляция
Данное приложение визуализирует поток информации, представленный в виде потока десятичных чисел, двоичных чисел, а также модулированного радиосигнала. Графический интерфейс отображает три соответствующих графика, а также три индикатора с текущим десятичным числом, двоичным числом, и комплексным числом, отображающим текущее изменение амплитуды и фазового сдвига радиосигнала.
Состоит из основного скрипта QAM_live.m:
clear all
dlength = 1024; % количество чисел в кадре данных
M = 16; % количество позиций модуляции
fs= 30; % чacтота сигнального сэмплирования
fm = 1; % частота радиосигнала
nf = 30; % частота обновления изображения
[dSig, bSig, mSig, tfield, dData, bData, btact, cNums] = Qframe(dlength, M, fs, fm);
tw = 16; % длина временного поля на графике
tfp = 0:1/fs:tw-1/fs; % разметка временного поля графика
sp = 1; % скорость обновления данных
F = uifigure('Name','Quadrature amplitude modulation', 'Position', [160 135 933 525],'Resize','off');
uilabel(F,"Text", string(M),'Position',[0 490 50 28],'FontSize', [20],'FontColor',[0 0.1 0.3], 'HorizontalAlignment', 'right','FontWeight','bold');
uilabel(F,"Text",'-QAM,','Position',[50 490 70 28],'FontSize', [20],'FontColor',[0 0.1 0.3],'FontWeight','bold');
uilabel(F,"Text",string(btact),'Position',[85 490 50 28],'FontSize', [20],'FontColor',[0 0.1 0.3], 'HorizontalAlignment', 'right','FontWeight','bold');
uilabel(F,"Text",'bits per symbol','Position',[138 490 150 28],'FontSize', [20],'FontColor',[0 0.1 0.3], 'HorizontalAlignment', 'left','FontWeight','bold');
dAx = uiaxes(F,'color', [62/256 95/256 138/256], 'GridColor', [1 1 0],'Position',[10 345 913 140],'XGrid','on','YGrid','on');
title(dAx,'Data in decimal form','FontWeight','bold','FontSize', [14], Color=[0 0.1 0.3]);
dNum = uilabel(F,"Text",'','Position',[40 330 90 33],'FontSize', [30],'FontColor',[1 0 1], 'HorizontalAlignment', 'left','FontWeight','bold');
bAx = uiaxes(F,'color', [62/256 95/256 138/256], 'GridColor', [1 1 0],'Position',[10 195 913 140],'XGrid','on','YGrid','on');
title(bAx,'Data in binary form','FontWeight','bold','FontSize', [14], Color=[0 0.1 0.3]);
bNum = uilabel(F,"Text",'','Position',[40 175 190 33],'FontSize', [30],'FontColor',[1 0 1], 'HorizontalAlignment', 'left','FontWeight','bold');
mAx = uiaxes(F,'color', [62/256 95/256 138/256], 'GridColor', [1 1 0],'Position',[10 40 913 140],'XGrid','on','YGrid','on');
title(mAx,'Modulated radio signal','FontWeight','bold','FontSize', [14], Color=[0 0.1 0.3]);
mNum = uilabel(F,"Text",'','Position',[40 20 290 33],'FontSize', [30],'FontColor',[1 0 1], 'HorizontalAlignment', 'left','FontWeight','bold');
dSigLive = plot(dAx, tfp, zeros(1, length(tfp)),LineWidth=1.3,Color=[0 1 0]);
axis(dAx,[0 tw-1/fs -0.1 1.1*max(dSig)]);
bSigLive = plot(bAx, tfp, zeros(1, length(tfp)),LineWidth=1.3,Color=[0 1 0]);
axis(bAx, [0 tw-1/fs -0.1 1.2]);
mSigLive = plot(mAx, tfp, zeros(1, length(tfp)),LineWidth=1.3,Color=[0 1 0]);
axis(mAx, [0 tw-1/fs -1.1*max(mSig) 1.1*max(mSig)]);
scatterplot(cNums)
title(string(M) + '-QAM complex plane')
ft=0; % счётчик сэмплов времени
fd=0; % счётчик символов данных
tStart=(double(convertTo(datetime('now'),"ntp")))/2^32; % текущее начальное время
while isvalid(F)
t=((double(convertTo(datetime('now'),"ntp")))/2^32-tStart); % текущее время, начиная с 0
if ft < t*fs
ft1=sp*ft+1;
ft=ft+fs/nf;
ft2=sp*ft;
if ft > fd*fs*btact
fd = fd+1;
dNum.Text = string(dData(fd));
bNum.Text = strjoin(string(uint8(bData(fd,:))));
mNum.Text = string(cNums(fd));
end
dSigLive.YData(1:sp*fs/nf)=dSig(ft1:ft2);
bSigLive.YData(1:sp*fs/nf)=bSig(ft1:ft2);
mSigLive.YData(1:sp*fs/nf)=mSig(ft1:ft2);
for n = 1:sp:tw*nf-sp
dSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)) = dSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-2*sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf);
bSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)) = bSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-2*sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf);
mSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)) = mSigLive.YData(((tw*nf+1)*(fs/nf))-n*(fs/nf)-2*sp*fs/nf+1:((tw*nf+1)*(fs/nf))-n*(fs/nf)-sp*fs/nf);
end
drawnow
end
if ft >= dlength*fs*btact
close(F);
end
end
Функция mSignal.m:
function [mSig] = mSignal(tfield, dlength, fs, btact, Amp, Phi, fm) % функция генерации радиосигнала
ampSig = zeros(1, length(tfield));
phiSig = zeros(1, length(tfield));
k=0;
for i=1:dlength
for j=1:fs*btact
k=k+1;
ampSig(k)=Amp(i);
phiSig(k)=Phi(i);
end
end
mSig = single(ampSig.*sin((2*pi.*(tfield-phiSig)).*fm));
end
Функция mData.m:
function [Amp, Phi, cNums] = mData(dData, M) % функция вычисления амплитуд и фаз модуляции
cNums = qammod(dData, M, 'UnitAveragePower', true); % вычисление комплексных чисел модуляции
Amp = abs(cNums); % вычисление амплитуд
Phi = angle(cNums); % вычисление фаз
end
Функция dSignal.m:
function dSig = dSignal(tfield, dlength, fs, btact, dData) % функция генерации кадра десятичных прямоугольных импульсов
dSig = uint8(zeros(1, length(tfield)));
k=0;
for i=1:dlength
for j=1:fs*btact
k=k+1;
dSig(k)=uint8(dData(i));
end
end
end
Функция bSignal.m
function [tfield, bSig] = bSignal(dlength, fs, bData, btact) % функция генерации кадра двоичных прямоугольных импульсов
fbData = flip(bData, 2);
tfield=0:1/fs:dlength*btact-1/fs; % разметка временного поля в значениях один бит на одну единицу времени
bSig=zeros(1,length(tfield));
k=0;
for i=1:dlength
for j=1:btact
k=k+1;
switch fbData(i,j)
case 0
bSig(1+fs*(k-1):fs*k)=zeros(1,fs);
case 1
bSig(1+fs*(k-1):fs*k)=ones(1,fs);
end
end
end
bSig=logical(bSig);
end
Dataframe.m:
function [decData, binData, btact] = Dataframe(dlength, M)
btact=log2(M); % количество бит, передаваемых за 1 такт
decData = randi([0 M-1],dlength,1); % генерация случайных десятичних чисел от 0 до M-1 в количестве dlength
stBin=dec2bin(decData,btact);
binData=zeros(dlength,btact);
for p=1:dlength
for q=1:btact
binData(p,q)=str2double(stBin(p,q));
end
end
binData=logical(binData);
end
Функция Qframe.m:
function [dSig, bSig, mSig, tfield, dData, bData, btact, cNums] = Qframe(dlength, M, fs, fm)
[dData, bData, btact] = Dataframe(dlength, M); % обращение к функции генерации кадра данных
[tfield, bSig] = bSignal(dlength, fs, bData, btact); % обращение к функции генерации кадра двоичных прямоугольных импульсов
dSig = dSignal(tfield, dlength, fs, btact, dData); % обращение функции генерации кадра десятичных прямоугольных импульсов
[Amp, Phi, cNums] = mData(dData, M); % обращение к функции вычисления амплитуд и фаз модуляции
mSig = mSignal(tfield, dlength, fs, btact, Amp, Phi, fm); % обращение к функции генерации радиосигнала
end
В данном примере представлена 64-позиционная модуляция (6 бит на 1 символ). В моменте изображено число 25 в десятичном виде, 011001 в двоичном виде, а также комплексной число -0.46291+0.77152i:
Комплексная плоскость: