classdef Pulseformer %Pulseformer Summary of this class goes here % Detailed explanation goes here properties(Access=public) end properties(Access=public) fs fsym matched_sps output_sps pulse pulselength alpha matched end methods (Access=public) function obj = Pulseformer(options) %NAME Construct an instance of this class % Detailed explanation goes here arguments options.fs double options.fsym double options.matched_sps double options.output_sps double options.pulse pulseform = pulseform.rc options.pulselength double {mustBeInteger} = 32 options.alpha double = 0.05 options.matched = 0; end % fn = fieldnames(options); for n = 1:numel(fn) try obj.(fn{n}) = options.(fn{n}); end end % do more stuff end function signalclass_out = process(obj,signalclass_in) % actual processing of the signal (steps 1. - 3.) signalclass_in.signal = obj.process_(signalclass_in.signal); % append to logbook lbdesc = 'Applied Pulseshaping'; signalclass_in = signalclass_in.logbookentry(lbdesc); % write fs to signal if obj.matched signalclass_in.fs = obj.fsym .* obj.output_sps;%.* (obj.fdac./obj.fsym); else signalclass_in.fs = obj.fs;%.* (obj.fdac./obj.fsym); end % write to output signalclass_out = signalclass_in; end end methods (Access=private) % Cant be seen from outside! So put all your functions here that can/ % shall not be called from outside function data_out = process_(obj,data_in) %METHOD1 Summary of this method goes here % Detailed explanation goes here arguments(Input) obj data_in end arguments(Output) data_out end if ~isempty(obj.output_sps) obj.fsym = obj.fsym.*obj.output_sps; end if ~rem(obj.fs,obj.fsym) %ist ein Vielfaches sps = obj.fs / obj.fsym; p = sps; q = 1; else %ist kein Vielfaches p = obj.fsym / gcd(obj.fs, obj.fsym); %upsampling p->->-> q = obj.fs/ gcd(obj.fs, obj.fsym); %downsampling <-q sps= q; %sps während dem pulse shaping end if obj.pulse == pulseform.rc filtertype = 'normal'; elseif pulseform.rrc filtertype = 'sqrt'; end %Bau das Filter (hier rc) racos_len = obj.pulselength*2; h = rcosdesign(obj.alpha,racos_len,sps,filtertype); % h = h./ max(h); if obj.matched h = conj(fliplr(h)); end manual_cyclic_convolution = 0; upsample_filter = 0; upfirdn_convolution = 1; if manual_cyclic_convolution % Apply filter the long way (from move_it) data_in = data_in'; blen = length(data_in)*sps; % oversample symbol sequence symbolov=zeros(size(data_in,1),blen); symbolov(:,1:sps:blen-sps+1)=data_in; H=fft(h,blen); % Convolution of Bit sequence with impulse response data_out=ifft( fft(symbolov.') .* repmat( H,size(data_in,1),1 ).' ).'; data_out = circshift(data_out,[0 -(obj.pulselength*sps)]); if rem(obj.fs,obj.fsym) data_out = data_out(1:q:end); end end if upsample_filter data_out_ = upsample(data_in,p); mfOutput = filter(h, 1, data_out_); % Matched filter output figure() hold on stem(mfOutput(1:1000),'Marker','o','MarkerSize',1,'LineStyle','-','LineWidth',1); stem(data_out_(1:1000),'Marker','o','MarkerSize',1,'LineStyle','-','LineWidth',1); end if upfirdn_convolution %Apply Filter using Matlab build in fctn. data_out_ = upfirdn(data_in,h,p,q); %cut signal, which is longer due to fir filter st = round(p/q*racos_len/2); %we need to cut y_out en = round(st + (length(data_in)*p/q)); data_out = data_out_(st:en); end if upfirdn_convolution && manual_cyclic_convolution figure() subplot(2,1,1) title("Convolution vs. Upfirdn and Cut") hold on % plot(data_out_(1:200),'DisplayName','Matlab upfirdn'); plot(data_out(1:200),'DisplayName','By Hand cyclic convolution') subplot(2,1,2) hold on plot(data_out(1:2000),'DisplayName','OUT'); plot(data_in(1:2000),'DisplayName','IN'); end %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; data_out = data_out'; %Check output integrity if abs(round(p/q * length(data_in)) - length(data_out)) > 4 warning('Check signal length after pulse shaping'); %disp('Check signal length after pulse shaping'); end end end end