- Added utilities for frequency planning

- Changed freq plane to: Fs 4096, int/dec 8X, Mixers 768
This commit is contained in:
canisio
2026-03-27 12:50:10 -03:00
parent d5bbdfb435
commit 584db6233c
22 changed files with 838 additions and 0 deletions

301
utilities/rxspectrum.m Normal file
View File

@@ -0,0 +1,301 @@
function rxspectrum(scenario, fc, bw, fs, fshift, L)
if( nargin == 0)
fprintf('Use this function to plot your Receive spectrum\n');
fprintf('\n');
fprintf('First argument is to run 8 example scenarios.\n');
fprintf('rxpsectrum(1) or rxspectrum(2)...to plot and study various scenarios\n');
fprintf('\n');
fprintf('For custom numbers function can be called as follows\n');
fprintf('rxspectrum([], center frequency, data bandwidth, sampling frequency,shift or carrier frequency, x-axis plotting limit(optional arugment)\n');
elseif (nargin == 1)
%% System Parameters
sys = [];
sys.scenario = scenario;
switch sys.scenario
case 1
% Good Scenario. Nyquist sampling theorem.
%
% The sampling rate of 4 GHz is high enough to satisfy Nyquist sampling
% theorem.
%
% Use Nyquist Zone 1.
sys.fc = 1e9;
sys.bw = 300e6;
sys.fs = 4e9;
sys.fshift = -1e9;
L = 7;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 2
% Good Scenario. Bandpass sampling theorem.
%
% The sampling rate of 3 GHz is not high enough to satisfy Nyquist sampling
% theorem but it is one of the good sampling rates from bandpass sampling
% theorem.
%
% Use Nyquist Zone 2.
sys.fc = 3e9;
sys.bw = 300e6;
sys.fs = 4e9;
sys.fshift = 1e9;
L = 7;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 3
% Bad Scenario.
%
% Sampling rate does not satisfy Nyquist nor bandpass sampling theorem.
%
% Spectrum overlaps (completely or partially).
sys.fc = 3e9;
sys.bw = 300e6;
sys.fs = 2.4e9; % Complete Overlap
% sys.fs = 5.8e9; % Partial Overlap
sys.fshift = -0.6e9;
L = 10;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 4
% Bad Scenario.
%
% Sampling rate satisifies bandpass sampling theorem but spectra touch each
% other.
%
% Unless we have an ideal brick wall lowpass filter, we cannot recover the
% signal at 3 GHz.
sys.fc = 3e9;
sys.bw = 300e6;
sys.fs = 5.7e9;
sys.fshift = 2.7e9;
L = 10;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 5
% Solution to scenario 4. Spectra no longer touch either other.
%
% But we cannot use Xilinx hard IP decimate-by-2.
sys.fc = 3e9;
sys.bw = 300e6;
sys.fs = 3.4e9;
sys.fshift = 0.4e9;
L = 8;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 6
% Solution to scenario 5. Spectra no longer touch either other and we can
% use Xilinx hard IP decimate-by-2.
sys.fc = 3e9;
sys.bw = 300e6;
sys.fs = 4e9;
sys.fshift = 1e9;
L = 8;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 7
% Same problem even with Nyquist sampling theorem.
sys.fc = 1.5e9;
sys.bw = 300e6;
sys.fs = 4e9;
sys.fshift = -1.5e9;
L = 7;
sys.xlim = [-L L];
sys.xticks = -L : L;
case 8
sys.fc = 1.5e9;
sys.bw = 300e6;
sys.fs = 2e9;
sys.fshift = -0.5e9;
L = 7;
sys.xlim = [-L L];
sys.xticks = -L : L;
otherwise
error('Invalid sys.scenario');
end % switch
end %if(nargin == 1)
if (nargin == 5)
%% System Parameters
sys = [];
sys.scenario = scenario;
sys.fc = fc;
sys.bw = bw;
sys.fs = fs;
sys.fshift = fshift;
L = 7;
sys.xlim = [-L L];
sys.xticks = -L : L;
end
if (nargin == 6)
%% System Parameters
sys = [];
sys.scenario = scenario;
sys.fc = fc;
sys.bw = bw;
sys.fs = fs;
sys.fshift = fshift;
sys.xlim = [-L L];
sys.xticks = -L : L;
end
sys.xunit = 'GHz';
%%
if isempty(findobj('Number', sys.scenario))
figure(sys.scenario)
set(gcf, 'Position', [27 82 1180 638])
else
figure(sys.scenario)
clf
end
%%
Nsubplots = 5;
subplot(Nsubplots, 1, 1);
xlim(sys.xlim);
xticks(sys.xticks);
set(gca, 'Position', [0.04 0.8720 0.9277 0.09])
plotspectrum('asym', sys.fc, sys.bw, 'r', sys.xunit);
plotspectrum('asymflip', -sys.fc, sys.bw, 'r', sys.xunit);
title(sprintf('Analog Bandpass Signal (Center = %.2f GHz. BW = %d MHz.)', ...
sys.fc/1e9, sys.bw/1e6), 'FontSize', 12);
plotannotations(sys.fs, 1);
set(get(gca, 'XAxis'), 'FontSize', 11);
%%
subplot(Nsubplots, 1, 2);
xlim(sys.xlim);
xticks(sys.xticks);
set(gca, 'Position', [0.04 0.6720 0.9277 0.09])
title(sprintf('Sampling Images (Towards +ve Frequencies). Fs = %.2f GHz.', ...
sys.fs/1e9), 'FontSize', 12);
for n = 1:8
f1 = sys.fc + n*sys.fs;
f2 = -sys.fc + (n*sys.fs);
plotspectrum('asym', f1, sys.bw, 'b', sys.xunit);
plotspectrum('asymflip', f2, sys.bw, 'b', sys.xunit);
end
set(get(gca, 'XAxis'), 'FontSize', 11);
%%
subplot(Nsubplots, 1, 3);
xlim(sys.xlim);
xticks(sys.xticks);
set(gca, 'Position', [0.04 0.4720 0.9277 0.09])
title(sprintf('Sampling Images (Towards -ve Frequencies). Fs = %.2f GHz.', ...
sys.fs/1e9), 'FontSize', 12);
for n = -1:-1:-8
f1 = sys.fc + n*sys.fs;
f2 = -sys.fc + (n*sys.fs);
plotspectrum('asym', f1, sys.bw, 'c', sys.xunit);
plotspectrum('asymflip', f2, sys.bw, 'c', sys.xunit);
end
set(get(gca, 'XAxis'), 'FontSize', 11);
%%
subplot(Nsubplots, 1, 4);
xlim(sys.xlim);
xticks(sys.xticks);
set(gca, 'Position', [0.04 0.2720 0.9277 0.09])
title(sprintf('Real Digital Signal (Fs = %.2f GHz. BW %d MHz.)', ...
sys.fs/1e9, sys.bw/1e6), 'FontSize', 12)
n = -8:8;
f1 = sys.fc + n*sys.fs;
f2 = -sys.fc + (n*sys.fs);
plotspectrum('asym', f1, sys.bw, 'r', sys.xunit);
plotspectrum('asymflip', f2, sys.bw, 'r', sys.xunit);
plotannotations(sys.fs, 0);
set(get(gca, 'XAxis'), 'FontSize', 11);
%%
subplot(Nsubplots, 1, 5);
xlim(sys.xlim);
xticks(sys.xticks);
set(gca, 'Position', [0.04 0.0720 0.9277 0.09])
title(sprintf(['Complex Baseband Signal (Fs = %.2f GHz. BW %d MHz. ', ...
'fshift = %.2f GHz)'], sys.fs/1e9, sys.bw/1e6, sys.fshift/1e9), ...
'FontSize', 12);
f1 = f1 + sys.fshift;
f2 = f2 + sys.fshift;
plotspectrum('asym', f1, sys.bw, 'r', sys.xunit);
plotspectrum('asymflip', f2, sys.bw, 'r', sys.xunit);
plotannotations(sys.fs, 0);
set(get(gca, 'XAxis'), 'FontSize', 11);
Fs = sys.fs / 1e9;
x = [-Fs/2, -Fs/4, -Fs/4, Fs/4, Fs/4, Fs/2];
y = [0.25, 0.25, 0.75, 0.75, 0.25, 0.25];
hold on
plot(x, y, 'k--', 'LineWidth', 2)
end
% ------------------------------------------------------------------------------
% Helper Functions
% ------------------------------------------------------------------------------
function plotannotations(fs, zone)
%% Plot DC.
xline(0, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
y = 0.9;
addtext1(0, y, '0')
%% Plot fs/2.
xline(fs/2/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
xline(-fs/2/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
addtext1(0 + fs/2/1e9, y, 'Fs/2')
addtext1(0 - fs/2/1e9, y, '-Fs/2')
%% Plot fs.
xline(fs/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
xline(-fs/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
addtext1(0 + fs/1e9, y, 'Fs')
addtext1(0 - fs/1e9, y, '-Fs')
%% Plot 3*fs/2.
xline(fs*1.5/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
xline(-fs*1.5/1e9, 'LineWidth', 3, 'Color', 'g', 'LineStyle', '--')
addtext1(0 + 1.5*fs/1e9, y, '3*Fs/2')
addtext1(0 - 1.5*fs/1e9, y, '-3*Fs/2')
% %% Plot ...
% ntext4(0 + 1.6*fs/1e9, 0.6, '...', 'FontSize', 30, 'FontWeight', 'bold');
% ntext4(0 - 1.7*fs/1e9, 0.6, '...', 'FontSize', 30, 'FontWeight', 'bold');
% %%
% if zone == 1
% addtext2(0.7, 0.65, {'Nyquist', 'Zone 1'})
% addtext2(0.7 + fs/2/1e9, 0.65, {'Nyquist', 'Zone 2'})
% % addtext2(0.7 + fs/1e9, 0.65, {'Nyquist', 'Zone 3'})
% end
end
function addtext1(x, y, t)
h = ntext4(x, y, t);
h.FontSize = 15;
h.FontWeight = 'bold';
h.HorizontalAlignment = 'center';
end
function addtext2(x, y, t)
h = ntext4(x, y, t);
h.FontSize = 15;
h.FontWeight = 'bold';
h.Color = [0 0.4470 0.7410];
h.HorizontalAlignment = 'center';
end