Skip to content

Commit

Permalink
plugins/dac: add data gui strategy to add and link buffer UI elements.
Browse files Browse the repository at this point in the history
Signed-off-by: AlexandraTrifan <Alexandra.Trifan@analog.com>
  • Loading branch information
AlexandraTrifan committed Jul 12, 2024
1 parent 9ee73b4 commit 15bcc68
Show file tree
Hide file tree
Showing 17 changed files with 834 additions and 157 deletions.
508 changes: 459 additions & 49 deletions plugins/dac/doc/dacplugin.qmodel

Large diffs are not rendered by default.

49 changes: 29 additions & 20 deletions plugins/dac/src/bufferdacaddon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <menusectionwidget.h>
#include <menucollapsesection.h>
#include <progresslineedit.h>
#include <titlespinbox.h>
#include <menulineedit.h>
#include <menuonoffswitch.h>
Expand Down Expand Up @@ -65,7 +64,6 @@ BufferDacAddon::BufferDacAddon(DacDataModel *model, QWidget *parent)
connect(fm, &FileBrowser::load, this, &BufferDacAddon::load);

MenuSectionWidget *channelsSection = new MenuSectionWidget(this);
// channelsSection->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
QLabel *channelsLbl = new QLabel("Channels");
StyleHelper::MenuSmallLabel(channelsLbl);

Expand All @@ -77,7 +75,6 @@ BufferDacAddon::BufferDacAddon(DacDataModel *model, QWidget *parent)
channelsContainer->setLayout(channelsContainerLayout);

QScrollArea *scrollArea = new QScrollArea(channelsSection);
// scrollArea->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(channelsContainer);

Expand All @@ -95,23 +92,13 @@ BufferDacAddon::BufferDacAddon(DacDataModel *model, QWidget *parent)
chnBtn->setOpenMenuChecksThis(true);
chnBtn->setCheckable(true);
chnBtn->setChecked(false);
channelsContainerLayout->addWidget(chnBtn);
i++;
}
for (TxNode *node : lst) {
MenuControlButton *chnBtn = new MenuControlButton(this);
chnBtn->setName(node->getUuid());
chnBtn->setCheckBoxStyle(MenuControlButton::CS_CIRCLE);
chnBtn->setColor(StyleHelper::getColor("CH" + QString::number(i)));
chnBtn->setDoubleClickToOpenMenu(true);
chnBtn->setOpenMenuChecksThis(true);
chnBtn->setCheckable(true);
chnBtn->setChecked(false);
connect(chnBtn->checkBox(), &QCheckBox::toggled, this, [=,this] (bool toggled) {
m_model->enableBufferChannel(node->getUuid(), toggled);
});
channelsContainerLayout->addWidget(chnBtn);
i++;
}


QWidget *topSection = new QWidget(this);
auto topLayout = new QHBoxLayout();
topSection->setLayout(topLayout);
Expand All @@ -123,6 +110,7 @@ BufferDacAddon::BufferDacAddon(DacDataModel *model, QWidget *parent)

m_layout->addWidget(topSection);
m_layout->addWidget(bufferConfigContainer);
m_layout->addWidget(m_optionalGuiStrategy);
}

BufferDacAddon::~BufferDacAddon()
Expand All @@ -136,10 +124,23 @@ void BufferDacAddon::load(QString path)
// handle deletion and cleanup
delete m_dataBuffer;
}
if (m_optionalGuiStrategy) {
delete m_optionalGuiStrategy;
}
m_optionalGuiStrategy = new QWidget(this);
auto optGuiStrLay = new QHBoxLayout();
m_optionalGuiStrategy->setLayout(optGuiStrLay);

m_dataBuffer = DataBufferBuilder()
.dataStrategy(DataBufferBuilder::FileStrategy)
.file(path).ui(true).parent(this).build();
.guiStrategy(DataBufferBuilder::FileGuiStrategy)
.file(path).parent(this).build();

auto guiStrWidget = m_dataBuffer->getDataGuiStrategyInterface()->ui();
if (guiStrWidget) {
optGuiStrLay->addWidget(guiStrWidget);
}
dynamic_cast<QBoxLayout*>(layout())->addWidget(m_optionalGuiStrategy);

// test
loadData();
Expand All @@ -161,13 +162,21 @@ void BufferDacAddon::chooseFile()

