001/* A recursive lattice filter with a port that sets the reflection coefficients.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.domains.sdf.lib;
029
030import java.util.LinkedList;
031import java.util.List;
032
033import ptolemy.actor.TypedIOPort;
034import ptolemy.actor.lib.RecursiveLattice;
035import ptolemy.actor.util.ExplicitChangeContext;
036import ptolemy.data.ArrayToken;
037import ptolemy.data.IntToken;
038import ptolemy.data.expr.Parameter;
039import ptolemy.data.type.BaseType;
040import ptolemy.kernel.CompositeEntity;
041import ptolemy.kernel.Entity;
042import ptolemy.kernel.util.Attribute;
043import ptolemy.kernel.util.IllegalActionException;
044import ptolemy.kernel.util.NameDuplicationException;
045import ptolemy.kernel.util.Settable;
046import ptolemy.kernel.util.Workspace;
047
048///////////////////////////////////////////////////////////////////
049//// VariableRecursiveLattice
050
051/**
052 This actor implements a recursive (all-pole) filter with a lattice
053 structure where the reflection coefficients are supplied at an input port.
054 The <i>blockSize</i> parameter specifies the number of inputs
055 of the filter that are processed per coefficient set provided on the
056 <i>newCoefficients</i> input. If no coefficients are provided on that
057 input port, then the default coefficients defined in the base class
058 are used. In all other respects, the behavior of
059 this actor is the same as that of the base class.
060
061 @author Edward A. Lee
062 @version $Id$
063 @since Ptolemy II 1.0
064 @Pt.ProposedRating Yellow (eal)
065 @Pt.AcceptedRating Yellow (eal)
066 */
067public class VariableRecursiveLattice extends RecursiveLattice
068        implements ExplicitChangeContext {
069    /** Construct an actor with the given container and name.
070     *  @param container The container.
071     *  @param name The name of this actor.
072     *  @exception IllegalActionException If the actor cannot be contained
073     *   by the proposed container.
074     *  @exception NameDuplicationException If the container already has an
075     *   actor with this name.
076     */
077    public VariableRecursiveLattice(CompositeEntity container, String name)
078            throws NameDuplicationException, IllegalActionException {
079        super(container, name);
080
081        blockSize = new Parameter(this, "blockSize");
082        blockSize.setExpression("1");
083
084        newCoefficients = new TypedIOPort(this, "newCoefficients");
085        newCoefficients.setInput(true);
086        newCoefficients.setTypeSameAs(reflectionCoefficients);
087
088        output.setTypeSameAs(input);
089
090        input_tokenConsumptionRate = new Parameter(input,
091                "tokenConsumptionRate");
092        input_tokenConsumptionRate.setTypeEquals(BaseType.INT);
093        input_tokenConsumptionRate.setExpression("blockSize");
094
095        output_tokenProductionRate = new Parameter(output,
096                "tokenProductionRate");
097        output_tokenProductionRate.setTypeEquals(BaseType.INT);
098        output_tokenProductionRate.setExpression("blockSize");
099
100        // The reflectionCoefficients parameter is no longer
101        // of any use, so it is hidden.
102        reflectionCoefficients.setVisibility(Settable.NONE);
103    }
104
105    ///////////////////////////////////////////////////////////////////
106    ////                         public variables                  ////
107
108    /** The number of inputs that use each each coefficient set.
109     *  This is an integer that defaults to 1.
110     */
111    public Parameter blockSize;
112
113    /** The input for new coefficient values.  The type is an array
114     *  of doubles.
115     */
116    public TypedIOPort newCoefficients;
117
118    /** The number of tokens consumed from the input port.
119     */
120    public Parameter input_tokenConsumptionRate;
121
122    /** The number of tokens produced from the output port.
123     */
124    public Parameter output_tokenProductionRate;
125
126    ///////////////////////////////////////////////////////////////////
127    ////                         public methods                    ////
128
129    /** Ensure that the blockSize parameter is positive.
130     *  @param attribute The attribute that changed.
131     *  @exception IllegalActionException If the block size is invalid,
132     *   or if the base class throws it.
133     */
134    @Override
135    public void attributeChanged(Attribute attribute)
136            throws IllegalActionException {
137        if (attribute == blockSize) {
138            IntToken blockSizeToken = (IntToken) blockSize.getToken();
139            _blockSizeValue = blockSizeToken.intValue();
140
141            if (_blockSizeValue < 1) {
142                throw new IllegalActionException(this,
143                        "Invalid blockSize: " + _blockSizeValue);
144            }
145        }
146
147        super.attributeChanged(attribute);
148    }
149
150    /** Clone the actor into the specified workspace. This calls the
151     *  base class and then resets the type constraints.
152     *  @param workspace The workspace for the new object.
153     *  @return A new actor.
154     *  @exception CloneNotSupportedException If a derived class contains
155     *   an attribute that cannot be cloned.
156     */
157    @Override
158    public Object clone(Workspace workspace) throws CloneNotSupportedException {
159        VariableRecursiveLattice newObject = (VariableRecursiveLattice) super.clone(
160                workspace);
161
162        newObject.newCoefficients
163                .setTypeSameAs(newObject.reflectionCoefficients);
164
165        // FIXME: Is this needed?  If so, shouldn't it be in the base class?
166        newObject.output.setTypeSameAs(newObject.input);
167        return newObject;
168    }
169
170    /** Consume the inputs and produce the outputs of the filter.
171     *  @exception IllegalActionException If parameter values are invalid,
172     *   or if there is no director.
173     */
174    @Override
175    public void fire() throws IllegalActionException {
176        if (newCoefficients.hasToken(0)) {
177            ArrayToken coefficientsToken = (ArrayToken) newCoefficients.get(0);
178            reflectionCoefficients.setToken(coefficientsToken);
179        }
180
181        for (int i = 0; i < _blockSizeValue; i++) {
182            super.fire();
183        }
184    }
185
186    /** Return a list of variables that this entity modifies.  The
187     * variables are assumed to have a change context of the given
188     * entity.
189     * @return A list of variables.
190     * @exception IllegalActionException If the list of modified
191     * variables cannot be returned.
192     */
193    @Override
194    public List getModifiedVariables() throws IllegalActionException {
195        List list = new LinkedList();
196        list.add(reflectionCoefficients);
197        return list;
198    }
199
200    /**
201     * Return the change context being made explicit.  In simple cases, this
202     * will simply be the entity implementing this interface.  However, in
203     * more complex cases, directors may implement this interface, or entities
204     * may modify parameters according to a different change context (i.e. HDF)
205     * @return The change context being made explicit.
206     * @exception IllegalActionException Not thrown in this base class.
207     */
208    @Override
209    public Entity getContext() throws IllegalActionException {
210        return this;
211    }
212
213    /** Return false if the input does not have enough tokens to fire.
214     *  Otherwise, return true.
215     *  @return False if the number of input tokens available is not at least
216     *   equal to the <i>blockSize</i> parameter.
217     *  @exception IllegalActionException If the superclass throws it.
218     */
219    @Override
220    public boolean prefire() throws IllegalActionException {
221        if (input.hasToken(0, _blockSizeValue) && newCoefficients.hasToken(0)) {
222            return super.prefire();
223        } else {
224            return false;
225        }
226    }
227
228    ///////////////////////////////////////////////////////////////////
229    ////                         private variables                 ////
230    private int _blockSizeValue = 1;
231}