27 #include <QButtonGroup> 28 #include <QRadioButton> 35 #include <qwt_plot_renderer.h> 48 module_panel->updateBlockInfo();
51 module_panel->updateBlockChannels(
52 std::any_cast<RT::Thread*>(event->
getParam(
"thread")));
53 module_panel->updateBlockInfo();
56 module_panel->updateBlockChannels(
57 std::any_cast<RT::Device*>(event->
getParam(
"device")));
58 module_panel->updateBlockInfo();
65 void Oscilloscope::Panel::updateChannelScale(
IO::endpoint probe_info)
67 const auto scale = this->scalesList->currentData().value<
double>();
68 this->scopeWindow->setChannelScale(probe_info, scale);
71 void Oscilloscope::Panel::updateChannelOffset(
IO::endpoint probe_info)
73 const double chanoffset = this->offsetsEdit->text().toDouble()
74 * offsetsList->currentData().value<
double>();
75 this->scopeWindow->setChannelOffset(probe_info, chanoffset);
81 pen.setColor(this->colorsList->currentData().value<QColor>());
82 pen.setWidth(this->widthsList->currentData().value<
int>());
83 pen.setStyle(this->stylesList->currentData().value<Qt::PenStyle>());
84 this->scopeWindow->setChannelPen(
endpoint, pen);
87 void Oscilloscope::Panel::updateChannelLabel(
IO::endpoint probe_info)
89 const QString chanlabel = QString::number(probe_info.
block->
getID()) +
" " 91 + this->scalesList->currentText();
93 this->scopeWindow->setChannelLabel(probe_info, chanlabel);
96 void Oscilloscope::Panel::updateWindowTimeDiv()
98 auto divt = this->timesList->currentData().value<int64_t>();
99 this->scopeWindow->setDivT(divt);
102 void Oscilloscope::Panel::enableChannel()
105 if (!this->activateButton->isChecked()) {
110 auto* oscilloscope_plugin =
112 auto* chanblock = this->blocksListDropdown->currentData().value<
IO::Block*>();
113 auto chanport = this->channelsList->currentData().value<
size_t>();
114 auto chandirection = this->typesList->currentData().value<
IO::flags_t>();
120 if (probe_fifo ==
nullptr) {
122 "Oscilloscope::Panel::enableChannel Unable to create probing channel " 124 chanblock->getName());
128 this->scopeWindow->createChannel(
endpoint, probe_fifo);
131 this->updateChannelOffset(
endpoint);
136 void Oscilloscope::Panel::disableChannel()
139 if (!this->activateButton->isChecked()) {
143 auto* oscilloscope_plugin =
145 auto* chanblock = this->blocksListDropdown->currentData().value<
IO::Block*>();
146 auto chanport = this->channelsList->currentData().value<
size_t>();
147 auto chandirection = this->typesList->currentData().value<
IO::flags_t>();
149 const IO::endpoint probe {chanblock, chanport, chandirection};
151 this->scopeWindow->removeChannel(probe);
152 oscilloscope_plugin->deleteProbe(probe);
155 void Oscilloscope::Panel::activateChannel(
bool active)
158 active && blocksListDropdown->count() > 0 && channelsList->count() > 0;
159 scalesList->setEnabled(enable);
160 offsetsEdit->setEnabled(enable);
161 offsetsList->setEnabled(enable);
162 colorsList->setEnabled(enable);
163 widthsList->setEnabled(enable);
164 stylesList->setEnabled(enable);
165 this->activateButton->setChecked(enable);
168 void Oscilloscope::Panel::apply()
170 switch (tabWidget->currentIndex()) {
178 ERROR_MSG(
"Oscilloscope::Panel::showTab : invalid tab\n");
182 void Oscilloscope::Panel::buildChannelList()
184 if (blocksListDropdown->count() <= 0) {
188 if (blocksListDropdown->currentIndex() < 0) {
189 blocksListDropdown->setCurrentIndex(0);
192 auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
193 auto type = this->typesList->currentData().value<
IO::flags_t>();
194 channelsList->clear();
195 for (
size_t i = 0; i < block->getCount(type); ++i) {
196 channelsList->addItem(QString(block->getChannelName(type, i).c_str()),
197 QVariant::fromValue(i));
199 channelsList->setCurrentIndex(0);
203 void Oscilloscope::Panel::showTab(
int index)
213 ERROR_MSG(
"Oscilloscope::Panel::showTab : invalid tab\n");
223 void Oscilloscope::Panel::applyChannelTab()
225 if (this->blocksListDropdown->count() <= 0
226 || this->channelsList->count() <= 0) {
230 auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
231 auto port = this->channelsList->currentData().value<
size_t>();
232 auto type = this->typesList->currentData().value<
IO::flags_t>();
236 this->scopeWindow->setPause(
true);
237 if (!activateButton->isChecked()) {
238 scopeWindow->removeChannel(probeInfo);
239 host_plugin->deleteProbe(probeInfo);
241 if (!this->scopeWindow->channelRegistered(probeInfo)) {
242 RT::OS::Fifo* fifo = host_plugin->createProbe(probeInfo);
243 if (fifo !=
nullptr) {
244 this->scopeWindow->createChannel(probeInfo, fifo);
247 this->updateChannelScale(probeInfo);
248 this->updateChannelOffset(probeInfo);
249 this->updateChannelPen(probeInfo);
250 this->updateChannelLabel(probeInfo);
252 scopeWindow->replot();
253 this->scopeWindow->setPause(
false);
254 this->syncChannelProperties();
258 void Oscilloscope::Panel::applyDisplayTab()
261 updateWindowTimeDiv();
262 scopeWindow->replot();
266 void Oscilloscope::Panel::buildBlockList()
269 this->getRTXIEventManager()->postEvent(&event);
271 std::any_cast<std::vector<IO::Block*>>(
event.getParam(
"blockList"));
272 auto* previous_block =
273 this->blocksListDropdown->currentData().value<
IO::Block*>();
274 blocksListDropdown->clear();
275 for (
auto* block : blocklist) {
278 if (block->getName().find(
"Probe") != std::string::npos
279 || block->getName().find(
"Recording") != std::string::npos)
283 this->blocksListDropdown->addItem(QString(block->getName().c_str()) +
" " 284 + QString::number(block->getID()),
285 QVariant::fromValue(block));
287 blocksListDropdown->setCurrentIndex(
288 this->blocksListDropdown->findData(QVariant::fromValue(previous_block)));
291 QWidget* Oscilloscope::Panel::createChannelTab(QWidget* parent)
294 "<p><b>Oscilloscope: Channel Options</b><br>" 295 "Use the dropdown boxes to select the signal streams you want to plot " 297 "any loaded modules or your DAQ device. You may change the plotting " 299 "the signal, apply a DC offset, and change the color and style of the " 302 auto* page =
new QWidget(parent);
305 auto* bttnLayout =
new QGridLayout(page);
308 auto* row1Layout =
new QHBoxLayout;
309 auto* channelLabel =
new QLabel(tr(
"Channel:"), page);
310 row1Layout->addWidget(channelLabel);
311 blocksListDropdown =
new QComboBox(page);
312 blocksListDropdown->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
313 blocksListDropdown->setSizeAdjustPolicy(QComboBox::AdjustToContents);
314 QObject::connect(blocksListDropdown,
315 SIGNAL(activated(
int)),
317 SLOT(buildChannelList()));
318 row1Layout->addWidget(blocksListDropdown);
321 typesList =
new QComboBox(page);
322 typesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
323 typesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
324 typesList->addItem(
"Output", QVariant::fromValue(
IO::OUTPUT));
325 typesList->addItem(
"Input", QVariant::fromValue(
IO::INPUT));
326 row1Layout->addWidget(typesList);
328 typesList, SIGNAL(activated(
int)),
this, SLOT(buildChannelList()));
331 channelsList =
new QComboBox(page);
332 channelsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
333 channelsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
335 channelsList, SIGNAL(activated(
int)),
this, SLOT(showChannelTab()));
336 row1Layout->addWidget(channelsList);
339 row1Layout->addSpacerItem(
340 new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
341 auto* scaleLabel =
new QLabel(tr(
"Scale:"), page);
342 row1Layout->addWidget(scaleLabel);
343 scalesList =
new QComboBox(page);
344 row1Layout->addWidget(scalesList);
345 const QFont scalesListFont(
"DejaVu Sans Mono");
346 const QString postfix =
"/div";
347 std::array<std::string, 6> unit_array = {
"V",
"mV",
"µV",
"nV",
"pV",
"fV"};
348 size_t unit_array_index = 0;
349 const std::array<double, 4> fixed_values = {10, 5, 2.5, 2};
350 double value_scale = 1.0;
351 scalesList->setFont(scalesListFont);
352 const std::string formatting =
"{:.1f} {}/div";
353 double temp_value = 0.0;
354 while (unit_array_index < unit_array.size()) {
355 for (
auto current_fixed_value : fixed_values) {
357 current_fixed_value * std::pow(1e3, unit_array_index) * value_scale;
358 if (temp_value < 1) {
360 if (unit_array_index >= 6) {
364 current_fixed_value * std::pow(1e3, unit_array_index) * value_scale;
368 formatting, temp_value, unit_array.at(unit_array_index))
370 current_fixed_value * value_scale);
372 value_scale = value_scale / 10.0;
375 auto* offsetLabel =
new QLabel(tr(
"Offset:"), page);
376 row1Layout->addWidget(offsetLabel);
377 offsetsEdit =
new QLineEdit(page);
378 offsetsEdit->setMaximumWidth(offsetsEdit->minimumSizeHint().width() * 2);
379 offsetsEdit->setValidator(
new QDoubleValidator(offsetsEdit));
380 row1Layout->addWidget(offsetsEdit);
381 offsetsList =
new QComboBox(page);
382 row1Layout->addWidget(offsetsList);
383 offsetsList->addItem(
"V", 1.0);
384 offsetsList->addItem(
"mV", 1e-3);
385 offsetsList->addItem(QString::fromUtf8(
"µV"), 1e-6);
386 offsetsList->addItem(
"nV", 1e-9);
387 offsetsList->addItem(
"pV", 1e-12);
390 auto* row2Layout =
new QHBoxLayout;
391 row2Layout->setAlignment(Qt::AlignLeft);
392 auto* colorLabel =
new QLabel(tr(
"Color:"), page);
393 row2Layout->addWidget(colorLabel);
394 colorsList =
new QComboBox(page);
395 colorsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
396 colorsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
397 row2Layout->addWidget(colorsList);
399 std::string color_name;
400 for (
size_t i = 0; i <
penColors.size(); i++) {
407 auto* widthLabel =
new QLabel(tr(
"Width:"), page);
408 row2Layout->addWidget(widthLabel);
409 widthsList =
new QComboBox(page);
410 widthsList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
411 widthsList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
412 row2Layout->addWidget(widthsList);
414 QPainter painter(&tmp);
415 for (
int i = 1; i < 6; i++) {
418 painter.drawLine(0, 12, 25, 12);
419 widthsList->addItem(tmp, QString::number(i) + QString(
" Pixels"), i);
423 auto* styleLabel =
new QLabel(tr(
"Style:"), page);
424 row2Layout->addWidget(styleLabel);
425 stylesList =
new QComboBox(page);
426 stylesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
427 stylesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
428 row2Layout->addWidget(stylesList);
429 std::string temp_name;
437 painter.drawLine(0, 12, 25, 12);
438 stylesList->addItem(tmp,
439 QString(temp_name.c_str()),
444 row2Layout->addSpacerItem(
445 new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
446 activateButton =
new QPushButton(
"Enable Channel", page);
447 row2Layout->addWidget(activateButton);
448 activateButton->setCheckable(
true);
449 activateButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
451 activateButton, SIGNAL(toggled(
bool)),
this, SLOT(activateChannel(
bool)));
452 activateChannel(
false);
454 bttnLayout->addLayout(row1Layout, 0, 0);
455 bttnLayout->addLayout(row2Layout, 1, 0);
457 QObject::connect(blocksListDropdown,
458 SIGNAL(currentTextChanged(
const QString&)),
460 SLOT(syncChannelProperties()));
461 QObject::connect(typesList,
462 SIGNAL(currentTextChanged(
const QString&)),
464 SLOT(syncChannelProperties()));
465 QObject::connect(channelsList,
466 SIGNAL(currentTextChanged(
const QString&)),
468 SLOT(syncChannelProperties()));
472 QWidget* Oscilloscope::Panel::createDisplayTab(QWidget* parent)
475 "<p><b>Oscilloscope: Display Options</b><br>" 476 "Use the dropdown box to select the time scale for the Oscilloscope. " 478 "scaling is applied to all signals plotted in the same window. You may " 480 "set a trigger on any signal that is currently plotted in the window. A " 482 "line will appear at the trigger threshold.</p>");
484 auto* page =
new QWidget(parent);
487 auto* displayTabLayout =
new QGridLayout(page);
490 auto* row1Layout =
new QHBoxLayout;
491 row1Layout->addWidget(
new QLabel(tr(
"Time/Div:"), page));
492 timesList =
new QComboBox(page);
493 row1Layout->addWidget(timesList);
494 const QFont timeListFont(
"DejaVu Sans Mono");
495 timesList->setFont(timeListFont);
496 timesList->addItem(
"5 s/div", QVariant::fromValue(5000000000));
497 timesList->addItem(
"2 s/div", QVariant::fromValue(2000000000));
498 timesList->addItem(
"1 s/div", QVariant::fromValue(1000000000));
499 timesList->addItem(
"500 ms/div", QVariant::fromValue(500000000));
500 timesList->addItem(
"200 ms/div", QVariant::fromValue(200000000));
501 timesList->addItem(
"100 ms/div", QVariant::fromValue(100000000));
502 timesList->addItem(
"50 ms/div", QVariant::fromValue(50000000));
503 timesList->addItem(
"20 ms/div", QVariant::fromValue(20000000));
504 timesList->addItem(
"10 ms/div", QVariant::fromValue(10000000));
505 timesList->addItem(
"5 ms/div", QVariant::fromValue(5000000));
506 timesList->addItem(
"2 ms/div", QVariant::fromValue(2000000));
507 timesList->addItem(
"1 ms/div", QVariant::fromValue(1000000));
508 timesList->addItem(QString::fromUtf8(
"500 µs/div"),
509 QVariant::fromValue(500000));
510 timesList->addItem(QString::fromUtf8(
"200 µs/div"),
511 QVariant::fromValue(200000));
512 timesList->addItem(QString::fromUtf8(
"100 µs/div"),
513 QVariant::fromValue(100000));
514 timesList->addItem(QString::fromUtf8(
"50 µs/div"),
515 QVariant::fromValue(50000));
516 timesList->addItem(QString::fromUtf8(
"20 µs/div"),
517 QVariant::fromValue(20000));
518 timesList->addItem(QString::fromUtf8(
"10 µs/div"),
519 QVariant::fromValue(10000));
520 timesList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
521 timesList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
523 auto* refreshLabel =
new QLabel(tr(
"Refresh:"), page);
524 row1Layout->addWidget(refreshLabel);
525 refreshDropdown =
new QComboBox(page);
526 row1Layout->addWidget(refreshDropdown);
527 refreshDropdown->addItem(
"60 Hz",
529 refreshDropdown->addItem(
531 refreshDropdown->addItem(
535 row1Layout->addSpacerItem(
536 new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
537 auto* bufferLabel =
new QLabel(tr(
"Buffer Size (MB):"), page);
538 row1Layout->addWidget(bufferLabel);
539 sizesEdit =
new QLineEdit(page);
540 sizesEdit->setMaximumWidth(sizesEdit->minimumSizeHint().width() * 3);
541 sizesEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
542 row1Layout->addWidget(sizesEdit);
543 const auto total_bytes =
static_cast<double>(scopeWindow->getDataSize()
545 sizesEdit->setText(QString::number(total_bytes / 1e6));
546 sizesEdit->setEnabled(
false);
549 auto* row2Layout =
new QHBoxLayout;
550 row2Layout->addWidget(
new QLabel(tr(
"Edge:"), page));
551 trigsGroup =
new QButtonGroup(page);
553 auto* off =
new QRadioButton(tr(
"Off"), page);
555 row2Layout->addWidget(off);
556 auto* plus =
new QRadioButton(tr(
"+"), page);
558 row2Layout->addWidget(plus);
559 auto* minus =
new QRadioButton(tr(
"-"), page);
561 row2Layout->addWidget(minus);
563 row2Layout->addWidget(
new QLabel(tr(
"Channel:"), page));
564 trigsChanList =
new QComboBox(page);
565 trigsChanList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
566 trigsChanList->setSizeAdjustPolicy(QComboBox::AdjustToContents);
567 row2Layout->addWidget(trigsChanList);
569 row2Layout->addWidget(
new QLabel(tr(
"Threshold:"), page));
570 trigsThreshEdit =
new QLineEdit(page);
571 trigsThreshEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
572 trigsThreshEdit->setMaximumWidth(trigsThreshEdit->minimumSizeHint().width()
574 row2Layout->addWidget(trigsThreshEdit);
575 trigsThreshEdit->setValidator(
new QDoubleValidator(trigsThreshEdit));
576 trigsThreshList =
new QComboBox(page);
577 trigsThreshList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
578 row2Layout->addWidget(trigsThreshList);
579 trigsThreshList->addItem(
"V", 1.0);
580 trigsThreshList->addItem(
"mV", 1e-3);
581 trigsThreshList->addItem(QString::fromUtf8(
"µV"), 1e-6);
582 trigsThreshList->addItem(
"nV", 1e-9);
583 trigsThreshList->addItem(
"pV", 1e-12);
603 displayTabLayout->addLayout(row1Layout, 0, 0);
604 displayTabLayout->addLayout(row2Layout, 1, 0);
609 void Oscilloscope::Panel::syncBlockInfo()
611 this->buildBlockList();
612 this->buildChannelList();
613 this->showChannelTab();
616 void Oscilloscope::Panel::showChannelTab()
618 auto type =
static_cast<IO::flags_t>(this->typesList->currentData().toInt());
619 auto* block = this->blocksListDropdown->currentData().value<
IO::Block*>();
620 auto port = this->channelsList->currentData().value<
size_t>();
622 const double scale = this->scopeWindow->getChannelScale(chan);
623 double offset = this->scopeWindow->getChannelOffset(chan);
624 scalesList->setCurrentIndex(
625 static_cast<int>(round(4 * (log10(1 / scale) + 1))));
627 if (offset * std::pow(10, -3 * offsetsList->count() - 3) < 1) {
631 while (fabs(offset) < 1 && offsetUnits < offsetsList->count()) {
636 offsetsEdit->setText(QString::number(offset));
637 offsetsList->setCurrentIndex(offsetUnits);
638 this->activateButton->setChecked(this->scopeWindow->channelRegistered(chan));
641 void Oscilloscope::Panel::showDisplayTab()
643 timesList->setCurrentIndex(
644 timesList->findData(QVariant::fromValue(this->scopeWindow->getDivT())));
648 auto* oscilloscope_plugin =
650 trigger_endpoint = this->scopeWindow->getTriggerEndpoint();
651 this->trigsGroup->button(
static_cast<int>(trigger_endpoint.
direction))
654 trigsChanList->clear();
655 std::vector<IO::endpoint> endpoint_list;
656 if (oscilloscope_plugin !=
nullptr) {
657 endpoint_list = oscilloscope_plugin->getTrackedEndpoints();
659 std::string direction_str;
660 for (
const auto&
endpoint : endpoint_list) {
663 + QString(direction_str.c_str()) +
" " 667 trigsChanList->addItem(
"<None>");
669 const int triglist_index =
670 trigsChanList->findData(QVariant::fromValue(trigger_endpoint));
671 trigsChanList->setCurrentIndex(triglist_index);
673 int trigThreshUnits = 0;
674 double trigThresh = this->scopeWindow->getTriggerThreshold();
675 if (trigThresh * std::pow(10, -3 * this->trigsThreshList->count() - 1) < 1) {
679 while (fabs(trigThresh) < 1
680 && trigThreshUnits < this->trigsThreshList->count()) {
685 trigsThreshList->setCurrentIndex(trigThreshUnits);
686 trigsThreshEdit->setText(QString::number(trigThresh));
688 sizesEdit->setText(QString::number(scopeWindow->getDataSize()));
693 , tabWidget(new QTabWidget)
694 , scopeWindow(new
Scope(this))
695 , layout(new QVBoxLayout)
696 , scopeGroup(new QWidget(this))
697 , setBttnGroup(new QGroupBox(this))
700 "<p><b>Oscilloscope:</b><br>The Oscilloscope allows you to plot any " 702 "in your workspace in real-time, including signals from your DAQ card " 704 "generated by user modules. Multiple signals are overlaid in the window " 706 "different line colors and styles can be selected. When a signal is " 708 "automatically appears in the bottom of the window. Multiple " 710 "be instantiated to give you multiple data windows. To select signals " 712 "use the right-click context \"Panel\" menu item. After selecting a " 714 "click the \"Enable\" button for it to appear in the window. To change " 716 "you must click the \"Apply\" button. The right-click context \"Pause\" " 718 "allows you to start and stop real-time plotting.</p>");
721 tabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
723 tabWidget, SIGNAL(currentChanged(
int)),
this, SLOT(showTab(
int)));
725 auto* scopeLayout =
new QHBoxLayout(
this);
726 scopeLayout->addWidget(scopeWindow);
727 scopeGroup->setLayout(scopeLayout);
728 auto* setBttnLayout =
new QHBoxLayout(
this);
731 pauseButton =
new QPushButton(
"Pause");
732 pauseButton->setCheckable(
true);
733 QObject::connect(pauseButton, SIGNAL(released()),
this, SLOT(
togglePause()));
734 setBttnLayout->addWidget(pauseButton);
735 applyButton =
new QPushButton(
"Apply");
736 QObject::connect(applyButton, SIGNAL(released()),
this, SLOT(apply()));
737 setBttnLayout->addWidget(applyButton);
738 settingsButton =
new QPushButton(
"Screenshot");
740 settingsButton, SIGNAL(released()),
this, SLOT(screenshot()));
741 setBttnLayout->addWidget(settingsButton);
744 setBttnGroup->setLayout(setBttnLayout);
747 tabWidget->setTabPosition(QTabWidget::North);
748 tabWidget->addTab(createChannelTab(
this),
"Channel");
749 tabWidget->addTab(createDisplayTab(
this),
"Display");
752 layout->addWidget(scopeGroup);
753 layout->addWidget(tabWidget);
754 layout->addWidget(setBttnGroup);
762 getMdiWindow()->setMinimumSize(this->minimumSizeHint().width(), 450);
763 getMdiWindow()->resize(this->minimumSizeHint().width() + 50, 600);
768 auto* otimer =
new QTimer(
this);
769 otimer->setTimerType(Qt::PreciseTimer);
772 qRegisterMetaType<IO::Block*>(
"IO::Block*");
773 QObject::connect(
this,
776 &Oscilloscope::Panel::removeBlockChannels);
781 this->buildChannelList();
782 scopeWindow->replot();
786 const std::string& probe_name)
793 ERROR_MSG(
"Unable to create xfifo for Oscilloscope Component {}",
802 switch (this->getState()) {
821 void Oscilloscope::Panel::screenshot()
823 QwtPlotRenderer renderer;
824 renderer.exportTo(scopeWindow,
"screenshot.pdf");
829 this->scopeWindow->setPause(this->pauseButton->isChecked());
858 void Oscilloscope::Panel::removeBlockChannels(
IO::Block* block)
860 this->scopeWindow->removeBlockChannels(block);
865 void Oscilloscope::Panel::syncChannelProperties()
868 probe_info.
block = blocksListDropdown->currentData().value<
IO::Block*>();
870 probe_info.
port = channelsList->currentData().value<
size_t>();
873 if (!scopeWindow->channelRegistered(probe_info)) {
877 const QColor color = scopeWindow->getChannelColor(probe_info);
878 colorsList->setCurrentIndex(colorsList->findData(color));
879 const int width = scopeWindow->getChannelWidth(probe_info);
880 widthsList->setCurrentIndex(widthsList->findData(width));
881 const Qt::PenStyle style = scopeWindow->getChannelStyle(probe_info);
882 stylesList->setCurrentIndex(stylesList->findData(QVariant::fromValue(style)));
883 double offset = scopeWindow->getChannelOffset(probe_info);
884 const double scale = scopeWindow->getChannelScale(probe_info);
885 scalesList->setCurrentIndex(
886 static_cast<int>(round(4 * (log10(1 / scale) + 1))));
888 if (offset * std::pow(10, -3 * offsetsList->count() - 3) < 1) {
892 while (fabs(offset) < 1 && offsetUnits < offsetsList->count()) {
897 offsetsEdit->setText(QString::number(offset));
898 offsetsList->setCurrentIndex(offsetUnits);
908 std::vector<Event::Object> unloadEvents;
909 for (
auto& registry_entry : this->m_component_registry) {
911 unloadEvents.back().setParam(
913 std::any(
static_cast<RT::Thread*
>(registry_entry.component.get())));
915 this->getEventManager()->postEvent(unloadEvents);
921 auto probe_loc = std::find_if(this->m_component_registry.begin(),
922 this->m_component_registry.end(),
923 [&](
const registry_entry_t& entry)
924 { return entry.endpoint == probe_info; });
925 if (probe_loc != this->m_component_registry.end()) {
926 return probe_loc->component->getFifoPtr();
928 const std::string comp_name =
929 fmt::format(
"{} Probe for Block {} Channel {} {} with Id {} ",
935 this->m_component_registry.push_back(
936 {probe_info, std::make_unique<Oscilloscope::Component>(
this, comp_name)});
938 this->m_component_registry.back().component.get();
944 connection.
dest = measuring_component;
946 std::vector<Event::Object> events;
948 events.back().setParam(
949 "thread", std::any(
static_cast<RT::Thread*
>(measuring_component)));
951 events.back().setParam(
"connection", std::any(connection));
952 this->getEventManager()->postEvent(events);
960 auto probe_loc = std::find_if(this->m_component_registry.begin(),
961 this->m_component_registry.end(),
962 [&](
const registry_entry_t& entry)
963 { return entry.endpoint == probe_info; });
964 if (probe_loc == this->m_component_registry.end()) {
969 event.setParam(
"thread",
970 std::any(
static_cast<RT::Thread*
>(measuring_component)));
971 this->getEventManager()->postEvent(&event);
972 this->m_component_registry.erase(probe_loc);
977 std::vector<IO::endpoint> all_endpoints;
978 for (
auto& entry : this->m_component_registry) {
979 if (entry.endpoint.block == block) {
980 all_endpoints.push_back(entry.endpoint);
983 for (
auto endpoint : all_endpoints) {
991 auto probe_loc = std::find_if(this->m_component_registry.begin(),
992 this->m_component_registry.end(),
993 [&](
const registry_entry_t& entry)
994 { return entry.endpoint == endpoint; });
995 if (probe_loc == this->m_component_registry.end()) {
1003 static_cast<RT::Thread*
>(probe_loc->component.get()));
1004 this->getEventManager()->postEvent(&activity_event);
1009 std::vector<IO::endpoint> result;
1010 result.reserve(this->m_component_registry.size());
1011 for (
const auto& entry : this->m_component_registry) {
1012 result.push_back(entry.endpoint);
1019 std::vector<Event::Object> events;
1020 events.reserve(this->m_component_registry.size());
1024 for (
const auto& entry : this->m_component_registry) {
1025 events.emplace_back(event_type);
1026 events.back().setParam(
"thread",
1027 static_cast<RT::Thread*
>(entry.component.get()));
1029 this->getEventManager()->postEvent(events);
1035 auto iter = std::find_if(this->m_component_registry.begin(),
1036 this->m_component_registry.end(),
1037 [&](
const registry_entry_t& entry)
1038 { return entry.endpoint == endpoint; });
1039 if (iter == this->m_component_registry.end()) {
1042 return iter->component.get();
1048 return std::make_unique<Oscilloscope::Plugin>(ev_manager);
1061 return std::unique_ptr<Oscilloscope::Component>(
nullptr);
void setParam(const std::string ¶m_name, const std::any ¶m_value)
Event::Type getType() const
std::any getParam(const std::string ¶m_name) const
std::string getName() const
Component(Widgets::Plugin *hplugin, const std::string &probe_name)
RT::OS::Fifo * getFifoPtr()
void updateBlockChannels(IO::Block *block)
Panel(QMainWindow *mw, Event::Manager *ev_manager)
void setActivity(IO::endpoint endpoint, bool activity)
Plugin(Event::Manager *ev_manager)
void receiveEvent(Event::Object *event) override
void setProbeActivity(IO::endpoint endpoint, bool activity)
void deleteProbe(IO::endpoint probe_info)
Oscilloscope::Component * getProbeComponentPtr(IO::endpoint endpoint)
RT::OS::Fifo * createProbe(IO::endpoint probe_info)
std::vector< IO::endpoint > getTrackedEndpoints()
void setAllProbesActivity(bool activity)
void deleteAllProbes(IO::Block *block)
virtual int64_t writeRT(void *buf, size_t data_size)=0
virtual int64_t read(void *buf, size_t data_size)=0
void ERROR_MSG(const std::string &errmsg, Args... args)
@ RT_THREAD_UNPAUSE_EVENT
struct IO::endpoint endpoint
constexpr std::array< std::string_view, 7 > color2string
constexpr std::string_view MODULE_NAME
struct Oscilloscope::sample sample
constexpr std::array< Qt::PenStyle, 5 > penStyles
std::unique_ptr< Widgets::Plugin > createRTXIPlugin(Event::Manager *ev_manager)
Widgets::FactoryMethods getFactories()
constexpr std::array< std::string_view, 5 > penstyles2string
const std::array< QColor, 7 > penColors
constexpr size_t DEFAULT_BUFFER_SIZE
std::unique_ptr< Widgets::Component > createRTXIComponent(Widgets::Plugin *host_plugin)
std::vector< Widgets::Variable::Info > get_default_vars()
Widgets::Panel * createRTXIPanel(QMainWindow *main_window, Event::Manager *ev_manager)
std::vector< IO::channel_t > get_default_channels()
int getFifo(std::unique_ptr< Fifo > &fifo, size_t fifo_size)
IO::flags_t src_port_type