void BufferDacAddon::runBtnToggled(bool toggled)
{
// data buffer already configured buffersize and other stuff
m_model->push(m_dataBuffer->getDataBufferStrategy()->data());
if (!m_dataBuffer) {
return;
}
// data buffer already configured buffersize
if (toggled) {
auto data = m_dataBuffer->getDataBufferStrategy()->data();
auto bufsize = data.at(0).size();
m_model->push(data, bufsize);
} else {
m_model->stop();
}
}

void BufferDacAddon::loadData()
{
qDebug(CAT_DAC_BUFFER) << m_dataBuffer->getDataBufferStrategy()->data()[0];
}

//void BufferDacAddon::setupFileSection()
1 change: 1 addition & 0 deletions plugins/dac/src/bufferdacaddon.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ private Q_SLOTS:
void load(QString path);
private:
DacDataModel *m_model;
QWidget *m_optionalGuiStrategy;
ProgressLineEdit *m_fileBufferPath;
QPushButton *m_fileBufferBrowseBtn;
QPushButton *m_fileBufferLoadBtn;
Expand Down
64 changes: 62 additions & 2 deletions plugins/dac/src/csvfilestrategy.cpp
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
#include "csvfilestrategy.h"
#include "dac_logging_categories.h"

#include <float.h>
#include <qmath.h>

#include <QString>
#include <QVector>
#include <QFile>

#define SCALE_MINUS_INFINITE -91

using namespace scopy;
CSVFileStrategy::CSVFileStrategy(QString filename, QWidget *parent)
: QWidget(parent)
{
m_filename = filename;
m_separator = ",";
m_recipe = {.scale = 0.0, .scaled = false};
loadFile();
// tbd thread?
}

QVector<QVector<double>> CSVFileStrategy::data()
{
return m_data;
return m_dataConverted;
}

void CSVFileStrategy::recipeUpdated(DataBufferRecipe recipe)
{
m_recipe = recipe;
applyConversion();
}

void CSVFileStrategy::loadFile()
{
double max = 0.0;
QVector<QVector<QString>> raw_data;
bool dataOk = true;
QFile file(m_filename);
Expand Down Expand Up @@ -49,17 +62,64 @@ void CSVFileStrategy::loadFile()

// suppose no m_data in the file
m_data.resize(raw_data.size());
m_dataConverted.resize(raw_data.size());
for(int i = 0; i < m_data.size(); ++i) {
m_data[i].resize(raw_data[i].size());
m_dataConverted[i].resize(raw_data[i].size());
}

for(int i = 0; i < raw_data.size(); ++i) {
for(int j = 0; j < raw_data[i].size(); ++j) {
m_data[i][j] = raw_data[i][j].toDouble(&dataOk);
double tmp = raw_data[i][j].toDouble(&dataOk);
if(!dataOk) {
qDebug(CAT_DAC_DATASTRATEGY) << "File is corrupted";
return;
}
m_data[i][j] = tmp;
m_max = (tmp > m_max) ? tmp : m_max;
}
}

// convert all here;
applyConversion();


}

void CSVFileStrategy::applyConversion()
{
for (int i = 0; i < m_data.size(); i++) {
for (int j = 0; j < m_data[i].size(); j++) {
m_dataConverted[i][j] = convert(m_data[i][j]);
}
}
}

double CSVFileStrategy::convert(double value)
{
// TBD check if m_recipe exists
double scale = 0.0;
double offset = 0.0;
double full_scale = dbFullScaleConvert(m_recipe.scale, false);
if (!m_recipe.scaled) {
scale = 16.0;
}
if (scale == 0.0) {
scale = 32767.0 * full_scale / m_max;
}

return (value * scale + offset);
}

double CSVFileStrategy::dbFullScaleConvert(double scale, bool inverse)
{
if (inverse) {
if (scale == 0)
return -DBL_MAX;
return (int)((20 * log10(scale)) - 0.5);
} else {
if (scale == SCALE_MINUS_INFINITE)
return 0;
return pow(10, scale / 20.0);
}
}
11 changes: 10 additions & 1 deletion plugins/dac/src/csvfilestrategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,23 @@ class SCOPY_DAC_EXPORT CSVFileStrategy : public QWidget, public DataBufferStrate

QVector<QVector<double>> data() override;

public Q_SLOTS:
void recipeUpdated(DataBufferRecipe) override;

Q_SIGNALS:
void loadFinished();
void loadFinished() override;

