001/* An actor that repeats each input sample a specified number of times. 002 003 Copyright (c) 1997-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.parameters.PortParameter; 031import ptolemy.data.IntToken; 032import ptolemy.data.Token; 033import ptolemy.data.expr.Parameter; 034import ptolemy.kernel.CompositeEntity; 035import ptolemy.kernel.util.Attribute; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038 039/////////////////////////////////////////////////////////////////// 040//// Repeat 041 042/** 043 An actor that repeats a block of input tokens the specified number of times 044 on the output. On each firing, it reads <i>blockSize</i> tokens 045 and repeats each block <i>numberOfTimes</i> times 046 on the output. Note that this causes a sample rate increase by 047 a factor of <i>numberOfTimes</i>, 048 and hence affects the number of invocations of downstream actors. 049 If the input does not have enough tokens, then this actor does 050 nothing. If <i>blockSize</i> or <i>numberOfTimes</i> is zero, 051 then it produces no outputs. 052 053 @author Shankar Rao, Steve Neuendorffer 054 @version $Id$ 055 @since Ptolemy II 1.0 056 @Pt.ProposedRating Yellow (neuendor) 057 @Pt.AcceptedRating Yellow (neuendor) 058 */ 059public class Repeat extends SDFTransformer { 060 /** Construct an actor in the specified container with the specified 061 * name. 062 * @param container The container. 063 * @param name The name of this Repeat actor within the container. 064 * @exception IllegalActionException If the actor cannot be contained 065 * by the proposed container. 066 * @exception NameDuplicationException If the name coincides with 067 * an actor already in the container. 068 */ 069 public Repeat(CompositeEntity container, String name) 070 throws IllegalActionException, NameDuplicationException { 071 super(container, name); 072 073 // parameters 074 numberOfTimes = new PortParameter(this, "numberOfTimes", 075 new IntToken(2)); 076 077 blockSize = new Parameter(this, "blockSize", new IntToken(1)); 078 079 input_tokenConsumptionRate.setExpression("blockSize"); 080 output_tokenProductionRate.setExpression("numberOfTimes*blockSize"); 081 } 082 083 /////////////////////////////////////////////////////////////////// 084 //// ports and parameters //// 085 086 /** The repetition factor. It is of type integer and has a default 087 * value of 2. It must be greater than zero. 088 */ 089 public PortParameter numberOfTimes; 090 091 /** The number of tokens in a block. It is of type integer and has a 092 * default value of 1. It must be greater than zero. 093 */ 094 public Parameter blockSize; 095 096 /////////////////////////////////////////////////////////////////// 097 //// public methods //// 098 099 /** Ensure that the numberOfTimes parameter and the blockSize 100 * parameter are both positive. 101 * @param attribute The attribute that has changed. 102 * @exception IllegalActionException If the parameters are out of range. 103 */ 104 @Override 105 public void attributeChanged(Attribute attribute) 106 throws IllegalActionException { 107 108 if (attribute == numberOfTimes || attribute == blockSize) { 109 int repetitions = ((IntToken) numberOfTimes.getToken()).intValue(); 110 int count = ((IntToken) blockSize.getToken()).intValue(); 111 112 if (repetitions < 0) { 113 throw new IllegalActionException(numberOfTimes, 114 "The value of numberOfTimes must be positive, but " 115 + "was set to " + repetitions); 116 } 117 118 if (count < 1) { 119 throw new IllegalActionException(blockSize, 120 "The value of blockSize must be positive, but " 121 + "was set to " + count); 122 } 123 } else { 124 super.attributeChanged(attribute); 125 } 126 } 127 128 /** Consume <i>blockSize</i> input tokens from the input port. 129 * Produce <i>blockSize*numberOfTimes</i> 130 * tokens on the output port, consisting of <i>numberOfTimes</i> 131 * repetitions of the input. For example, if <i>blockSize</i> = 3 and 132 * <i>numberOfTimes</i> = 2, then on the following input:<br> 133 * <pre> 1 2 3 4 5 6</pre><br> 134 * two invocations of this method will send the following output:<br> 135 * <pre> 1 2 3 1 2 3 4 5 6 4 5 6</pre><br> 136 * @exception IllegalActionException If there is no director. 137 */ 138 @Override 139 public void fire() throws IllegalActionException { 140 super.fire(); 141 142 numberOfTimes.update(); 143 int repetitions = ((IntToken) numberOfTimes.getToken()).intValue(); 144 int count = ((IntToken) blockSize.getToken()).intValue(); 145 if (input.hasToken(0, count)) { 146 Token[] inputBlock = input.get(0, count); 147 148 for (int i = 0; i < repetitions; i += 1) { 149 output.send(0, inputBlock, count); 150 } 151 } 152 } 153}