001/* A type polymorphic FIR filter with a port that sets the taps. 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 ptolemy.actor.TypedIOPort; 031import ptolemy.data.ArrayToken; 032import ptolemy.data.IntToken; 033import ptolemy.data.expr.Parameter; 034import ptolemy.kernel.CompositeEntity; 035import ptolemy.kernel.util.Attribute; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.Settable; 039import ptolemy.kernel.util.Workspace; 040 041/////////////////////////////////////////////////////////////////// 042//// VariableFIR 043 044/** 045 This actor implements a type polymorphic finite-impulse response 046 filter with multirate capability, where the impulse response 047 of the filter is provided by an input. Since this filter operates on 048 Tokens, it is polymorphic in the type of data it operates on. 049 <p> 050 If the <i>decimation</i> parameter is unity (the default), then 051 the <i>blockSize</i> parameter specifies the number of inputs 052 of the filter that are processed per coefficient set provided on the 053 <i>newTaps</i> input. Otherwise, if <i>decimation</i> is greater than unity, 054 then the number of tokens consumed is the product of <i>decimation</i> 055 and <i>blockSize</i>, and all these inputs are processed using the 056 filter coefficients provided on <i>newTaps</i>. 057 In all other respects, the behavior of this 058 actor is the same as that of the base class. 059 <p> 060 Note that when a new set of filter coefficients arrives on <i>newTaps</i>, 061 if the new set has more coefficients than the old set, then a transient 062 will occur that may be unexpected. The delay line containing previously 063 consumed data has to be increased in length to match the number of 064 new coefficients. However, the extended part of the delay line cannot 065 possibly be initialized with previously consumed data because that 066 data has not been saved. Unless this actor were to save <i>all</i> 067 previously consumed data (which would be hopelessly inefficient), there 068 is no way it can be assured of always having the requisite data. 069 Thus, the actor initializes the extended part of the delay line 070 with zeros of the same type as the input data. 071 072 @author Edward A. Lee, Yuhong Xiong 073 @version $Id$ 074 @since Ptolemy II 1.0 075 @Pt.ProposedRating Yellow (neuendor) 076 @Pt.AcceptedRating Yellow (neuendor) 077 078 @see ptolemy.data.Token 079 */ 080public class VariableFIR extends FIR { 081 /** Construct an actor with the given container and name. 082 * @param container The container. 083 * @param name The name of this actor. 084 * @exception IllegalActionException If the actor cannot be contained 085 * by the proposed container. 086 * @exception NameDuplicationException If the container already has an 087 * actor with this name. 088 */ 089 public VariableFIR(CompositeEntity container, String name) 090 throws NameDuplicationException, IllegalActionException { 091 super(container, name); 092 093 blockSize = new Parameter(this, "blockSize"); 094 blockSize.setExpression("1"); 095 096 newTaps = new TypedIOPort(this, "newTaps"); 097 newTaps.setInput(true); 098 099 newTaps.setTypeSameAs(taps); 100 101 // The taps parameter is no longer of any use, so it is hidden. 102 taps.setVisibility(Settable.NONE); 103 104 output.setTypeSameAs(input); 105 106 output_tokenProductionRate.setExpression("interpolation * blockSize"); 107 input_tokenConsumptionRate.setExpression("decimation * blockSize"); 108 } 109 110 /////////////////////////////////////////////////////////////////// 111 //// public variables //// 112 113 /** The number of inputs that use each each coefficient set is the 114 * value of this parameter multiplied by the value of the 115 * <i>decimation</i> parameter. 116 * This is an integer that defaults to 1. 117 */ 118 public Parameter blockSize; 119 120 /** The input for new tap values. This is an array. 121 */ 122 public TypedIOPort newTaps; 123 124 /////////////////////////////////////////////////////////////////// 125 //// public methods //// 126 127 /** Set a flag that causes recalculation of various local variables 128 * that are used in execution on the next invocation of fire(). 129 * @param attribute The attribute that changed. 130 * @exception IllegalActionException If the attribute contains 131 * an invalid value or if the super method throws it. 132 */ 133 @Override 134 public void attributeChanged(Attribute attribute) 135 throws IllegalActionException { 136 super.attributeChanged(attribute); 137 138 if (attribute == interpolation || attribute == decimation 139 || attribute == blockSize) { 140 _reinitializeNeeded = true; 141 } 142 } 143 144 /** Clone the actor into the specified workspace. This calls the 145 * base class and then resets the type constraints. 146 * @param workspace The workspace for the new object. 147 * @return A new actor. 148 * @exception CloneNotSupportedException If a derived class contains 149 * an attribute that cannot be cloned. 150 */ 151 @Override 152 public Object clone(Workspace workspace) throws CloneNotSupportedException { 153 VariableFIR newObject = (VariableFIR) super.clone(workspace); 154 155 newObject.newTaps.setTypeSameAs(newObject.taps); 156 newObject.output.setTypeSameAs(newObject.input); 157 return newObject; 158 } 159 160 /** Consume the inputs and produce the outputs of the FIR filter. 161 * @exception IllegalActionException If parameter values are invalid, 162 * or if there is no director, or if runtime type conflicts occur. 163 */ 164 @Override 165 public void fire() throws IllegalActionException { 166 if (newTaps.hasToken(0)) { 167 ArrayToken tapsToken = (ArrayToken) newTaps.get(0); 168 _taps = tapsToken.arrayValue(); 169 170 // Get a token representing zero in the appropriate type. 171 _zero = _taps[0].zero(); 172 173 _reinitialize(); 174 } 175 176 int blockSizeValue = ((IntToken) blockSize.getToken()).intValue(); 177 178 for (int i = 0; i < blockSizeValue; i++) { 179 super.fire(); 180 } 181 } 182 183 /** Return false if the input does not have enough tokens to fire. 184 * Otherwise, return true. 185 * @return False if the number of input tokens available is not at least 186 * equal to the <i>decimation</i> parameter multiplied by the 187 * <i>blockSize</i> parameter. 188 * @exception IllegalActionException If the superclass throws it. 189 */ 190 @Override 191 public boolean prefire() throws IllegalActionException { 192 // If an attribute has changed since the last fire(), or if 193 // this is the first fire(), then reinitialize. 194 if (_reinitializeNeeded) { 195 _reinitialize(); 196 } 197 198 if (newTaps.hasToken(0)) { 199 return super.prefire(); 200 } else { 201 if (_debugging) { 202 _debug("Called prefire(), which returns false."); 203 } 204 205 return false; 206 } 207 } 208}