Сообщество Engee

Квадратурная амплитудная модуляция

Автор
avatar-artpgchartpgch
Notebook

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

Состоит из основного скрипта QAM_live.m:

In [ ]:
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
UndefVarError: `clear` not defined

Функция mSignal.m:

In [ ]:
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:

In [ ]:
function [Amp, Phi, cNums] = mData(dData, M) % функция вычисления амплитуд и фаз модуляции
    cNums = qammod(dData, M, 'UnitAveragePower', true); % вычисление комплексных чисел модуляции
    Amp = abs(cNums); % вычисление амплитуд
    Phi = angle(cNums); % вычисление фаз
    end

Функция dSignal.m:

In [ ]:
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

In [ ]:
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:

In [ ]:
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:

In [ ]:
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:qam_example.png

Комплексная плоскость:qam_plane.png