Unfortunately, there is still a problem with decimation in
ptolemy.domains.sdf.lib.FIR.  Below is a small moml example that
demonstrates the problem.  The example taps are {0,0,0,0,1,1/2,1/4,1/8} with
interpolation=4, decimation=2 The current code outputs the first two
non-zero outputs TWICE as a response to a single dirac input.  The correct
ouput would be two zeros followed by two non-zero samples of the impulse
response.

The problem happens when decimation > 1. In the current FIR.fire() code,
...
        int phase = _dec - _decPhase - 1;

        // Interpolate once for each input consumed
        for (int inC = 1; inC <= _dec; inC++) {

            if (--_mostRecent < 0) _mostRecent = _data.length - 1;
            _data[_mostRecent] = input.get(0);

            // Produce however many outputs are required
            // for each input consumed
            while (phase < _interp) {
                _outToken = _zero;

                // Compute the inner product.
                for (int i = 0; i < _phaseLength; i++) {
                    int tapsIndex = i * _interp + phase;

                    int dataIndex =
                        (_mostRecent + _dec - inC + i)%(_data.length);
...
this last line of code expects _dec inputs in _data[]et starting at
_mostRecent to _mostRecent+_dec-1. However, as inC iterates 1,2...,_dec,
only 1,2,... input samples are present in _data[] starting at _mostRecent,
so dataIndex will be incorrect.

The dataIndex expression corresponds to the one in Ptolemy Classic, where
the SDF scheduler made sure that there were _dec new inputs in the input
port buffer before fire() would be called (an FIR fire() consumes decimation
inputs, and produces interpolation outputs). To achieve the same setup in
PtolemyII's FIR.java, we should do something like:

...
        int phase = _dec - _decPhase - 1;

        // Transfer _dec inputs to _data[]
        for (int inC = 1; inC <= _dec; inC++) {
            if (--_mostRecent < 0) _mostRecent = _data.length - 1;
            _data[_mostRecent] = input.get(0);
        }

        // Interpolate once for each input consumed
        for (int inC = 1; inC <= _dec; inC++) {

            // Produce however many outputs are required
            // for each input consumed
            while (phase < _interp) {
                _outToken = _zero;

                // Compute the inner product.
                for (int i = 0; i < _phaseLength; i++) {
                    int tapsIndex = i * _interp + phase;

                    int dataIndex =
                        (_mostRecent + _dec - inC + i)%(_data.length);
...
to get the same (correct) operation.  This also requires

        if (_data == null || _data.length != _phaseLength) {
            _data = new Token[_phaseLength];
            for(int i = 0; i < _phaseLength; i++ ) {
                _data[i] = _zero;
            }
        }

in _reinitialize() to be replaced by something like:

        int L = (int)Math.max(_phaseLength,_dec);
        if (_data == null || _data.length != L) {
            _data = new Token[L];
            for(int i = 0; i < L; i++ ) {
                _data[i] = _zero;
            }
        }

since, in the example below, we could set decimation to 4, in which case
_dec = 4 is > _phaseLength = 2, and we need to store the last _dec input
samples at the beginning of fire().

Regards,
Zoltan Kemenczy
Research in Motion Limited
295 Phillip St., Waterloo, Ontario Canada N2L 3W8
----------------------------------------------------------------------------
--------------------------------------------------------------

<?xml version="1.0" standalone="no"?>
<!DOCTYPE entity PUBLIC "-//UC Berkeley//DTD MoML 1//EN"
    "http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd";>
<entity name="firbug2" class="ptolemy.actor.TypedCompositeActor">
    <property name="_vergilSize" class="ptolemy.actor.gui.SizeAttribute"
value="[600, 450]">
    </property>
    <property name="_vergilLocation"
class="ptolemy.actor.gui.LocationAttribute" value="[230, 228]">
    </property>
    <property name="SDF" class="ptolemy.domains.sdf.kernel.SDFDirector">
        <property name="Scheduler"
class="ptolemy.domains.sdf.kernel.SDFScheduler">
        </property>
        <property name="iterations" class="ptolemy.data.expr.Parameter"
value="2">
        </property>
        <property name="vectorizationFactor"
class="ptolemy.data.expr.Parameter" value="1">
        </property>
        <property name="_location" class="ptolemy.moml.Location"
value="80.0, 34.5">
        </property>
    </property>
    <entity name="FIR" class="ptolemy.domains.sdf.lib.FIR">
        <property name="decimation" class="ptolemy.data.expr.Parameter"
value="2">
        </property>
        <property name="decimationPhase" class="ptolemy.data.expr.Parameter"
value="1">
        </property>
        <property name="interpolation" class="ptolemy.data.expr.Parameter"
value="4">
        </property>
        <property name="taps" class="ptolemy.data.expr.Parameter"
value="{0.0,0.0,0.0,0.0,1.0,0.5,0.24,0.125}">
        </property>
        <property name="_location" class="ptolemy.moml.Location"
value="165.0, 140.0">
        </property>
        <port name="input" class="ptolemy.domains.sdf.kernel.SDFIOPort">
            <property name="input"/>
            <property name="tokenConsumptionRate"
class="ptolemy.data.expr.Parameter" value="2">
            </property>
            <property name="tokenInitProduction"
class="ptolemy.data.expr.Parameter" value="0">
            </property>
            <property name="tokenProductionRate"
class="ptolemy.data.expr.Parameter" value="0">
            </property>
        </port>
        <port name="output" class="ptolemy.domains.sdf.kernel.SDFIOPort">
            <property name="output"/>
            <property name="tokenConsumptionRate"
class="ptolemy.data.expr.Parameter" value="0">
            </property>
            <property name="tokenInitProduction"
class="ptolemy.data.expr.Parameter" value="0">
            </property>
            <property name="tokenProductionRate"
class="ptolemy.data.expr.Parameter" value="4">
            </property>
        </port>
    </entity>
    <entity name="SequencePlotter"
class="ptolemy.actor.lib.gui.SequencePlotter">
        <property name="fillOnWrapup" class="ptolemy.data.expr.Parameter"
value="true">
        </property>
        <property name="legend" class="ptolemy.kernel.util.StringAttribute">
        </property>
        <property name="startingDataset" class="ptolemy.data.expr.Parameter"
value="0">
        </property>
        <property name="xInit" class="ptolemy.data.expr.Parameter"
value="0.0">
        </property>
        <property name="xUnit" class="ptolemy.data.expr.Parameter"
value="1.0">
        </property>
        <property name="_location" class="ptolemy.moml.Location"
value="274.5, 138.5">
        </property>
        <port name="input" class="ptolemy.actor.TypedIOPort">
            <property name="input"/>
            <property name="multiport"/>
        </port>
        <configure><?plotml
<!DOCTYPE plot PUBLIC "-//UC Berkeley//DTD PlotML 1//EN"
"http://ptolemy.eecs.berkeley.edu/xml/dtd/PlotML_1.dtd";>
<plot>
<title>SequencePlotter</title> <xLabel></xLabel> <yLabel></yLabel> <xRange
min="0.0" max="7.0"/> <yRange min="0.0" max="1.0"/> <default connected="no"
marks="dots"/> </plot>?>
        </configure>
    </entity>
    <entity name="Pulse" class="ptolemy.actor.lib.Pulse">
        <property name="firingCountLimit"
class="ptolemy.data.expr.Parameter" value="0">
        </property>
        <property name="indexes" class="ptolemy.data.expr.Parameter"
value="[0:1:9].toArray()">
        </property>
        <property name="values" class="ptolemy.data.expr.Parameter"
value="[1,0,0,0,0,0,0,0,0,0].toArray()">
        </property>
        <property name="repeat" class="ptolemy.data.expr.Parameter"
value="false">
        </property>
        <property name="_location" class="ptolemy.moml.Location"
value="65.0, 139.5">
        </property>
        <port name="output" class="ptolemy.actor.TypedIOPort">
            <property name="output"/>
        </port>
        <port name="trigger" class="ptolemy.actor.TypedIOPort">
            <property name="input"/>
            <property name="multiport"/>
        </port>
    </entity>
    <relation name="relation2" class="ptolemy.actor.TypedIORelation">
        <property name="bufferSize" class="ptolemy.data.expr.Parameter"
value="4">
        </property>
    </relation>
    <relation name="relation" class="ptolemy.actor.TypedIORelation">
        <property name="bufferSize" class="ptolemy.data.expr.Parameter"
value="2">
        </property>
    </relation>
    <link port="FIR.input" relation="relation"/>
    <link port="FIR.output" relation="relation2"/>
    <link port="SequencePlotter.input" relation="relation2"/>
    <link port="Pulse.output" relation="relation"/>
</entity>

----------------------------------------------------------------------------
Posted to the ptolemy-hackers mailing list.  Please send administrative
mail for this list to: [EMAIL PROTECTED]

Reply via email to