diff options
| author | Davit Grigoryan <[email protected]> | 2026-04-09 12:25:24 -0700 |
|---|---|---|
| committer | Davit Grigoryan <[email protected]> | 2026-04-22 02:37:26 -0700 |
| commit | 14ca50edb249d5f4ef621903259d955deb3a2fc3 (patch) | |
| tree | a1798764b97c2c351ea9c8ab1422886e9488d18b /LoopFilter.m | |
Diffstat (limited to 'LoopFilter.m')
| -rw-r--r-- | LoopFilter.m | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/LoopFilter.m b/LoopFilter.m new file mode 100644 index 0000000..ab9ea8e --- /dev/null +++ b/LoopFilter.m @@ -0,0 +1,175 @@ +classdef (StrictDefaults) LoopFilter < serdes.SerdesAbstractSystemObject & TriggeredComponent + % LoopFilter Loop Filter + % obj = LoopFilter returns a System Object, obj, that integrates the + % input Up/Down signal and increments or decrements the output phase + % control signal. + % + % LoopFilter methods: + % step - Integrates the input Up/Down phase detector signal and + % increments or decrements the output phase control signal when the + % sum exceeds some limit. The useage is: + % PhaseControl = step(obj,ClockIn,UpDown) + % + % LoopFilter properties: + % ProportionalGain - Proportional gain. Typically set to 1/timeInterleaveDepth + % PhaseStep - Step size for phase increment or decrement + % UpDownMaxLimit - Up/down counter limit + + % Copyright 2021 The MathWorks, Inc. + + %#codegen + + properties (Nontunable) + + % Proportional gain + % Typically set to 1/timeInterleaveDepth + ProportionalGain = 1.0; + + % Step size for phase increment/decrement + PhaseStep = 1/128; + + % Up/down counter limit + UpDownMaxLimit = 16; + end + properties (Hidden, SetAccess=private) + PhaseControlInternal % Phase control output + UpDownSum % Accumulated up/down pulses (sum) + UpDownLimit % Current limit of up/down sum + PhaseChange % Phase increment/decrement + end + properties(Hidden,Nontunable) + %Required by abstract class but not used + 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 = LoopFilter(varargin) + % Support name-value pair arguments when constructing object + obj.BlockName = 'LoopFilter'; + 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 phase error output + obj.PhaseControlInternal = 0.0; + + % Initialize filter properties + obj.UpDownSum = 0.0; + obj.UpDownLimit = 0.0; + obj.PhaseChange = 0.0; + end + + function validateInputsImpl(~,waveIn) + validateattributes(waveIn,{'numeric'},{'finite'},'','waveIn'); + end + + function PhaseControl = stepImpl(obj,ClockIn,UpDown) + %PhaseControl = stepImpl(obj,ClockIn,UpDown) + + if isSample(obj) + %Triggered clock step + ClockStep(obj,ClockIn) + + % On falling clock edge, filter the incoming phase error + if obj.PhaseFallingIndex > 0 + + % Reset phase increment/decrement + obj.PhaseChange = 0.0; + + % Update up/down accumulator + obj.UpDownSum = obj.UpDownSum + UpDown; + + % Up/down sum exceed current limit (positive or negative side) + if abs(obj.UpDownSum) >= obj.UpDownLimit + + % Set phase increment/decrement + obj.PhaseChange = sign(obj.UpDownSum) * obj.PhaseStep; + + % Reset up/down accumulator + obj.UpDownSum = 0; + + % Ramp up up/down limit at start up + if obj.UpDownLimit >= obj.UpDownMaxLimit + obj.UpDownLimit = obj.UpDownMaxLimit; + else + obj.UpDownLimit = obj.UpDownLimit + 1; + end + + end + + % Update phase control + obj.PhaseControlInternal = obj.PhaseControlInternal + obj.ProportionalGain * obj.PhaseChange; + + end % obj.PhaseFallingIndex > 0 + end + + % Assign output + PhaseControl = obj.PhaseControlInternal; + end + + function resetImpl(~) + % Initialize / reset discrete-state properties + end + + %% Simulink functions + function icon = getIconImpl(~) + % Define icon for System block + icon = "Loop\nFilter"; + end + function [name1,name2] = getInputNamesImpl(~) + name1 = sprintf('Demux\nClock'); + name2 = 'UpDown'; + end + function name1 = getOutputNamesImpl(~) + name1 = sprintf('Phase\nControl'); + 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',{'ProportionalGain','PhaseStep',... + 'UpDownMaxLimit'}); + end + end +end |
