updates of framework
- focus on AWG output power and lowpass characteristics
This commit is contained in:
@@ -28,8 +28,10 @@ classdef Electricalsignal < Signal
|
||||
|
||||
function pow = power(obj)
|
||||
|
||||
pow = mean( abs(obj.signal).^2 ) ;
|
||||
pow = pow2db(pow)+30; %dbm
|
||||
% Power of an electrical signal
|
||||
R = 50;
|
||||
pow = mean(abs(obj.signal).^2) / R; % Power in watts = V^2 / R
|
||||
pow = 10*log10(pow) + 30; % Power in dB +30 = dBm
|
||||
|
||||
end
|
||||
|
||||
@@ -47,6 +49,66 @@ classdef Electricalsignal < Signal
|
||||
|
||||
end
|
||||
|
||||
function obj = normalize(obj,options)
|
||||
|
||||
arguments
|
||||
obj Electricalsignal
|
||||
options.mode normalization_mode = normalization_mode.rms
|
||||
end
|
||||
|
||||
switch options.mode
|
||||
|
||||
case normalization_mode.milliwatt
|
||||
|
||||
curpow = sqrt(mean(obj.signal.^2)/50); %watt
|
||||
tgtpow = sqrt(1e-3); %watt -> wir wollen milliwatt
|
||||
|
||||
scling = tgtpow/curpow;
|
||||
|
||||
obj.signal = obj.signal*scling;
|
||||
|
||||
case normalization_mode.rms
|
||||
|
||||
obj.signal = obj.signal / sqrt(mean(obj.signal.^2));
|
||||
|
||||
case normalization_mode.oneone
|
||||
|
||||
obj.signal = obj.signal - min(obj.signal);
|
||||
obj.signal = obj.signal/max(abs(obj.signal));
|
||||
obj.signal = (2*obj.signal) - 1;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function obj = setPower(obj,outputpower, mode)
|
||||
|
||||
arguments
|
||||
obj Electricalsignal
|
||||
outputpower
|
||||
mode power_notation
|
||||
end
|
||||
|
||||
switch mode
|
||||
case power_notation.W
|
||||
|
||||
case power_notation.mW
|
||||
outputpower_w = outputpower/1000; %mW to Watt
|
||||
case power_notation.dBm
|
||||
outputpower_w = 10^((outputpower-30)/10); % dBm to Watt
|
||||
case power_notation.dBW
|
||||
outputpower_w = 10^((outputpower)/10); % dBm to Watt
|
||||
end
|
||||
|
||||
curpow = sqrt(mean(obj.signal.^2)/50); %watt mit 50 ohm ref
|
||||
tgtpow = sqrt(outputpower_w); %watt -> wir wollen milliwatt
|
||||
|
||||
scling = tgtpow/curpow;
|
||||
|
||||
obj.signal = obj.signal*scling;
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ classdef Informationsignal < Signal
|
||||
|
||||
function pow = power(obj)
|
||||
|
||||
pow = mean(abs(obj.signal),"all") ;
|
||||
pow = mean(abs(obj.signal.^2),"all") ;
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -373,14 +373,14 @@ classdef Signal
|
||||
fsig = obj.fs;
|
||||
q = fsig/fsym;
|
||||
|
||||
if q > 10
|
||||
sig = abs(obj.signal).^2;
|
||||
if q > 10 && isinteger(q)
|
||||
sig = (obj.signal);
|
||||
else
|
||||
sig = abs(obj.resample("fs_in",fsig,"fs_out",fsym*10).signal);
|
||||
sig = (obj.resample("fs_in",fsig,"fs_out",fsym*30).signal);
|
||||
q = 10;
|
||||
end
|
||||
|
||||
figure(12)
|
||||
figure()
|
||||
clf
|
||||
cursor = 200*q;
|
||||
|
||||
@@ -390,6 +390,8 @@ classdef Signal
|
||||
cursor=cursor+q;
|
||||
s=s+1;
|
||||
end
|
||||
|
||||
ylim([-3 3]);
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -5,9 +5,10 @@ classdef AWG
|
||||
properties(Access=public)
|
||||
|
||||
kover %oversampling factor e.g. 16
|
||||
upsampling_method
|
||||
repetitions %repeat the signal to generate a longer sequence?
|
||||
fdac %needed
|
||||
normalize %want to normalize at first? either 0 or 1
|
||||
normalize2dac %want to normalize at first? either 0 or 1
|
||||
bit_resolution %bit res. of quantizer (e.g. 5 bit)
|
||||
dac_min
|
||||
dac_max
|
||||
@@ -32,8 +33,9 @@ classdef AWG
|
||||
|
||||
arguments
|
||||
options.kover = 16;
|
||||
options.upsampling_method upsampling_mode
|
||||
options.repetitions = 1;
|
||||
options.normalize = 1;
|
||||
options.normalize2dac = 1;
|
||||
options.fdac = 92e9;
|
||||
options.bit_resolution = 5.5
|
||||
options.dac_min = -0.5;
|
||||
@@ -44,6 +46,7 @@ classdef AWG
|
||||
options.lpf_type = 0;
|
||||
options.f_cutoff = 32e9;
|
||||
options.H_lpf Filter
|
||||
|
||||
end
|
||||
|
||||
fn = fieldnames(options);
|
||||
@@ -59,9 +62,20 @@ classdef AWG
|
||||
|
||||
len_in = length(signalclass_in.signal);
|
||||
|
||||
if signalclass_in.fs ~= obj.fdac
|
||||
signalclass_in = signalclass_in.resample("fs_in",signalclass_in.fs,"fs_out",obj.fdac);
|
||||
end
|
||||
|
||||
% 1-3. actual processing of the signal (normalize->quantize->sample hold)
|
||||
signalclass_in.signal = obj.process_(signalclass_in.signal);
|
||||
|
||||
% cast the inform. signal to electrical signal
|
||||
signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook);
|
||||
|
||||
% normalize to 0dBm before applying the lowpass
|
||||
%signalclass_in = signalclass_in.normalize("mode","milliwatt");
|
||||
signalclass_in = signalclass_in.setPower(12,"dBm");
|
||||
|
||||
% 4. Apply LPF on the signal
|
||||
if obj.lpf_active
|
||||
if isa(obj.H_lpf,'Filter')
|
||||
@@ -74,10 +88,9 @@ classdef AWG
|
||||
signalclass_in = lpf.process(signalclass_in);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% cast the inform. signal to electrical signal
|
||||
signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook);
|
||||
|
||||
|
||||
% append to logbook
|
||||
current_class = class(obj);
|
||||
lbdesc = ['AWG ', current_class , '// k_over:',num2str(obj.kover),'. f_dac:',num2str(obj.fdac*1e-9),'GHz. Resolution:',num2str(obj.bit_resolution),' bits.'];
|
||||
@@ -108,16 +121,17 @@ classdef AWG
|
||||
|
||||
obj.signal_length = length(data_in);
|
||||
|
||||
if obj.normalize
|
||||
% 0a Normalize the signal to 1 Vpp and set the amplitude of the signal
|
||||
if obj.normalize2dac
|
||||
% 0a Normalize the signal to full scale DAC range
|
||||
data_in = data_in - min(data_in);
|
||||
data_in = data_in/(max(data_in)-min(data_in));
|
||||
else
|
||||
% 0b Cut the Signal at -1 and 1 and scale to amplitude
|
||||
data_in(data_in > 1) = 1;
|
||||
data_in(data_in < -1) = -1;
|
||||
data_in = data_in * (obj.dac_max-obj.dac_min);
|
||||
data_in = data_in + obj.dac_min;
|
||||
end
|
||||
|
||||
% 1. Quantize the signal
|
||||
% 1. Quantize the signal - Full Scale is between obj.dac_min
|
||||
% and dac_max. If signal is smaller in between, you won't use
|
||||
% the full bit-resolution.
|
||||
if obj.bit_resolution>0
|
||||
elec_out = obj.quantization(data_in) ;
|
||||
else
|
||||
@@ -125,8 +139,16 @@ classdef AWG
|
||||
end
|
||||
|
||||
% 2. Sample and hold + repeat (data_out: 1xsignal length)
|
||||
elec_out = repmat(elec_out,obj.repetitions,obj.kover);
|
||||
elec_out = reshape(elec_out',[],1);
|
||||
if obj.upsampling_method == 1
|
||||
% just use matlab function
|
||||
elec_out = resample(elec_out,obj.kover,1);
|
||||
elseif obj.upsampling_method == 2
|
||||
% sample and hold
|
||||
elec_out = repmat(elec_out,obj.repetitions,obj.kover);
|
||||
elec_out = reshape(elec_out',[],1);
|
||||
else
|
||||
error('chosen upsampling method not implemented?');
|
||||
end
|
||||
|
||||
% 3. Add skew (not implemented so far)
|
||||
if obj.skew_active
|
||||
@@ -145,7 +167,7 @@ classdef AWG
|
||||
|
||||
if isreal(x_in)
|
||||
% shift signal and clip to quantizer intervall
|
||||
x_in = min(max(x_in-obj.dac_min,0),obj.dac_max-obj.dac_min);
|
||||
x_in = min( max(x_in-obj.dac_min,0), obj.dac_max-obj.dac_min);
|
||||
|
||||
% quantize signal
|
||||
x_in = round((steps-1)/(obj.dac_max-obj.dac_min)*x_in);
|
||||
|
||||
@@ -24,6 +24,7 @@ classdef PAMmapper
|
||||
|
||||
if isa(signal_in,'Signal')
|
||||
signal_in.signal = obj.map_(signal_in.signal);
|
||||
signal_in = signal_in.normalize("mode","rms");
|
||||
signal_in = signal_in.logbookentry();
|
||||
out = signal_in;
|
||||
else
|
||||
@@ -57,7 +58,7 @@ classdef PAMmapper
|
||||
pam_sig=2*pam_sig-3;
|
||||
end
|
||||
|
||||
pam_sig = pam_sig .* 1/sqrt(5);
|
||||
pam_sig = pam_sig/sqrt(5);
|
||||
|
||||
case 6
|
||||
|
||||
@@ -85,7 +86,7 @@ classdef PAMmapper
|
||||
pam_sig=2*pam_sig-7;
|
||||
end
|
||||
|
||||
|
||||
pam_sig = pam_sig/sqrt(21);
|
||||
case 16
|
||||
% 16-ASK:
|
||||
x1 = bitpattern(:,1);
|
||||
@@ -126,6 +127,7 @@ classdef PAMmapper
|
||||
elseif obj.unipolar==1
|
||||
thres=[0.5,1.5,2.5];
|
||||
end
|
||||
|
||||
thres = thres .* 1/sqrt(5);
|
||||
|
||||
case 6 %PAM 6
|
||||
@@ -139,6 +141,8 @@ classdef PAMmapper
|
||||
elseif obj.unipolar==1
|
||||
thres=0.5:6.5;
|
||||
end
|
||||
|
||||
thres=thres./sqrt(21);
|
||||
|
||||
case 16
|
||||
% 16-ASK
|
||||
|
||||
@@ -88,7 +88,7 @@ classdef Pulseformer
|
||||
%Bau das Filter (hier rrc)
|
||||
racos_len = obj.pulselength*2;
|
||||
alpha = obj.rrcalpha;
|
||||
h = rcosdesign(alpha,racos_len,sps);
|
||||
h = rcosdesign(alpha,racos_len,sps,"normal");
|
||||
h = h./ max(h);
|
||||
end
|
||||
|
||||
@@ -118,8 +118,8 @@ classdef Pulseformer
|
||||
|
||||
|
||||
% %Apply Filter using Matlab build in fctn.
|
||||
h = rcosdesign(alpha,racos_len,sps);
|
||||
h = h./ max(h);
|
||||
% h = rcosdesign(alpha,racos_len,sps);
|
||||
% h = h./ max(h);
|
||||
%data_out_ = upfirdn(data_in,h,up,dn);
|
||||
%
|
||||
% %cut signal, which is longer due to fir filter
|
||||
@@ -128,8 +128,8 @@ classdef Pulseformer
|
||||
% data_out = data_out(st:en);
|
||||
|
||||
%scaling?! see pulsef module line 696
|
||||
scale = max(max([abs(real(data_out)) abs(imag(data_out))])); %find max value from real and imag part
|
||||
data_out = data_out./scale;
|
||||
% scale = max(max([abs(real(data_out)) abs(imag(data_out))])); %find max value from real and imag part
|
||||
% data_out = data_out./scale;
|
||||
|
||||
data_out = data_out';
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ classdef EQ_silas < handle
|
||||
d_constellation %constellation points of the reference
|
||||
|
||||
y_out %equalizer output signal
|
||||
d_out %decision output
|
||||
|
||||
% FFE coefficients always named with "e"
|
||||
Ne
|
||||
@@ -107,7 +108,7 @@ classdef EQ_silas < handle
|
||||
|
||||
end
|
||||
|
||||
function [signalclass_out] = process(obj,signalclass_in, reference_signalclass_in)
|
||||
function [signalclass_out,symbols_out] = process(obj,signalclass_in, reference_signalclass_in)
|
||||
|
||||
% actual processing of the signal (steps 1. - 3.)
|
||||
% 1 normalize RMS
|
||||
@@ -117,6 +118,7 @@ classdef EQ_silas < handle
|
||||
obj.process_(signalclass_in.signal', reference_signalclass_in.signal');
|
||||
|
||||
signalclass_in.signal = obj.y_out';
|
||||
|
||||
|
||||
%change sampling frequency of outgoing signal
|
||||
signalclass_in.fs = reference_signalclass_in.fs;
|
||||
@@ -125,6 +127,9 @@ classdef EQ_silas < handle
|
||||
lbdesc = ['EQ von Silas ist gelaufen '];
|
||||
signalclass_in = signalclass_in.logbookentry(lbdesc);
|
||||
|
||||
symbols_out = signalclass_in;
|
||||
symbols_out.signal = obj.d_out;
|
||||
|
||||
% write to output
|
||||
signalclass_out = signalclass_in;
|
||||
|
||||
@@ -213,7 +218,7 @@ classdef EQ_silas < handle
|
||||
|
||||
%start the dd mode with coefficients from training
|
||||
coeff = [obj.e;obj.b];
|
||||
obj.e_dc = ones(obj.eq_updatelatency,1);%.*obj.e_dc;
|
||||
obj.e_dc = ones(obj.eq_updatelatency,1).*obj.e_dc;
|
||||
dc_block = ones(obj.eq_parallelization_blocklength,1);
|
||||
|
||||
for ddloop = 1:obj.ddloops
|
||||
@@ -236,8 +241,9 @@ classdef EQ_silas < handle
|
||||
d_feedback = zeros(obj.Cb(1),1);
|
||||
d_vnle = obj.calcVNLENonlinVecs(d_feedback,obj.Ib2,obj.Ib3,obj.Nb,obj.d_norm);
|
||||
d_hat = zeros(obj.x_length,1);
|
||||
|
||||
m_reg = 0;
|
||||
lvl_err = NaN(obj.x_length,numel(obj.d_constellation));
|
||||
lvl_err_mov = NaN(100,numel(obj.d_constellation));
|
||||
m_reg = 0;
|
||||
|
||||
if obj.eq_avg_blocklength > 0
|
||||
averaging_window = zeros(obj.eq_avg_blocklength,1);
|
||||
@@ -264,19 +270,30 @@ classdef EQ_silas < handle
|
||||
x_d = [x_vnle;-d_vnle];
|
||||
|
||||
%Apply filter
|
||||
%y(m) = (m_reg(end)*dc_cnt + obj.e_dc(end)) + x_d.'* coeff;
|
||||
if obj.mu_dc_dd > 0
|
||||
y(m) = obj.e_dc(end) + x_d.'* coeff;
|
||||
else
|
||||
y(m) = x_d.'* coeff;
|
||||
end
|
||||
|
||||
%Decision
|
||||
|
||||
%Decision 1
|
||||
[~,symbol_idx] = min(abs(y(m) - obj.d_constellation)); % decision for closest constellation point
|
||||
d_hat(k) = obj.d_constellation(symbol_idx);
|
||||
|
||||
%Error between FFE & DFE filtered signal and Decision
|
||||
obj.error(k) = y(m) - d_hat(k);
|
||||
%
|
||||
lvl_err(k,symbol_idx) = obj.error(k);
|
||||
|
||||
lvl_err_mov(:,symbol_idx) = circshift(lvl_err_mov(:,symbol_idx),1);
|
||||
lvl_err_mov(1,symbol_idx) = obj.error(k);
|
||||
|
||||
%Decision 2
|
||||
y(m) = y(m)-mean(lvl_err_mov(:,symbol_idx),'omitnan');
|
||||
[~,symbol_idx] = min(abs(y(m) - obj.d_constellation)); % decision for closest constellation point
|
||||
d_hat(k) = obj.d_constellation(symbol_idx);
|
||||
|
||||
%Error between FFE & DFE filtered signal and Decision
|
||||
obj.error(k) = y(m) - d_hat(k);
|
||||
|
||||
%Update FFE and DFE coefficients
|
||||
coeff = coeff - (mu_mat * (obj.error(k) * conj(x_d)));
|
||||
@@ -324,7 +341,34 @@ classdef EQ_silas < handle
|
||||
end
|
||||
end
|
||||
|
||||
%%
|
||||
%
|
||||
% b = movmean(lvl_err,[500 500],1,"omitnan");
|
||||
%
|
||||
% figure(11)
|
||||
% for i = 1:4
|
||||
% hold on
|
||||
% stem(lvl_err(:,i))
|
||||
% end
|
||||
|
||||
|
||||
|
||||
%%
|
||||
|
||||
obj.y_out = (circshift( y.' ,-(obj.delay))).';
|
||||
obj.d_out = d_hat(1:2:end);
|
||||
% err = obj.error(1:2:end);
|
||||
% res = NaN(8,length(err));
|
||||
% for lvl = 1:8
|
||||
% a = find(obj.d_out==obj.d_constellation(lvl));
|
||||
% res(lvl,a) = err(a);
|
||||
% end
|
||||
% mean(res,2,"omitnan");
|
||||
%
|
||||
% figure(12)
|
||||
% scatter(1:length(obj.y_out),obj.y_out,1,'.')
|
||||
% hold on
|
||||
% scatter(1:length(obj.d_out),obj.d_out,1,'.')
|
||||
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user