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

Commit 54df04bf authored by Martin Hudlicka's avatar Martin Hudlicka
Browse files

New MATLAB files

parent 8d6aa005
function F_Save_Results_TimeDomainAlignment(EVMrms_pct, tau0, G_OPT)
% This function saves the outputs from the Alternate TAA case
% 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');
Quantity = [{'EVM_rms%', 'Optimal Delay (ns)','G_OPT Amp', 'G_OPT Phase (deg)'}];
Value = [EVMrms_pct; tau0; G_OPTamp; G_OPTphase];
fprintf(fid, '%s \t %s\r\n', 'Quantity', 'Value');
for n =1:length(Value)
fprintf(fid, '%-23s %1.15g\r\n', Quantity{n}, Value(n));
fprintf(fid,'%s\n','Quantity Definition:');
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');
Extra_Quantity = [{'DC Value','Total DC Phase (deg)', 'Delay Tolerance (ns)','EVM_peak%'}];
Extra_Value = [structGlobal.rxSigAve; structGlobal.rxTotalAngle; structGlobal.delayTolerance; structGlobal.EVMpeak_pct];
fprintf(fid, '%s \t\t %s\r\n', 'Extra Quantity', 'Value');
for n =1:length(Extra_Value)
fprintf(fid, '%-23s %1.15g\r\n', Extra_Quantity{n}, Extra_Value(n));
fprintf(fid,'%s\n','Extra Quantity Definition:');
fprintf(fid,'%s\n','> DC Value = Received signal average value');
fprintf(fid,'%s\n','> Total DC Phase (deg) = Total DC phase as sum of coarse and fine xcorr alignment to be applied to received waveform rxSig before symbol sampling/calculation');
fprintf(fid,'%s\n','> Delay Tolerance (ns) = Absolute size of fine time grid used in xcorr');
fprintf(fid,'%s\n','> EVM_peak% = Peak EVM as a percentage');
function F_TimeDomainAlignment(refSigFreq,rxSigFreq,refSig,refConst,params)
% This function implements the Baseline EVM Algorithm with Time-Domain
% Alignment as detailed in Section 9.1.1 of the P1765 document.
% Replace the function call on line 62 in the main program with the following:
% F_UserInputs_TimeDomainAlignment()
% Replace lines 99 through 114 in the main program
% with the following function call to perform EVM calculation
% using time-domain alignment:
% F_TimeDomainAlignment(refSigFreq,rxSigFreq,refSig,refConst,params);
% Make sure that the main program uses all these functions in order
% to calculate EVM using the time-domain alignment method
% F_UserInputs_TimeDomainAlignment
% F_Basic_Communication_Parameters
% F_Apply_RX_Filter
% F_freqSqrtRaisedCosine
% F_TimeDomainAlignment
% F_calculateOptimal_TimeDomainAlignment
% F_Sample_Normalize_EVM
% F_Plot_Constellation_Diagram
% F_Save_Results_TimeDomainAlignment
% Main program: IEEE_P1765_Baseline_EVM_Algorithm
% Inputs:
% refSig: Time-Domain Waveform from Ideal Constellation
% refSigFreq: Frequency-Domain version of refSig
% rxSigFreq: Matched Filtered Baseband Reference Waveform in Frequency Domain
% refConst: Reference Constellation Supplied with this Package
% params: Structure containing all the basic communication parameters
% 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
%% Optimal Time Delay and Normalization Algorithm for Waveform Samples (Crosscorrelation)
[tau0, rxSig] = F_calculateOptimal_TimeDomainAlignment(refSigFreq,rxSigFreq,refConst,params);
%% Perform Symbol Sampling, Complex Gain Normalization and Calculate EVM
[EVMrms_pct,G_OPT] = F_Sample_Normalize_EVM(refSig,rxSig,params);
%% Save Both AlternateTAA and Extra Results in a Single File
F_Save_Results_TimeDomainAlignment(EVMrms_pct, tau0, G_OPT);
\ No newline at end of file
function F_UserInputs_TimeDomainAlignment()
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('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');
[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?'},...
if filename_choice == 1
structGlobal.filename_results = strcat('EVM_xcorr_',structGlobal.SISmn);
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};
%% 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?'},...
if filename_choice == 1
structGlobal.filename_constellation = strcat('Constellation_xcorr_',structGlobal.SISmn);
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};
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]);
function [tau0, rxSig] = F_calculateOptimal_TimeDomainAlignment(refSigFreq,rxSigFreq,refConst,params)
% Function to calculate EVM receiver optimal time delay and
% complex normalization based on alternate crosscorrelation based TAA.
% See Section 9.1.1 Baseline EVM Algorithm with Alternate Time Alignment
% Inputs:
% refSigFreq: Ideal signal calculated from 64-QAM ideal constellation in frequency domain
% rxSigFreq: Match filtered baseband version of measured signal in frequency domain
% refConst: Reference Constellation Supplied with the package
% params: Structure containing the basic communication parameters
% Outputs:
% tau0: Optimal time delay to be applied in phase before same sampling/calculation
% rxSig: Optimal time delayed/waveform normalized version of measured signal
% Extra outputs:
% delayTolerance: Absolute size of fine time grid used in xcorr
% rxTotalAngle: Total DC phase as sum of coarse and fine xcorr alignment to be applied to received waveform rxSig before symbol sampling/calculation
global structGlobal
% Normalize Average Power in Received Signal to Match the Reference Signal (Optional)
% > Used for legacy RRC filter case only when applying alternative xcorr method
% > Not used for Joost RRC filter case for either time alignment algorithm alternatives
% refSigPower = dot(refSig,refSig)/numSamp;
% rxSigPower = dot(rxSig,rxSig)/numSamp;
% refrx_pwr_ratio = refSigPower/rxSigPower;
% rxSig = rxSig*sqrt(refrx_pwr_ratio);
% First Round: Determine Sample Delay and Phase Offset for Original Sampling Grid
rxSig = ifft(rxSigFreq); % Added by Paritosh on 6/15/2021
refSig = ifft(refSigFreq); % Added by Paritosh on 6/15/2021
ccorrFreq1 = rxSigFreq .* conj(refSigFreq);
ccorr1 = ifft(ccorrFreq1);
[m1, ind1] = max(abs(ccorr1));
ccorrmax1 = ccorr1(ind1);
rxDelay1 = ind1 - 1;
rxDelayTime1 = rxDelay1/params.fsamp;
rxAngle1 = angle(ccorrmax1)*180/pi;
rxSig = (circshift(rxSig.',-rxDelay1)).';
rxSig = rxSig*exp(1i*pi*-rxAngle1/180);
% Second Round: Determine Vernier Sample Delay and Phase Offset
resfac = 1000; % Chosen refinement scale of original dt1 sampling grid [to 50 femtosec (fs) spacing in this case]
% structGlobal added by Paritosh on 6/15/2021:
structGlobal.delayTolerance = 1/(params.fsamp*1000); % Absolute tolerance on total delay (+/– 50 fs = 0.1% dt1 in this case)
sigSize = length(refSig); % Also equals length(rxSig)
refSig_us = zeros(1,sigSize*resfac);
refSig_us(1:params.numSampSym*resfac:sigSize*resfac) = refConst(1:params.numSym); % Creating ideal fine version of refSig
rxSig_us = interpft(rxSig,resfac*sigSize);
refSigFreq_us = fft(refSig_us);
rxSigFreq_us = fft(rxSig_us);
ccorrFreq2 = rxSigFreq_us .* conj(refSigFreq_us);
ccorr2 = ifft(ccorrFreq2);
[m2, ind2] = max(abs(ccorr2));
ccorrmax2 = ccorr2(ind2);
rxDelay2 = ind2 - 1;
rxDelayTime2 = rxDelay2/(params.fsamp*resfac);
if rxDelayTime2 > params.dt1 % Accounting for negative fine delay if needed
rxDelayTime2 = rxDelayTime2 - params.tinterval;
rxDelay2 = rxDelay2 - params.numSamp*resfac;
rxTotalDelayTime = rxDelayTime1 + rxDelayTime2; % Time delay down to +/– 50 fs
rxAngle2 = angle(ccorrmax2)*180/pi;
structGlobal.rxTotalAngle = rxAngle1 + rxAngle2; % Total DC phase offset (degrees); % structGlobal added by Paritosh on 6/15/2021
rxSig_us = (circshift(rxSig_us.',-rxDelay2)).';
rxSig_us = rxSig_us*exp(1i*pi*-rxAngle2/180);
rxSig = rxSig_us(1:resfac:params.numSamp*resfac); % Downsampling back to numSamp = sigSize
tau0 = rxTotalDelayTime; % Added by Paritosh on 6/15/2021
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment