Files @ 262f56d3e063
Branch filter:

Location: tempo-plotter/src/stream.cpp - annotation

Hasan Yavuz ÖZDERYA
support multi plot and channel visibility for value tracker
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
f7670384fcb0
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
7dd5ac90961f
7dd5ac90961f
391ab62116c8
391ab62116c8
391ab62116c8
f7670384fcb0
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
fe286d8bd071
fe286d8bd071
fe286d8bd071
fe286d8bd071
fe286d8bd071
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
5c0005f331cf
5c0005f331cf
5c0005f331cf
5c0005f331cf
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
262f56d3e063
1e7920e956a9
1e7920e956a9
1e7920e956a9
1e7920e956a9
1e7920e956a9
68f79a7c6762
68f79a7c6762
68f79a7c6762
68f79a7c6762
68f79a7c6762
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
7dd5ac90961f
7dd5ac90961f
391ab62116c8
391ab62116c8
391ab62116c8
f7670384fcb0
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
fe286d8bd071
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f5271e6d0ce0
391ab62116c8
6b14ef397a98
6b14ef397a98
6b14ef397a98
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
6b14ef397a98
6b14ef397a98
6b14ef397a98
f5271e6d0ce0
f5271e6d0ce0
6b14ef397a98
f5271e6d0ce0
6b14ef397a98
6b14ef397a98
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
391ab62116c8
391ab62116c8
391ab62116c8
f5271e6d0ce0
5c0005f331cf
391ab62116c8
7dd5ac90961f
7dd5ac90961f
7dd5ac90961f
391ab62116c8
f5271e6d0ce0
f5271e6d0ce0
6b14ef397a98
6b14ef397a98
6b14ef397a98
f5271e6d0ce0
cd99f9b81da2
391ab62116c8
f5271e6d0ce0
f5271e6d0ce0
f5271e6d0ce0
391ab62116c8
391ab62116c8
f5271e6d0ce0
d92b6daade5d
f5271e6d0ce0
d92b6daade5d
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
8554454db965
8554454db965
8554454db965
8554454db965
8554454db965
8554454db965
8554454db965
8554454db965
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
5c0005f331cf
391ab62116c8
391ab62116c8
391ab62116c8
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
f7670384fcb0
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
391ab62116c8
/*
  Copyright © 2018 Hasan Yavuz Özderya

  This file is part of serialplot.

  serialplot is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  serialplot is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "stream.h"
#include "ringbuffer.h"
#include "indexbuffer.h"
#include "linindexbuffer.h"

Stream::Stream(unsigned nc, bool x, unsigned ns) :
    _infoModel(nc)
{
    _numSamples = ns;
    _paused = false;

    xAsIndex = true;
    xMin = 0;
    xMax = 1;

    // create xdata buffer
    _hasx = x;
    if (x)
    {
        // TODO: implement XRingBuffer (binary search)
        Q_ASSERT(false);
    }
    else
    {
        xData = makeXBuffer();
    }

    // create channels
    for (unsigned i = 0; i < nc; i++)
    {
        auto c = new StreamChannel(i, xData, new RingBuffer(ns), &_infoModel);
        channels.append(c);
    }
}

Stream::~Stream()
{
    for (auto ch : channels)
    {
        delete ch;
    }
    delete xData;
}

bool Stream::hasX() const
{
    return _hasx;
}

unsigned Stream::numChannels() const
{
    return channels.length();
}

unsigned Stream::numSamples() const
{
    return _numSamples;
}

const StreamChannel* Stream::channel(unsigned index) const
{
    Q_ASSERT(index < numChannels());
    return channels[index];
}

StreamChannel* Stream::channel(unsigned index)
{
    return const_cast<StreamChannel*>(static_cast<const Stream&>(*this).channel(index));
}

QVector<const StreamChannel*> Stream::allChannels() const
{
    QVector<const StreamChannel*> result(numChannels());
    for (unsigned ci = 0; ci < numChannels(); ci++)
    {
        result[ci] = channel(ci);
    }
    return result;
}

const ChannelInfoModel* Stream::infoModel() const
{
    return &_infoModel;
}

ChannelInfoModel* Stream::infoModel()
{
    return const_cast<ChannelInfoModel*>(static_cast<const Stream&>(*this).infoModel());
}

void Stream::setNumChannels(unsigned nc, bool x)
{
    unsigned oldNum = numChannels();
    if (oldNum == nc && x == _hasx) return;

    // adjust the number of channels
    if (nc > oldNum)
    {
        for (unsigned i = oldNum; i < nc; i++)
        {
            auto c = new StreamChannel(i, xData, new RingBuffer(_numSamples), &_infoModel);
            channels.append(c);
        }
    }
    else if (nc < oldNum)
    {
        for (unsigned i = oldNum-1; i > nc-1; i--)
        {
            delete channels.takeLast();
        }
    }

    // change the xdata
    if (x != _hasx)
    {
        if (x)
        {
            // TODO: implement XRingBuffer (binary search)
            Q_ASSERT(false);
        }
        else
        {
            xData = makeXBuffer();
        }

        for (auto c : channels)
        {
            c->setX(xData);
        }
        _hasx = x;
    }

    if (nc != oldNum)
    {
        _infoModel.setNumOfChannels(nc);
        // TODO: how about X change?
        emit numChannelsChanged(nc);
    }

    Sink::setNumChannels(nc, x);
}

XFrameBuffer* Stream::makeXBuffer() const
{
    if (xAsIndex)
    {
        return new IndexBuffer(_numSamples);
    }
    else
    {
        return new LinIndexBuffer(_numSamples, xMin, xMax);
    }
}

const SamplePack* Stream::applyGainOffset(const SamplePack& pack) const
{
    Q_ASSERT(infoModel()->gainOrOffsetEn());

    SamplePack* mPack = new SamplePack(pack);
    unsigned ns = pack.numSamples();

    for (unsigned ci = 0; ci < numChannels(); ci++)
    {
        // TODO: we could use some kind of map (int32, int64 would suffice) to speed things up
        bool gainEn = infoModel()->gainEn(ci);
        bool offsetEn = infoModel()->offsetEn(ci);
        if (gainEn || offsetEn)
        {
            double* mdata = mPack->data(ci);

            double gain = infoModel()->gain(ci);
            double offset = infoModel()->offset(ci);

            if (gainEn)
            {
                for (unsigned i = 0; i < ns; i++)
                {
                    mdata[i] *= gain;
                }
            }
            if (offsetEn)
            {
                for (unsigned i = 0; i < ns; i++)
                {
                    mdata[i] += offset;
                }
            }
        }
    }

    return mPack;
}

void Stream::feedIn(const SamplePack& pack)
{
    Q_ASSERT(pack.numChannels() == numChannels() &&
             pack.hasX() == hasX());

    if (_paused) return;

    unsigned ns = pack.numSamples();
    if (_hasx)
    {
        // TODO: implement XRingBuffer (binary search)
        Q_ASSERT(false);
        // static_cast<RingBuffer*>(xData)->addSamples(pack.xData(), ns);
    }

    // modified pack that gain and offset is applied to
    const SamplePack* mPack = nullptr;
    if (infoModel()->gainOrOffsetEn())
        mPack = applyGainOffset(pack);

    for (unsigned ci = 0; ci < numChannels(); ci++)
    {
        auto buf = static_cast<RingBuffer*>(channels[ci]->yData());
        double* data = (mPack == nullptr) ? pack.data(ci) : mPack->data(ci);
        buf->addSamples(data, ns);
    }

    Sink::feedIn((mPack == nullptr) ? pack : *mPack);

    if (mPack != nullptr) delete mPack;
    emit dataAdded();
}

void Stream::pause(bool paused)
{
    _paused = paused;
}

void Stream::clear()
{
    for (auto c : channels)
    {
        static_cast<RingBuffer*>(c->yData())->clear();
    }
}

void Stream::setNumSamples(unsigned value)
{
    if (value == _numSamples) return;
    _numSamples = value;

    xData->resize(value);
    for (auto c : channels)
    {
        static_cast<RingBuffer*>(c->yData())->resize(value);
    }
}

void Stream::setXAxis(bool asIndex, double min, double max)
{
    xAsIndex = asIndex;
    xMin = min;
    xMax = max;

    // Note that x axis scaling is ignored when X is provided from source as data
    // TODO: assert (UI options for x axis should be disabled)
    if (!hasX())
    {
        xData = makeXBuffer();
        for (auto c : channels)
        {
            c->setX(xData);
        }
    }
}

void Stream::saveSettings(QSettings* settings) const
{
    _infoModel.saveSettings(settings);
}

void Stream::loadSettings(QSettings* settings)
{
    _infoModel.loadSettings(settings);
}