summaryrefslogtreecommitdiff
path: root/BaudRatePD.m
diff options
context:
space:
mode:
Diffstat (limited to 'BaudRatePD.m')
-rw-r--r--BaudRatePD.m175
1 files changed, 175 insertions, 0 deletions
diff --git a/BaudRatePD.m b/BaudRatePD.m
new file mode 100644
index 0000000..3113f75
--- /dev/null
+++ b/BaudRatePD.m
@@ -0,0 +1,175 @@
+classdef (StrictDefaults) BaudRatePD < serdes.SerdesAbstractSystemObject & TriggeredComponent
+ % BaudRatePD Baud-Rate Phase Detector
+ % obj = BaudRatePD returns a System Object, obj, that performs a
+ % baud-rate or Meuller-Muller phase detection.
+ %
+ % BaudRatePD methods:
+ % step - Performs a baud-rate phase detection using the demux'ed input
+ % decisions and samples. An example usage is as follows:
+ % UpDownOut = step(obj,ClockIn,DecisionIn,SampleIn)
+ %
+ % BaudRatePD properites:
+ % DemuxWidth - Width of input signals
+
+ % Copyright 2018-2019 The MathWorks, Inc.
+
+ %#codegen
+
+ properties (Nontunable)
+
+ %Demux Width
+ DemuxWidth = 32;
+ end
+ properties (Hidden, SetAccess=private)
+ SamplePrevious % Last sample from previous frame
+ DecisionPrevious % Last decision from previous frame
+ TimingFunctionValue % Timing function value
+ SymmetricTransition % Symmetric transition indicator
+ UpDownOutInternal % Phase error output
+ end
+ properties(Hidden)
+ %Property required by abstract class but unused
+ NumberOfClocks = 1;
+ end
+ properties (SetAccess = immutable, Nontunable, Hidden)
+ IsLinear = true;
+ IsTimeInvariant = true;
+ end
+ properties (Nontunable,Hidden)
+ %Input Waveform Type
+ % Set the input wave type as one of 'Sample' | 'Impulse' |
+ % 'Waveform'. The default is 'Sample'.
+ WaveType = 'Sample';
+ end
+ properties(Hidden, Constant)
+ WaveTypeSet = matlab.system.StringSet({'Sample','Impulse','Waveform'});
+ end
+
+ methods
+ % Constructor
+ function obj = BaudRatePD(varargin)
+ % Support name-value pair arguments when constructing object
+ obj.BlockName = 'BaudRatePD';
+ setProperties(obj,nargin,varargin{:})
+ end
+ end
+ methods (Hidden)
+ % The below methods, getAMIParameters, getAMIInputNames and
+ % getAMIOutputNames are for use only within the serdesDesigner App
+ % and will not influence the AMI parameters in Simulink whatsoever.
+ function amiParameters = getAMIParameters(~)
+ amiParameters = {};
+ end
+ function names = getAMIInputNames(~)
+ names = {};
+ end
+ function names = getAMIOutputNames(~)
+ names = {};
+ end
+ end
+ methods (Access = protected, Hidden)
+ function val = isSample(obj)
+ val = strcmpi(obj.WaveType,'Sample');
+ end
+ end
+ methods(Access = protected)
+ %% Common functions
+ function setupImpl(obj)
+
+ setupClock(obj);
+
+ % Initialize sample and decision from previous frame
+ obj.SamplePrevious = 0;
+ obj.DecisionPrevious = 0;
+
+ % Initialize timing function and symmetric transition indicator
+ obj.TimingFunctionValue = zeros(obj.DemuxWidth, 1);
+ obj.SymmetricTransition = zeros(obj.DemuxWidth, 1);
+
+ % Initialize output
+ obj.UpDownOutInternal = 0;
+ end
+
+ function validateInputsImpl(~,waveIn)
+ validateattributes(waveIn,{'numeric'},{'finite'},'','waveIn');
+ end
+
+ function UpDownOut = stepImpl(obj,ClockIn,DecisionIn,SampleIn)
+ %UpDownOut = stepImpl(obj,ClockIn,DecisionIn,SampleIn)
+
+ %TODO
+% if nargin==4
+% SampleIn = varargin{1};
+% ClockIn = varargin{2};
+% else
+% SampleIn = 0;
+% ClockIn = 0;
+% end
+
+ if isSample(obj)
+ %Triggered clock step
+ ClockStep(obj,ClockIn)
+
+ % On falling clock edge, process frame of samples
+ if obj.PhaseFallingIndex > 0
+
+ % Calculate timing function
+ % D[i]*S[i-1] - S[i]*D[i-1]
+ obj.TimingFunctionValue = SampleIn .* [obj.DecisionPrevious; DecisionIn(1:end-1)] - ...
+ DecisionIn .* [obj.SamplePrevious; SampleIn(1:end-1)];
+
+ % Mark symmetric transitions
+ % D[i] == -D[i-1]
+ obj.SymmetricTransition = double(abs(DecisionIn + [obj.DecisionPrevious; DecisionIn(1:end-1)]) < eps);
+
+ % Calculate phase error
+ % 1. Slice timing function from every sample in the frame
+ % 2. Only symmetric transitions contribute to phase error
+ % 3. Add contributions of all samples in the frame together
+ obj.UpDownOutInternal = sum(obj.SymmetricTransition .* sign(obj.TimingFunctionValue));
+
+ % Update previous frame decision and sample
+ obj.DecisionPrevious = DecisionIn(end);
+ obj.SamplePrevious = SampleIn(end);
+
+ end % obj.PhaseFallingIndex > 0
+ end
+
+ % Assign output
+ UpDownOut = obj.UpDownOutInternal;
+ end
+
+ function resetImpl(~)
+ % Initialize / reset discrete-state properties
+ end
+
+ %% Simulink functions
+ function icon = getIconImpl(~)
+ % Define icon for System block
+ icon = "Baud\nRate\nPhase\nDetector";
+ end
+ function [name1,name2,name3] = getInputNamesImpl(~)
+ name1 = sprintf('Demux\nClock');
+ name2 = 'Decision';
+ name3 = 'Sample';
+ end
+ function name1 = getOutputNamesImpl(~)
+ name1 = 'UpDown';
+ end
+ function num = getNumInputsImpl(obj)
+ if isSample(obj)
+ num = 3;
+ else
+ num = 1;
+ end
+ end
+ end
+ methods(Static, Access=protected)
+ function group = getPropertyGroupsImpl(~)
+ % Define property section(s) for System block dialog
+ group = matlab.system.display.SectionGroup(...
+ 'Title','Main',...
+ 'PropertyList',{'DemuxWidth'});
+ end
+ end
+end \ No newline at end of file