IEEE.org     |     IEEE Xplore Digital Library     |     IEEE Standards     |     IEEE Spectrum     |     More Sites

Commit f2ae91f9 authored by Martin Hudlicka's avatar Martin Hudlicka
Browse files

Updated MATLAB files

parent c9d842b5
function rxSigFreq = F_Apply_RX_Filter(distSigFreq,params)
% This function calculates the transfer function (Hrrc) of the root raised
% cosine function in the frequency domain and applies it to the Baseband
% Reference Waveform. This is discussed in IEEE P1765 document Section
% 5.1.2.1 and Annex A.
%
% Inputs:
% distSigFreq: Baseband version of reference signal in frequency domain
% params: Structure containing all the basic communication parameters
%
% Outputs:
% rxSigFreq: The filtered spectrum in the frequency domain using the
% matched filter intended for the modulation type being used.
global structGlobal
% Calculate Root Raised Cosine Filter's Transfer Function in Frequency Domain
% Hrrc based on Joost's paper
Hrrc = F_freqSqrtRaisedCosine(1/params.fsym, params.rolloff, 1/params.fsamp, params.numseg*length(params.t1));
% To match the length of the Hrrc vector with the other previously defined vectors
Hrrc = [zeros(round((params.numSamp-length(Hrrc))/2),1);Hrrc;zeros(round((params.numSamp-length(Hrrc))/2),1)];
Hrrc = Hrrc(1:length(Hrrc) - 1); % Removing endpoint to match with numSamp
Hrrc = circshift(Hrrc,length(Hrrc)/2); % For baseband
Hrrc = transpose(Hrrc)/max(Hrrc); % Ensuring unit gain in passband
% Apply Ideal Matched Filtering to Baseband Reference Waveform
rxSigFreq = distSigFreq.*Hrrc; % Ideal matched filtering in frequency domain
rxSig = ifft(rxSigFreq); % Transform match-filtered Baseband Reference Waveform to the time domain
structGlobal.rxSigAve = abs(sum(rxSig)/length(distSigFreq)); % Signal Average Value (should be small)
end
\ No newline at end of file
function params = F_Basic_Communication_Parameters()
% This function defines the basic communication parameters for the P1765
% Baseline EVM Algorithm code including the root raised cosine filter
% params is the structure which will store all the defined parameters
params.QAM = 64; % N-QAM
params.N = abs(sqrt(params.QAM)); % N-QAM
params.fcarr = 4; % RF carrier frequency in GHz
params.fsamp = 20; % Sample rate in GSsamples/s
params.numSym = 511; % Number of symbols
params.fsym = 1; % Symbol rate in GSymbols/s
params.numSampSym = round(params.fsamp / params.fsym); % Number of samples/symbol
params.numSamp = params.numSym * params.numSampSym; % Number of time samples
params.dt1 = 1/params.fsamp; % Time sample spacing (ns)
params.t1 = (0:params.numSamp-1) * params.dt1; % Time sampling grid (ns)
params.tinterval = params.dt1*params.numSamp; % Time length of grid (ns)
params.df1 = params.fsamp/params.numSamp; % Frequency grid spacing (GHz)
params.f1 = (-(params.numSamp/2):(params.numSamp/2)-1) * params.df1; % Standard frequency grid (GHz)
params.finterval = params.df1*params.numSamp; % Frequency length of grid (GHz) = time-domain record DFT BW
params.rolloff = 0.35; % Filter rolloff
params.span = params.numSym; % Filter span (symbols)
params.sps = round(params.fsamp/params.fsym); % Samples per symbol
end
function F_Plot_Constellation_Diagram(refSym,rxSym,params)
% This function plots the reference and received signal constellation
% diagrams and saves it in the evm_results_folder which was taken as
% input from the user in F_UserInputs().
% The constellation diagram is saved with the filename which was taken as
% input from the user in F_UserInputs().
% This version has been tested on several monitors and resolutions to
% ensure that it plots reliable constellation diagrams without any adjustment.
%
% Inputs:
% refSym: Reference Symbols
% rxSym: Received Symbols
% params: Structure containing all the basic communication parameters
global structGlobal
% Create figure
figure1 = figure('NumberTitle','off');
% Create axes
axes1 = axes('Parent',figure1);
hold(axes1,'on');
% Create reference signal constellation plot
X1 = real(refSym);
Y1 = imag(refSym);
plot(X1,Y1,'DisplayName','Reference Symbols','MarkerSize',8,'Marker','o','LineWidth',1,'LineStyle','none','Color',[0 0 1]);
% Create receiver signal constellation plot
X2 = real(rxSym);
Y2 = imag(rxSym);
plot(X2,Y2,'DisplayName','Received Symbols','MarkerSize',8,'Marker','x','LineWidth',1,'LineStyle','none','Color',[1 0 0]);
% Create xlabel
xlabel('In-Phase (I)','HorizontalAlignment','center','FontSize',24);
% Create ylabel
ylabel('Quadrature (Q)','HorizontalAlignment','center','FontSize',24);
% Create title
stri = strcat(structGlobal.SISmn,' 64-QAM Constellation');
title(stri,'VerticalAlignment','bottom','HorizontalAlignment','center','FontWeight','bold','FontSize',24);
% Create legend
legend1 = legend(axes1,'show');
% Placement of plot legend in MATLAB plot window
set(legend1,'Position',[0.60 0.02 0.35 0.08],'FontSize',14);
% Set the remaining axes/figure properties
axis square
box(axes1,'on');
set(axes1,'XLim',[-params.N params.N]);
set(axes1,'xtick',(-params.N:2:params.N));
set(axes1,'YLim',[-params.N params.N]);
set(axes1,'ytick',(-params.N:2:params.N));
set(axes1,'FontSize',24,'GridAlpha',1,'XGrid','on','YGrid','on');
% Move the plot box up to accomodate the legend
current_position = get(gca, 'Position');
set(gca, 'Position', current_position + [0, +0.02, 0, +0.02]);
% Set the actual height and width of the box
width = 5;
height = 5;
set(gcf, 'Units', 'Inches', 'Position', [1, 1, width+1, height+1], 'PaperUnits', 'Inches', 'PaperSize', [width, height])
set(gca, 'Fontsize', 14);
% Saving figure as graphic file in current directory (plot must still be present in MATLAB plot window)
stri_fig = fullfile(structGlobal.evm_results_folder,strcat(structGlobal.filename_constellation,'.jpg'));
set(figure1,'PaperPositionMode','auto');
print(figure1,stri_fig,'-djpeg','-r300');
end
\ No newline at end of file
function [EVMrms_pct,G_OPT] = F_Sample_Normalize_EVM(refSig,rxSig,params)
% This function performs symbol sampling, determines the complex gain
% G_OPT and normalization and calculates EVM as mentioned in the IEEE
% P1765 document in Sections 5.1.2.3, 5.1.2.4, and 5.1.2.5 respectively.
%
% Inputs:
% refSig: Time-domain waveform from 64-QAM ideal constellation
% rxSig: Optimal time-delayed and waveform normalized version of XOut
% where XOut = fft shifted version of match-filtered reference signal spectrum
% params: Structure containing all the basic communication parameters
%
% Outputs:
% EVMrms_pct: Baseline rms EVM in percent
% G_OPT: Optimal complex gain/ normalization factor for symbol samples
% G_OPTamp: abs(G_OPT)
% G_OPTphase: angle(G_OPT) in degrees
%
% Extra outputs:
% EVMpeak_pct: Baseline peak EVM in percent
global structGlobal
% Sampling symbols (Section 5.1.2.3) from optimally aligned/normalized waveforms
refSym = refSig(1:params.numSampSym:params.numSamp);
rxSym = rxSig(1:params.numSampSym:params.numSamp);
% Optimal Normalization (Section 5.1.2.4) for Symbol Samples
rxSymPower = dot(rxSym,rxSym);
rxrefSymCorr = dot(rxSym,refSym);
G_OPT = rxrefSymCorr/rxSymPower;
rxSym = G_OPT*rxSym; % Optimal symbol normalization of received signal constellation
% RMS EVM Calculation (Section 5.1.2.5)
EV = rxSym - refSym;
EVMrms_pct = 100*sqrt(dot(EV,EV)/dot(refSym,refSym))
% Peak EVM Calculation
EVMp = max(abs(EV));
refSymPower = dot(refSym,refSym)/params.numSym;
structGlobal.EVMpeak_pct = 100*EVMp/sqrt(refSymPower);
F_Plot_Constellation_Diagram(refSym,rxSym,params);
end
function F_Save_Results(EVMrms_pct, tau0, G_OPT)
% This function saves the IEEE P1765 Baseline EVM Algorithm's official outputs
% EVMrms_pct: Baseline rms EVM in percent
% tau0: Optimal time delay before same sampling/calculation
% G_OPT: Optimal complex gain / normalization factor for symbol samples
% (saved as absolute and phase parts)
%
% It also saves the extra outputs in the same file for users
% rxSigAve: Received signal average value
% optTolerance: Absolute tolerance determined for iterative delay calculation convergence (ns)
% iterindx: Number of iterations for optimal delay loop convergence (= 10000 if convergence fails)
% G_0: Optimal complex gain to be applied before symbol sampling/EVM calculation saved as
% G_0amp: abs(G_0)
% G_0phase: angle(G_0) in degrees
% EVMpeak_pct: Peak EVM (in %)
global structGlobal
G_OPTamp = abs(G_OPT);
G_OPTphase = angle(G_OPT)*180/pi; % degrees
fname = strcat(structGlobal.filename_results,'.txt');
fid = fopen(fullfile(structGlobal.evm_results_folder,fname),'w');
fprintf(fid,'\n\n');
fprintf(fid,'%s\n','OFFICIAL RESULTS');
Official_Quantity = [{'EVM_rms%', 'Optimal Delay (ns)','G_OPT Amp', 'G_OPT Phase (deg)'}];
Official_Value = [EVMrms_pct; tau0; G_OPTamp; G_OPTphase];
fprintf(fid,'%s\n','------------------------------------------------');
fprintf(fid, '%s \t %s\r\n', 'Official Quantity', 'Value');
fprintf(fid,'%s\n','------------------------------------------------');
for n =1:length(Official_Value)
fprintf(fid, '%-23s %1.15g\r\n', Official_Quantity{n}, Official_Value(n));
end
fprintf(fid,'\n\n');
fprintf(fid,'%s\n','Official Quantity Definition:');
fprintf(fid,'%s\n','-----------------------------');
fprintf(fid,'%s\n','> EVM_rms% = RMS EVM as a percentage');
fprintf(fid,'%s\n','> Optimal Delay (ns) = Optimal time delay to be applied in the phase of XOut before symbol sampling/EVM calculation');
fprintf(fid,'%s\n',' where XOut is fftshifted match filtered baseband version of reference signal in frequency domain');
fprintf(fid,'%s\n','> G_OPT Amp = Symbol Norm Amp = abs(G_OPT), where G_OPT is optimal complex gain/normalization factor for symbol samples');
fprintf(fid,'%s\n','> G_OPT Phase = Symbol Norm Phase = angle(G_OPT) in degrees');
fprintf(fid,'\n\n');
Extra_Quantity = [{'DC Value', 'Delay Tolerance (ns)', 'Delay Iterations', 'Wvfrm Gain Amp', 'Wvfrm Gain Phase (deg)','EVM_peak%'}];
Extra_Value = [structGlobal.rxSigAve; structGlobal.optTolerance; structGlobal.iterindx; structGlobal.G_0amp; structGlobal.G_0phase; structGlobal.EVMpeak_pct];
fprintf(fid,'%s\n','------------------------------------------------');
fprintf(fid, '%s \t\t %s\r\n', 'Extra Quantity', 'Value');
fprintf(fid,'%s\n','------------------------------------------------');
for n =1:length(Extra_Value)
fprintf(fid, '%-23s %1.15g\r\n', Extra_Quantity{n}, Extra_Value(n));
end
fprintf(fid,'\n\n');
fprintf(fid,'%s\n','Extra Quantity Definition:');
fprintf(fid,'%s\n','--------------------------');
fprintf(fid,'%s\n','> DC Value = Received signal average value');
fprintf(fid,'%s\n','> Delay Tolerance (ns) = Absolute tolerance determined for iterative delay calculation convergence');
fprintf(fid,'%s\n','> Delay Iterations = Number of iterations for optimal delay loop convergence (= 10000 if convergence fails');
fprintf(fid,'%s\n','> Wvfrm Gain Amp = abs(G_0), where G_0 = Optimal complex gain is applied to XOut before symbol sampling/EVM calculation');
fprintf(fid,'%s\n',' where XOut = fft shifted version of match-filtered reference signal spectrum');
fprintf(fid,'%s\n','> Wvfrm Gain Phase = angle(G_0) in degrees');
fprintf(fid,'%s\n','> EVM_peak% = Peak EVM as a percentage');
fclose(fid);
end
function F_UserInputs()
global structGlobal
% Select the folder where these programs reside
uiwait(msgbox({'In order for the program to run correctly,'...
'the parent program folder needs to be selected'...
'as the working directory in the next window.'}));
pause(0.001);
program_folder = uigetdir(pwd,'Select the folder where these programs reside');
cd(program_folder);
% Select a folder to save the EVM results based on user input');
structGlobal.evm_results_folder = uigetdir(pwd,'Select a folder to save EVM calculation results');
% Read in ASCII Baseband Reference Waveform file
disp('__________________________________________________________________');
disp('The user’s selection will be based on the P1765 Signal Impairment Sets');
disp('defined in Section 6.1 and Annex A of IEEE P1765');
disp('Read in ASCII Baseband Reference Waveform file');
disp('__________________________________________________________________');
[filename,path] = uigetfile([pwd,'\P1765 Reference Waveforms\Baseband\Waveform_SIS01_BB.txt'],'Select the signal text file');
structGlobal.file = fullfile(path,filename);
% Find the starting index of SIS in the filename for default filenaming convention
% SIS = Signal Impairment Sets.
% The filenames have SIS followed by two digits from 01 through 21
SISmn_index_start = strfind(filename,'SIS');
SISmn_index_end = SISmn_index_start + 4;
% Extract the SISmn from the waveform file
structGlobal.SISmn = filename(SISmn_index_start:SISmn_index_end);
%% Enter filename to use for saving results or choose to use the default name
list = {'DEFAULT filename','CUSTOM filename'};
[filename_choice,~] = listdlg('PromptString',...
{'Would you like to set a default or custom filename','for EVM results?'},...
'SelectionMode','single','ListSize',[250,100],'ListString',list);
if filename_choice == 1
structGlobal.filename_results = strcat('EVM_',structGlobal.SISmn);
else
prompt = {'Enter filename (without extension):'};
dlgtitle = 'Custom filename';
dims = [1 50];
definput = {'evm_results_file'};
response = inputdlg(prompt,dlgtitle,dims,definput);
structGlobal.filename_results = response{1};
end
%% Enter filename to use for saving constellation diagram or choose to use the default name
list = {'DEFAULT filename','CUSTOM filename'};
[filename_choice,~] = listdlg('PromptString',...
{'Would you like to set a default or custom filename','for constellation diagram?'},...
'SelectionMode','single','ListSize',[250,100],'ListString',list);
if filename_choice == 1
structGlobal.filename_constellation = strcat('Constellation_',structGlobal.SISmn);
else
prompt = {'Enter filename (without extension):'};
dlgtitle = 'Custom filename';
dims = [1 50];
definput = {'constellation_diagram_file'};
response = inputdlg(prompt,dlgtitle,dims,definput);
structGlobal.filename_constellation = response{1};
end
disp(['EVM results will be saved in the following folder: ',structGlobal.evm_results_folder]);
disp(['Filename for the storing the EVM results: ',structGlobal.filename_results]);
disp(['Filename for the saving the constellation diagram: ',structGlobal.filename_constellation]);
disp('__________________________________________________________________');
end
\ No newline at end of file
function [tau0, XOutopt] = F_calculateOptimal(XIn, XOut, Ts)
% Version: 8.27.2020
%
%
% Function to calculate baseline EVM receiver optimal time delay and
% complex normalization based on all time samples (carried out in frequency domain).
% See Section 5.1.2.2 Optimal Time Alignment of Waveform 2 to Waveform 1
% and Removal of Constant Phase Offset, and Annex B of IEEE P1765 document.
%
% Inputs:
% XIn: Discrete uniform spectra of input waveform with frequency spacing 1/Ts
% XOut: Same but for output waveform
% Ts: Time duration (ns) of input/output time-domain waveforms corresponding to XIn and XOut
%
% Outputs:
% tau0: Optimal time delay to be applied in the phase of XOut before same sampling/calculation
% XOutopt: XOut after optimal time-shifting/normalization
%
% Extra outputs:
% G_0: Optimal complex gain to be applied to XOut before symbol sampling/EVM calculation
% G_0amp: abs(G_0)
% G_0phase: angle(G_0)*180/pi
% optTolerance: Absolute tolerance determined for iterative delay calculation convergence
% iterindx: Number of iterations for optimal delay loop convergence (= 10000 if convergence fails)
global structGlobal
K = length(XIn);
% K is the number of sampling intervals in XIn (which must equal that in XOut)
% and also equal to number of time sampling points in Xin and Xout minus one
% (last end-sample identified with first one due to periodicity)
P0 = conj(XIn).*XOut;
P1 = P0.*(0:K - 1);
P2 = P1.*(0:K - 1);
domega = 2*pi/Ts; % Angular frequency spacing of XIn and XOut
dt = Ts/K; % Time sampling interval
% First coarse alignment based on cross-correlation
% See Section 5.1.2.2(1) of IEEE P1765 document: Coarse time alignment
R = abs(ifft(P0));
[Rmax, Icoarse] = max(R);
T0init = (Icoarse - 1)*dt; % Coarse delay (within one time sampling interval dt)
% Fine time alignment
% See Section 5.1.2.2(2) of IEEE P1765 document: Fine time alignment
% Parabolic fit refinement
if Icoarse ==1
Rleft = R(K); Rright = R(2);
elseif Icoarse == K
Rleft = R(K - 1); Rright = R(1);
else
Rleft = R(Icoarse - 1); Rright = R(Icoarse + 1);
end
T = T0init + (dt/2)*(Rleft - Rright)/(Rleft + Rright - 2*Rmax); % Parabolic fit refined delay estimate
% Iterative optimal refinement
structGlobal.optTolerance = 10*eps(T); % MATLAB eps function giving distance from T to nearest double floating
% point number (margin factor of 10 added to reach usable tolerance)
domegaT = domega*T;
domegadT = 1;
domegadTtol = domega*structGlobal.optTolerance; % Iterative tolerance for domegaT
index = 1;
while (abs(domegadT) > domegadTtol) && (index < 10001) % Failsafe loop exit criteria
Mc = exp(-1i*(0:K - 1)*domegaT);
C0 = dot(Mc,P0);
C1 = dot(Mc,P1);
C2 = dot(Mc,P2);
num = imag(C1*conj(C0));
den = real(abs(C1)^2 - C2*conj(C0));
domegadT = num/den;
domegaT = domegaT + domegadT;
index = index + 1;
end
G_0 = dot(XOut,(XIn.*Mc))/dot(XOut,XOut); % Optimal complex gain, this variable is not used further per Section 5.1.2.2
tau0 = domegaT/domega; % Optimal time delay
XOutopt = G_0*(XOut.*conj(Mc)); % Optimal time delayed/normalized version of XOut
errvecopt = XIn - XOutopt; % Error vector of optimal alignment/normalization
errmin = dot(errvecopt,errvecopt); % Minimum error power between XIn and XOut
structGlobal.iterindx = index - 1; % Number of domegaT loop iterations (= 10000 if convergence fails)
structGlobal.G_0amp = abs(G_0);
structGlobal.G_0phase = angle(G_0)*180/pi;
end
\ No newline at end of file
function Hrrc = F_freqSqrtRaisedCosine(Tsym, alpha, deltaT, N)
% This function generates the frequency response of a root raised cosine
% filter using the definition in the following reference:
% M. Joost, "Theory of Root-Raised Cosine Filter," published online at
% www.michael-joost.de/rrcfilter.pdf
% See Section 5.2.1 of IEEE P1765 document: Filter the Baseband Signals
% INPUTS:
% Tsym: Symbol duration in ns, inverse of symbol rate
% alpha: Root raised cosine filter rolloff
% deltaT: Point spacing in ns, inverse of sample rate
% N: Total number of points
% OUTPUTS:
% Hrrc: Transfer function of the root-raised cosine filter
% The Hrrc is defined in three frequency ranges
% At lower frequencies, f < f1, constant spectrum
% For frequencies, f1 > f > f2, root raised cosine function
% At higher frequencies, f > f2, zero
% Calculate the frequencies f1 and f2:
f2 = ((1.0 + alpha) / 2.0) / double(Tsym); % Maximum filter frequency
f1 = ((1.0 - alpha) / 2.0) / double(Tsym); % Start of rolloff
deltaF = 1.0 / (double(N) * deltaT); % Frequency spacing
ns = floor(f2 / deltaF); % Set of frequencies in the passband of the filter
Ntotal = 1 + 2 * ns;
Hrrc = complex(zeros(Ntotal,1));
B = sqrt(Tsym);
% Create the filter values
k = 0;
for kFreq = -ns:ns
Freq = double(kFreq) * deltaF;
k = k + 1;
if abs(Freq) <= f1
Hrrc(k) = B;
elseif abs(Freq) <= f2
Hrrc(k) = (B / sqrt(2.0)) * sqrt(1.0 + cos(pi * (Tsym/alpha) * ((abs(Freq) - f1))));
end
end
end
\ No newline at end of file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IEEE P1765 baseline EVM receiver/calculation code (user distributable)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This code is implementing the IEEE P1765 Baseline EVM Algorithm as
% defined in Section 5.2 and Figure 5 of the P1765 document.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Authors:
% Christopher P. Silva - Original code Version 04.30.2021
% Paritosh Manurkar - Modularization of the code into a main program and subroutines Version 06.28.2021
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% > Define global structure (instead of global variables) and initialize extra output variables
% > Create a structure to save all the basic communication parameters
% > Define the root raised cosine (RRC) filter transfer function in frequency domain
% > Use the correct waveforms generated using the frequency domain RRC filter
% > Downconversion from RF to baseband is not a part of the P1765 Baseline EVM Algorithm
% > A function to perform downconversion has been supplied for pre-processing
% > Downsampling an oversampled signal is not a part of the P1765 Baseline EVM Algorithm
% > A function to perform downsampling has been supplied for pre-processing
% > Regenerate ideal reference constellation (Single Carrier)
% > Read in baseband ASCII time-domain waveform file
% > Time-domain waveform alignment and normalization
% > Symbol sampling and constellation normalization
% > EVM RMS/peak (in %) calculation
% > Automated plotting of ideal/processed signal constellation and saving plot graphic
% > Save the official and extra outputs and their descriptions in a text file:
% OFFICIAL OUTPUTS
% > RMS EVM (in %)
% > Optimal delay tau0 (ns)
% > Optimal complex gain/ normalization factor for symbol samples G_OPT
% >> G_OPTamp: abs(G_OPT)
% >> G_OPTphase: angle(G_OPT) in degrees
% EXTRA OUTPUTS
% > Received signal average value
% > Absolute tolerance determined for iterative delay calculation convergence (ns)
% > Number of iterations for optimal delay loop convergence (= 10000 if convergence fails)
% > Optimal complex gain G_0 to be applied before symbol sampling/EVM calculation
% >> G_0amp: abs(G_0)
% >> G_0phase: angle(G_0) in degrees
% > Peak EVM (in %)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear; close all; clc;
%% Define Global Structure and Initialize Variables
global structGlobal
structGlobal.rxSigAve = 0; % Received signal average value
structGlobal.optTolerance = 0; % Absolute tolerance (ns)
structGlobal.iterindx = 0; % Number of iterations for optimal delay loop convergence
structGlobal.G_0amp = 0; % Amplitude of optimal complex gain
structGlobal.G_0phase = 0; % Phase of optimal complex gain
structGlobal.EVMpeak_pct = 0; % Peak EVM (in %)
structGlobal.evm_results_folder = 'placeholder'; % Folder in which results will be saved
structGlobal.filename_results = 'placeholder'; % Base filename for saving results
structGlobal.filename_constellation = 'placeholder';% Base filename for saving constellation diagram
structGlobal.SISmn = 'placeholder'; % Extract impairment set information from waveform filename
%% User Inputs for Folder and Filename
F_UserInputs();
%% Define Basic Communication Parameters and save in structure params
params = F_Basic_Communication_Parameters();
%% Read in ASCII Baseband Reference Waveform File
distSig = transpose(dlmread(structGlobal.file));
sigSize = length(distSig);
params.numseg = sigSize/params.numSamp; % Integer number of consecutive waveform segments of basic length numSamp
if params.numseg > 1
params.numSamp = params.numseg*params.numSamp; % New numSamp = number of segments times old numSamp
params.numSym = params.numseg*params.numSym; % New numSym = number of segments times old numSym
params.df1a = params.fsamp/params.numSamp; % New frequency grid spacing (Hz)
params.f1a = [-(params.numSamp/2):(params.numSamp/2)-1] * params.df1a; % New frequency grid (Hz)
params.t1a = [0:params.numSamp-1] * params.dt1; % New time sampling grid (sec) — note dt1a = dt1
end
distSigFreq = fft(distSig);
bw_mod = (1 + params.rolloff)*params.fsym; % Modulation bandwidth (GHz)
%% Load the Reference Constellation Supplied with this Package
refConst = transpose(dlmread(fullfile(pwd,'Constellation _ Pulse Shaping Files','RefSymbolsConst.txt')));
refSym = repmat(refConst,1,params.numseg); % Edit to make numseg copies of basic symbol sequence
refConst = refSym;
%% Create Time-Domain Waveform from Ideal Constellation
refSig = zeros(1,params.numSamp);
refSig(1:params.numSampSym:params.numSamp) = refSym(1:params.numSym);
refSigFreq = fft(refSig);
%% Apply Ideal Matched Filtering to Baseband Reference Waveform
rxSigFreq = F_Apply_RX_Filter(distSigFreq,params);
%% Optimal Time Delay and Normalization Algorithm for Waveform Samples (Official)
% Shift zero-frequency component to center of spectrum for baseband signals
XIn = fftshift(refSigFreq);