001/* A 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.Lattice;
035import ptolemy.actor.util.ExplicitChangeContext;
036import ptolemy.data.ArrayToken;
037import ptolemy.data.IntToken;
038import ptolemy.data.expr.Parameter;
039import ptolemy.kernel.CompositeEntity;
040import ptolemy.kernel.Entity;
041import ptolemy.kernel.util.Attribute;
042import ptolemy.kernel.util.IllegalActionException;
043import ptolemy.kernel.util.NameDuplicationException;
044import ptolemy.kernel.util.Settable;
045import ptolemy.kernel.util.Workspace;
046
047///////////////////////////////////////////////////////////////////
048//// VariableLattice
049
050/**
051 This actor implements an FIR filter with a lattice structure where
052 the reflection coefficients are supplied at an input port.
053 The <i>blockSize</i> parameter specifies the number of inputs
054 of the filter that are processed per coefficient set provided on the
055 <i>newCoefficients</i> input. If no coefficients are provided on that
056 input port, then the default coefficients defined in the base class
057 are used. In all other respects, the behavior of
058 this actor is the same as that of the base class.
059
060 @author Edward A. Lee
061 @version $Id$
062 @since Ptolemy II 1.0
063 @Pt.ProposedRating Yellow (eal)
064 @Pt.AcceptedRating Yellow (cxh)
065 */
066public class VariableLattice extends Lattice implements ExplicitChangeContext {
067    /** Construct an actor with the given container and name.
068     *  @param container The container.
069     *  @param name The name of this actor.
070     *  @exception IllegalActionException If the actor cannot be contained
071     *   by the proposed container.
072     *  @exception NameDuplicationException If the container already has an
073     *   actor with this name.
074     */
075    public VariableLattice(CompositeEntity container, String name)
076            throws NameDuplicationException, IllegalActionException {
077        super(container, name);
078
079        blockSize = new Parameter(this, "blockSize");
080        blockSize.setExpression("1");
081
082        newCoefficients = new TypedIOPort(this, "newCoefficients");
083        newCoefficients.setInput(true);
084
085        newCoefficients.setTypeSameAs(reflectionCoefficients);
086        output.setTypeSameAs(input);
087
088        input_tokenConsumptionRate = new Parameter(input,
089                "tokenConsumptionRate");
090        input_tokenConsumptionRate.setExpression("blockSize");
091
092        output_tokenProductionRate = new Parameter(output,
093                "tokenProductionRate");
094        output_tokenProductionRate.setExpression("blockSize");
095
096        // The reflectionCoefficients parameter is no longer
097        // of any use, so it is hidden.
098        reflectionCoefficients.setVisibility(Settable.NONE);
099    }
100
101    ///////////////////////////////////////////////////////////////////
102    ////                         public variables                  ////
103
104    /** The number of inputs that use each each coefficient set.
105     *  This is an integer that defaults to 1.
106     */
107    public Parameter blockSize;
108
109    /** The input for new coefficient values.  This is an array
110     *  of doubles.
111     */
112    public TypedIOPort newCoefficients;
113
114    /** The parameter that gives the number of tokens consumed by the input
115     *  port.  This is set equal to <i>blockSize</i>.
116     */
117    public Parameter input_tokenConsumptionRate;
118
119    /** The parameter that gives the number of tokens produces by the output
120     *  port.  This is set equal to <i>blockSize</i>.
121     */
122    public Parameter output_tokenProductionRate;
123
124    ///////////////////////////////////////////////////////////////////
125    ////                         public methods                    ////
126
127    /** Ensure that the blockSize parameter is positive.
128     *  @param attribute The attribute that changed.
129     *  @exception IllegalActionException If the block size is invalid,
130     *   or if the base class throws it.
131     */
132    @Override
133    public void attributeChanged(Attribute attribute)
134            throws IllegalActionException {
135        if (attribute == blockSize) {
136            IntToken blockSizeToken = (IntToken) blockSize.getToken();
137            _blockSizeValue = blockSizeToken.intValue();
138
139            if (_blockSizeValue < 1) {
140                throw new IllegalActionException(this,
141                        "Invalid blockSize: " + _blockSizeValue);
142            }
143        } else {
144            super.attributeChanged(attribute);
145        }
146    }
147
148    /** Clone the actor into the specified workspace. This calls the
149     *  base class and then resets the type constraints.
150     *  @param workspace The workspace for the new object.
151     *  @return A new actor.
152     *  @exception CloneNotSupportedException If a derived class contains
153     *   an attribute that cannot be cloned.
154     */
155    @Override
156    public Object clone(Workspace workspace) throws CloneNotSupportedException {
157        VariableLattice newObject = (VariableLattice) super.clone(workspace);
158
159        newObject.newCoefficients
160                .setTypeSameAs(newObject.reflectionCoefficients);
161
162        // FIXME: Is this needed?  If so, shouldn't it be in the base class?
163        newObject.output.setTypeSameAs(newObject.input);
164        return newObject;
165    }
166
167    /** Consume the inputs and produce the outputs of the filter.
168     *  @exception IllegalActionException If parameter values are invalid,
169     *   or if there is no director.
170     */
171    @Override
172    public void fire() throws IllegalActionException {
173        if (newCoefficients.hasToken(0)) {
174            ArrayToken coefficientsToken = (ArrayToken) newCoefficients.get(0);
175            reflectionCoefficients.setToken(coefficientsToken);
176        }
177
178        for (int i = 0; i < _blockSizeValue; i++) {
179            super.fire();
180        }
181    }
182
183    /** Return a list of variables that this entity modifies.  The
184     * variables are assumed to have a change context of the given
185     * entity.
186     * @return A list of variables.
187     * @exception IllegalActionException If the list of modified
188     * variables cannot be returned.
189     */
190    @Override
191    public List getModifiedVariables() throws IllegalActionException {
192        List list = new LinkedList();
193        list.add(reflectionCoefficients);
194        return list;
195    }
196
197    /**
198     * Return the change context being made explicit.  In simple cases, this
199     * will simply be the entity implementing this interface.  However, in
200     * more complex cases, directors may implement this interface, or entities
201     * may modify parameters according to a different change context (i.e. HDF)
202     * @return The change context being made explicit.
203     * @exception IllegalActionException Not thrown in this base class.
204     */
205    @Override
206    public Entity getContext() throws IllegalActionException {
207        return this;
208    }
209
210    /** Return false if the input does not have enough tokens to fire.
211     *  Otherwise, return true.
212     *  @return False if the number of input tokens available is not at least
213     *   equal to the <i>blockSize</i> parameter.
214     *  @exception IllegalActionException If the superclass throws it.
215     */
216    @Override
217    public boolean prefire() throws IllegalActionException {
218        if (input.hasToken(0, _blockSizeValue) && newCoefficients.hasToken(0)) {
219            return super.prefire();
220        } else {
221            return false;
222        }
223    }
224
225    ///////////////////////////////////////////////////////////////////
226    ////                         private variables                 ////
227    private int _blockSizeValue = 1;
228}