private:
double m_max;
QString m_filename;
QString m_separator;
QVector<QVector<double>> m_data;
QVector<QVector<double>> m_dataConverted;
DataBufferRecipe m_recipe;
void loadFile();
double dbFullScaleConvert(double scale, bool inverse);
double convert(double value);
void applyConversion();
};
} //namespace scopy
#endif // CSVFILESTRATEGY_H
75 changes: 74 additions & 1 deletion plugins/dac/src/dacdatamodel.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "dacdatamodel.h"
#include "txnode.h"
#include "dac_logging_categories.h"

#include <QDebug>

using namespace scopy;
Expand All @@ -9,6 +11,8 @@ DacDataModel::DacDataModel(struct iio_device *dev, QObject *parent)
, m_bufferTxs({})
, m_activeDds(false)
, m_activeBuffer(false)
, m_buffer(nullptr)
, m_cyclicBuffer(true)
{
m_dev = dev;
m_name = iio_device_get_name(m_dev);
Expand Down Expand Up @@ -76,7 +80,20 @@ void DacDataModel::setCyclic(bool cyclic)
m_cyclicBuffer = cyclic;
}

void DacDataModel::push(QVector<QVector<double> > data)
void DacDataModel::enableBufferChannel(QString uuid, bool enable)
{
auto chn = m_bufferTxs.value(uuid)->getChannel();
if (!chn) {
// qdebug error
}
if (enable) {
iio_channel_enable(chn);
} else {
iio_channel_disable(chn);
}
}

void DacDataModel::push(QVector<QVector<double> > data, unsigned int buffersize)
{
if (!m_isBufferCapable) {
// qDebug(CAT_DA) << "Not buffer capable."
Expand All @@ -85,10 +102,66 @@ void DacDataModel::push(QVector<QVector<double> > data)
if (!m_activeBuffer) {
// qDebug() << "Buffer mode not activated"
}

if (m_buffer) {
// stop? cancel?
iio_buffer_destroy(m_buffer);
m_buffer = nullptr;
}
// 1. destroy old buffer
// 2. enable channels
// 3. get sample size

ssize_t s_size = iio_device_get_sample_size(m_dev);
if (!s_size) {
qDebug(CAT_DAC_DATA) << "Unable to create buffer due to sample size";
return;
}

// size % manager->alignment != 0 || size % s_size
if ( buffersize == 0) {
qDebug(CAT_DAC_DATA) << "Unable to create buffer due to sample size and number of samples";
return;
}

m_buffer = iio_device_create_buffer(m_dev, buffersize, m_cyclicBuffer);
if (!m_buffer) {
qDebug(CAT_DAC_DATA) << "Unable to create buffer: %s\n" << strerror(errno);
return;
}

// interleave channels
QVector<double> allData = {};
for (int i = 0; i < data[0].size(); i++) {
for (auto chn : qAsConst(data)) {
allData.append(chn[i]);
}

}

memcpy(iio_buffer_start(m_buffer), allData.data(),
(char*)iio_buffer_end(m_buffer) - (char*)iio_buffer_start(m_buffer));

iio_buffer_push(m_buffer);
qDebug(CAT_DAC_DATA) << "Waveform loaded successfully.";

// tbd create a buffer config structure
// iio_device_create_buffer(m_dev, buffersize, m_cyclic);
}

void DacDataModel::stop()
{
if (!m_isBufferCapable) {
// qDebug(CAT_DA) << "Not buffer capable."
return;
}
if (m_buffer) {
// stop? cancel?
iio_buffer_destroy(m_buffer);
m_buffer = nullptr;
}
}

bool DacDataModel::initBufferDac()
{
unsigned int txCount = 0;
Expand Down
6 changes: 4 additions & 2 deletions plugins/dac/src/dacdatamodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ class DacDataModel : public QObject

void setCyclic(bool cyclic);

void push(QVector<QVector<double>> data);
// void enableChannel()
void enableBufferChannel(QString uuid, bool enable);
void push(QVector<QVector<double> > data, unsigned int buffersize);
void stop();
private:
struct iio_device *m_dev;
QString m_name;
QList<struct iio_channel*> m_channels;
struct iio_buffer *m_buffer;

bool m_isBufferCapable;
bool m_isDds;
Expand Down
Loading

0 comments on commit 15bcc68

Please sign in to comment.