classdef PAMmapper %PAMMAPPER Summary of this class goes here % Detailed explanation goes here properties M unipolar thresholds end methods function obj = PAMmapper(M, unipolar) %PAMMAPPER Construct an instance of this class % Detailed explanation goes here obj.M = M; obj.unipolar = unipolar; obj.thresholds = obj.get_demodulation_thresholds(); end function out = map(obj,signal_in) 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 out = signal_in; end end function signalclass_out = demap(obj,signalclass_in) signalclass_in.signal = obj.demap_(signalclass_in.signal); signalclass_in = signalclass_in.logbookentry(); signalclass_out = signalclass_in; end function pam_sig = map_(obj,bitpattern) switch obj.M case 2 % 2-ASK: BPSK / OOK pam_sig=bitpattern(:,1); if obj.unipolar==0 pam_sig=2*pam_sig-1; end case 4 % 4-ASK: pam_sig=2*bitpattern(:,1)+(bitpattern(:,1)==bitpattern(:,2)); if obj.unipolar==0 pam_sig=2*pam_sig-3; end pam_sig = pam_sig/sqrt(5); case 6 m = 1; if size(bitpattern,2)>size(bitpattern,1) bitpattern = bitpattern'; %vector aufrecht stellen end % LUT based mapping for k = 1:5:fix(length(bitpattern)/5)*5 pam_sig(m:m+1,1) = obj.thresholds(bin2dec(int2str(bitpattern(k:k+4)'))+1,:); m = m+2; end pam_sig = pam_sig/sqrt(10); case 8 % 8-ASK: x1 = bitpattern(:,1); x2 = (bitpattern(:,1)==bitpattern(:,3)); x3 = x2~=bitpattern(:,2); pam_sig = 4*x1 + 2*x2 + x3; if obj.unipolar==0 pam_sig=2*pam_sig-7; end pam_sig = pam_sig/sqrt(21); case 16 % 16-ASK: x1 = bitpattern(:,1); x2 = (bitpattern(:,1)==bitpattern(:,4)); x3 = x2~=bitpattern(:,3); x4 = x3~=bitpattern(:,2); pam_sig = 8*x1 + 4*x2 + 2*x3 + x4; if obj.unipolar==0 pam_sig=2*pam_sig-15; end end end function thres = get_demodulation_thresholds(obj) %simply get the obj.thresholdseshold values for PAM %28.03.2023 - Silas Oett. - Extracted from digi_demod.m % switch obj.M case 2 % 2-ASK if obj.unipolar thres=0.5; else %bi polar thres=0; end case 4 % 4-ASK if obj.unipolar==0 thres=[-2,0,2]; elseif obj.unipolar==1 thres=[0.5,1.5,2.5]; end thres = thres .* 1/sqrt(5); case 6 %PAM 6 thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1]; case 8 % 8-ASK if obj.unipolar==0 thres=-6:2:6; elseif obj.unipolar==1 thres=0.5:6.5; end thres=thres./sqrt(21); case 16 % 16-ASK if obj.unipolar==0 && scale_mode==1 thres=-14:2:14; elseif obj.unipolar==1 && scale_mode==1 thres=0.5:14.5; end end end function [data_out] = demap_(obj,data_in) data_in= data_in'; if obj.M ~= 6 % create output if ~isempty(obj.thresholds) a = squeeze(repmat(real(data_in),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in) 1])); %Threshold in 3 Spalten comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3 comp_real=repmat(real(data_in),[1 1 length(obj.thresholds)]) > repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in) 1]); else comp_real=[]; end s1=size(comp_real,1); s2=size(comp_real,2); end switch obj.M case 2 % 2-ASK data_out=comp_real(:,:,1); case 4 % 4-ASK data_out=[comp_real(:,:,2); ones(s1,s2) - comp_real(:,:,1) + comp_real(:,:,3)]; case 6 data_in = data_in/(sqrt(mean(abs(data_in).^2))); data_in = data_in*sqrt(10); if size(data_in,2) > 1 data_in = data_in.'; end if length(data_in)/2 ~= round(length(data_in)/2) data_in = [data_in;0]; end m = 1; for n = 1:2:length(data_in) dist = sqrt((data_in(n)-obj.thresholds(:,1)).^2+(data_in(n+1)-obj.thresholds(:,2)).^2); [~,dd_idx] = min(dist); % dec_out(n:n+1) = LUT(dd_idx,:); data_out(m:m+4) = bitget(dd_idx-1,5:-1:1); m = m+5; end case 8 % 8-ASK data_out=[comp_real(:,:,4); comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7); 1-comp_real(:,:,2)+comp_real(:,:,6)]; case 16 % 16-ASK data_out=[comp_real(:,:,8); comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7)+comp_real(:,:,9)-comp_real(:,:,11)+comp_real(:,:,13)-comp_real(:,:,15); comp_real(:,:,2)-comp_real(:,:,6)+comp_real(:,:,10)-comp_real(:,:,14); 1-comp_real(:,:,4)+comp_real(:,:,12)]; end data_out = data_out'; end function [data_out] = decide_pamlevel(obj,data_in,options) arguments obj data_in Signal options.symbol_levels = [] end %A) normally return the preproduct of the decision a = squeeze(repmat(real(data_in.signal),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in.signal) 1])); %Threshold in 3 Spalten comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3 data_out = data_in; data_out.signal = sum(comp_real,2); %Option: return the actual level values/ just map onto given %symbol levels if ~isempty(options.symbol_levels) data_out.signal = options.symbol_levels(data_out.signal+1); end end function [out] = separate_pamlevels(obj,data_in) %A) normally return the preproduct of the decision a = squeeze(repmat(real(data_in.signal),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in.signal) 1])); %Threshold in 3 Spalten comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3 comp_real_sum = sum(comp_real,2); out = NaN(length(data_in),length(obj.thresholds)+1); for idx = 1:length(data_in) out(idx,comp_real_sum(idx)+1) = data_in.signal(idx); end end end end