34 , buttonGroup(new QGroupBox)
35 , deviceList(new QComboBox)
36 , analogChannelList(new QComboBox)
37 , analogRangeList(new QComboBox)
38 , analogDownsampleList(new QComboBox)
39 , analogReferenceList(new QComboBox)
40 , analogSubdeviceList(new QComboBox)
41 , analogUnitPrefixList(new QComboBox)
42 , analogUnitList(new QComboBox)
43 , analogUnitPrefixList2(new QComboBox)
44 , analogGainEdit(new QLineEdit)
45 , analogZeroOffsetEdit(new QLineEdit)
46 , digitalChannelList(new QComboBox)
47 , digitalDirectionList(new QComboBox)
48 , digitalSubdeviceList(new QComboBox)
50 , freqUnitList(new QComboBox)
51 , periodUnitList(new QComboBox)
52 , freqEdit(new QLineEdit)
53 , periodEdit(new QLineEdit)
56 "<p><b>System Control Panel:</b><br>This control panel allows you to " 58 "the channels on your DAQ card. RTXI automatically detects the number " 60 "of channels that are available. You should set the \"Scale\" of the " 62 "to be the inverse of the gain that is applied to the signal through the " 63 "combination of hardware and software that you are using. To acquire " 65 "a channel, you must set it to be Active using the toggle button. Any " 67 "settings such as the \"Range\" or \"Scale\" must be set by clicking the " 69 "button.<br><br> The \"Thread\" tab allows you to set the period for " 71 "execution. You must click \"Apply\" to change this setting and " 73 "to other user modules such as the Data Recorder. Custom user modules " 75 "execute special code when the real-time period is changed using the " 79 auto* layout =
new QGridLayout;
82 deviceGroup =
new QGroupBox(tr(
"DAQ Setup"));
83 auto* deviceLayout =
new QGridLayout;
86 deviceLayout->addWidget(
new QLabel(tr(
"Device:")), 0, 0);
88 deviceLayout->addWidget(deviceList, 0, 1, 1, 5);
91 deviceList, SIGNAL(activated(
int)),
this, SLOT(
updateDevice()));
94 deviceLayout->addWidget(
new QLabel(tr(
"Frequency:")), 1, 0);
95 deviceLayout->addWidget(freqEdit, 1, 1);
99 auto period = std::any_cast<int64_t>(get_period_event.
getParam(
"period"));
104 freqEdit, SIGNAL(textEdited(
const QString&)),
this, SLOT(
updatePeriod()));
105 freqUnitList->setFixedWidth(50);
106 freqUnitList->addItem(
" Hz", 1);
107 freqUnitList->addItem(
"kHz", 1000);
108 deviceLayout->addWidget(freqUnitList, 1, 2);
110 freqUnitList, SIGNAL(activated(
int)),
this, SLOT(
updatePeriod()));
113 deviceLayout->addWidget(
new QLabel(tr(
"Period:")), 1, 3);
114 deviceLayout->addWidget(periodEdit, 1, 4);
116 periodEdit, SIGNAL(textEdited(
const QString&)),
this, SLOT(
updateFreq()));
117 deviceLayout->addWidget(periodUnitList, 1, 5);
118 periodUnitList->setFixedWidth(50);
119 periodUnitList->addItem(
" s", 1.0);
120 periodUnitList->addItem(
"ms", 1e-3);
121 periodUnitList->addItem(
"us", 1e-6);
122 periodUnitList->addItem(
"ns", 1e-9);
124 periodUnitList, SIGNAL(activated(
int)),
this, SLOT(
updateFreq()));
128 deviceGroup->setLayout(deviceLayout);
131 analogGroup =
new QGroupBox(tr(
"Analog Channels"));
132 auto* analogLayout =
new QGridLayout;
135 analogLayout->addWidget(
new QLabel(tr(
"Channel:")), 1, 0);
137 analogSubdeviceList->addItem(
"Input",
139 analogSubdeviceList->addItem(
"Output",
142 analogSubdeviceList, SIGNAL(activated(
int)),
this, SLOT(
updateDevice()));
143 analogLayout->addWidget(analogSubdeviceList, 1, 1);
146 analogChannelList, SIGNAL(activated(
int)),
this, SLOT(
display()));
147 analogLayout->addWidget(analogChannelList, 1, 2);
149 analogActiveButton =
new QPushButton(
"Active");
150 analogActiveButton->setCheckable(
true);
151 analogLayout->addWidget(analogActiveButton, 1, 3);
153 analogLayout->addWidget(
new QLabel(tr(
"Range:")), 2, 0, 1, 1);
154 analogLayout->addWidget(analogRangeList, 2, 1, 1, 2);
155 analogRangeList->clear();
156 const std::string formatting =
"{:.1f}";
157 std::string range_list_text;
160 auto [min, max] = range;
161 range_list_text = fmt::format(formatting, min) + std::string(
" to ")
162 + fmt::format(formatting, max);
163 analogRangeList->addItem(QString(range_list_text.c_str()),
164 QVariant::fromValue(indx));
168 analogLayout->addWidget(analogReferenceList, 2, 3, 1, 2);
169 analogLayout->addWidget(
new QLabel(tr(
"Scale:")), 3, 0);
170 analogReferenceList->clear();
171 analogReferenceList->addItem(
174 analogReferenceList->addItem(
177 analogReferenceList->addItem(
"Differential",
180 analogReferenceList->addItem(
184 analogGainEdit->setAlignment(Qt::AlignRight);
185 analogLayout->addWidget(analogGainEdit, 3, 1);
187 analogUnitPrefixList->addItem(
"yotta-", 1e24);
188 analogUnitPrefixList->addItem(
"zetta-", 1e21);
189 analogUnitPrefixList->addItem(
"exa-", 1e18);
190 analogUnitPrefixList->addItem(
"peta-", 1e15);
191 analogUnitPrefixList->addItem(
"tera-", 1e12);
192 analogUnitPrefixList->addItem(
"giga-", 1e9);
193 analogUnitPrefixList->addItem(
"mega-", 1e6);
194 analogUnitPrefixList->addItem(
"kilo-", 1e3);
195 analogUnitPrefixList->addItem(
"", 1);
196 analogUnitPrefixList->addItem(
"milli-", 1e-3);
197 analogUnitPrefixList->addItem(
"micro-", 1e-6);
198 analogUnitPrefixList->addItem(
"nano-", 1e-9);
199 analogUnitPrefixList->addItem(
"pico-", 1e-12);
200 analogUnitPrefixList->addItem(
"femto-", 1e-15);
201 analogUnitPrefixList->addItem(
"atto-", 1e-18);
202 analogUnitPrefixList->addItem(
"zepto-", 1e-21);
203 analogUnitPrefixList->addItem(
"yocto-", 1e-24);
204 analogLayout->addWidget(analogUnitPrefixList, 3, 2);
206 analogLayout->addWidget(analogUnitList, 3, 3);
207 analogUnitList->clear();
210 analogUnitList->addItem(QString(units.c_str()),
211 QVariant::fromValue(units_index));
214 analogLayout->addWidget(
new QLabel(tr(
" / Volt")), 3, 4);
215 analogLayout->addWidget(
new QLabel(tr(
"Offset:")), 4, 0);
216 analogZeroOffsetEdit->setText(
"0");
217 analogZeroOffsetEdit->setAlignment(Qt::AlignRight);
218 analogLayout->addWidget(analogZeroOffsetEdit, 4, 1);
221 analogUnitPrefixList2->addItem(
"yotta-", 1e24);
222 analogUnitPrefixList2->addItem(
"zetta-", 1e21);
223 analogUnitPrefixList2->addItem(
"exa-", 1e18);
224 analogUnitPrefixList2->addItem(
"peta-", 1e15);
225 analogUnitPrefixList2->addItem(
"tera-", 1e12);
226 analogUnitPrefixList2->addItem(
"giga-", 1e9);
227 analogUnitPrefixList2->addItem(
"mega-", 1e6);
228 analogUnitPrefixList2->addItem(
"kilo-", 1e3);
229 analogUnitPrefixList2->addItem(
"", 1);
230 analogUnitPrefixList2->addItem(
"milli-", 1e-3);
231 analogUnitPrefixList2->addItem(
"micro-", 1e-6);
232 analogUnitPrefixList2->addItem(
"nano-", 1e-9);
233 analogUnitPrefixList2->addItem(
"pico-", 1e-12);
234 analogUnitPrefixList2->addItem(
"femto-", 1e-15);
235 analogUnitPrefixList2->addItem(
"atto-", 1e-18);
236 analogUnitPrefixList2->addItem(
"zepto-", 1e-21);
237 analogUnitPrefixList2->addItem(
"yocto-", 1e-24);
239 analogLayout->addWidget(analogUnitPrefixList2, 4, 2, 1, 1);
240 analogLayout->addWidget(
new QLabel(tr(
" Volt/Amps")), 4, 3);
241 analogLayout->addWidget(
new QLabel(tr(
"Downsample:")), 5, 0);
242 analogDownsampleList->addItem(
"1", 1);
243 analogDownsampleList->addItem(
"2", 2);
244 analogDownsampleList->addItem(
"4", 4);
245 analogDownsampleList->addItem(
"6", 6);
246 analogDownsampleList->addItem(
"8", 8);
247 analogDownsampleList->addItem(
"10", 10);
248 analogLayout->addWidget(analogDownsampleList, 5, 1);
251 analogGroup->setLayout(analogLayout);
254 digitalGroup =
new QGroupBox(tr(
"Digital I/O"));
255 auto* digitalLayout =
new QGridLayout;
258 digitalLayout->addWidget(
new QLabel(tr(
"Channel:")), 1, 0, 1, 1);
260 digitalSubdeviceList->addItem(
"I/O");
262 digitalSubdeviceList, SIGNAL(activated(
int)),
this, SLOT(
updateDevice()));
263 digitalLayout->addWidget(digitalSubdeviceList, 1, 1, 1, 1);
266 digitalChannelList, SIGNAL(activated(
int)),
this, SLOT(
display()));
267 digitalLayout->addWidget(digitalChannelList, 1, 2, 1, 1);
269 digitalDirectionList->addItem(
"Input",
271 digitalDirectionList->addItem(
"Output",
273 digitalLayout->addWidget(digitalDirectionList, 1, 3, 1, 1);
275 digitalActiveButton =
new QPushButton(
"Active");
276 digitalActiveButton->setCheckable(
true);
277 digitalLayout->addWidget(digitalActiveButton, 1, 4, 1, 1);
280 digitalGroup->setLayout(digitalLayout);
283 auto* buttonLayout =
new QHBoxLayout;
286 auto* applyButton =
new QPushButton(
"Apply");
287 QObject::connect(applyButton, SIGNAL(released()),
this, SLOT(
apply()));
288 buttonLayout->addWidget(applyButton);
289 auto* cancelButton =
new QPushButton(
"Close");
291 cancelButton, SIGNAL(released()), parentWidget(), SLOT(close()));
292 buttonLayout->addWidget(cancelButton);
295 buttonGroup->setLayout(buttonLayout);
298 layout->addWidget(deviceGroup, 1, 0);
299 layout->addWidget(analogGroup, 2, 0);
300 layout->addWidget(digitalGroup, 3, 0);
301 layout->addWidget(buttonGroup, 4, 0);
305 setWindowTitle(
"System Control Panel");
308 this->
getMdiWindow()->setFixedSize(this->minimumSizeHint());
315 void SystemControl::Panel::submitAnalogChannelUpdate()
317 auto* dev = deviceList->currentData().value<
DAQ::Device*>();
318 auto a_chan = analogChannelList->currentData().value<
DAQ::index_t>();
321 const double a_gain = analogGainEdit->text().toDouble()
322 * analogUnitPrefixList->currentData().toDouble();
323 const double a_zerooffset = analogZeroOffsetEdit->text().toDouble()
324 * analogUnitPrefixList2->currentData().toDouble();
327 if (!analogActiveButton->isChecked()) {
330 dev->setAnalogGain(a_type, a_chan, a_gain);
331 dev->setAnalogZeroOffset(a_type, a_chan, a_zerooffset);
333 a_type, a_chan, analogRangeList->currentData().value<
DAQ::index_t>());
334 dev->setAnalogReference(
335 a_type, a_chan, analogReferenceList->currentData().value<
DAQ::index_t>());
337 a_type, a_chan, analogUnitList->currentData().value<
DAQ::index_t>());
340 ->itemData(analogDownsampleList->currentIndex(), Qt::DisplayRole)
342 dev->setAnalogDownsample(a_type, a_chan,
static_cast<size_t>(value));
343 dev->setAnalogCounter(a_type, a_chan);
346 void SystemControl::Panel::submitDigitalChannelUpdate()
348 auto* dev = deviceList->currentData().value<
DAQ::Device*>();
349 auto d_chan = digitalChannelList->currentData().value<
DAQ::index_t>();
354 dev->setChannelActive(d_type, d_chan, digitalActiveButton->isChecked());
355 if (!digitalActiveButton->isChecked()) {
359 dev->setDigitalDirection(d_chan, d_dir);
365 int64_t freq = freqEdit->text().toInt();
366 freq *= freqUnitList->currentData().toInt();
369 event.setParam(
"period", std::any(period));
370 this->getRTXIEventManager()->postEvent(&event);
373 if (deviceList->count() == 0 || deviceList->currentIndex() < 0) {
377 auto* device = this->deviceList->currentData().value<
DAQ::Device*>();
379 disable_device.setParam(
"device", std::any(
static_cast<RT::Device*
>(device)));
383 this->getRTXIEventManager()->postEvent(&disable_device);
384 if (analogActiveButton->isEnabled()) {
385 this->submitAnalogChannelUpdate();
387 if (digitalActiveButton->isEnabled()) {
388 this->submitDigitalChannelUpdate();
390 this->getRTXIEventManager()->postEvent(&enable_device);
397 if (this->deviceList->currentIndex() < 0) {
401 auto* dev = deviceList->currentData().value<
DAQ::Device*>();
402 analogChannelList->clear();
403 digitalChannelList->clear();
407 for (
size_t i = 0; i < dev->getChannelCount(type); ++i) {
408 analogChannelList->addItem(
409 QString::number(i), QVariant::fromValue(
static_cast<DAQ::index_t>(i)));
413 for (
size_t i = 0; i < dev->getChannelCount(type); ++i) {
414 digitalChannelList->addItem(
415 QString::number(i), QVariant::fromValue(
static_cast<DAQ::index_t>(i)));
424 auto period = periodEdit->text().toDouble();
425 period *= periodUnitList->currentData().toDouble();
426 auto freq = 1 / period;
433 freqEdit->setText(QString::number(freq));
434 freqUnitList->setCurrentIndex(index);
442 auto freq = freqEdit->text().toDouble();
443 freq *= freqUnitList->currentData().toDouble();
445 auto period = 1 / freq;
447 while (period < .001 && (index < 4)) {
452 periodEdit->setText(QString::number(period));
453 periodUnitList->setCurrentIndex(index);
456 void SystemControl::Panel::buildDAQDeviceList()
459 this->getRTXIEventManager()->postEvent(&device_list_request);
460 auto devices = std::any_cast<std::vector<DAQ::Device*>>(
461 device_list_request.getParam(
"devices"));
462 for (
auto* device : devices) {
463 this->deviceList->addItem(QString(device->getName().c_str()),
464 QVariant::fromValue(device));
471 if (deviceList->count() == 0) {
472 deviceList->setEnabled(
false);
473 analogSubdeviceList->setEnabled(
false);
474 digitalSubdeviceList->setEnabled(
false);
476 displayAnalogGroup();
477 displayDigitalGroup();
481 this->getRTXIEventManager()->postEvent(&get_period_event);
482 auto tmp = std::any_cast<int64_t>(get_period_event.
getParam(
"period"));
483 while ((tmp >= 1000) && ((index) != 0)) {
487 periodEdit->setText(QString::number(
static_cast<int64_t
>(tmp)));
488 periodUnitList->setCurrentIndex(index);
494 if (deviceList->count() == 0 || deviceList->currentIndex() < 0) {
497 if (analogChannelList->count() == 0 || analogChannelList->currentIndex() < 0)
499 analogActiveButton->setChecked(
false);
500 analogActiveButton->setEnabled(
false);
501 analogRangeList->setEnabled(
false);
502 analogDownsampleList->setEnabled(
false);
503 analogReferenceList->setEnabled(
false);
504 analogGainEdit->setEnabled(
false);
505 analogZeroOffsetEdit->setEnabled(
false);
506 analogUnitPrefixList->setEnabled(
false);
507 analogUnitPrefixList2->setEnabled(
false);
508 analogUnitList->setEnabled(
false);
511 auto* dev = deviceList->currentData().value<
DAQ::Device*>();
514 auto chan = analogChannelList->currentData().value<
DAQ::index_t>();
518 analogActiveButton->setEnabled(
true);
519 analogChannelList->setEnabled(
true);
520 analogRangeList->setEnabled(
true);
521 analogReferenceList->setEnabled(
true);
522 analogGainEdit->setEnabled(
true);
523 analogZeroOffsetEdit->setEnabled(
true);
524 analogUnitPrefixList->setEnabled(
true);
525 analogUnitPrefixList2->setEnabled(
true);
526 analogUnitList->setEnabled(
true);
528 analogActiveButton->setChecked(dev->getChannelActive(type, chan));
529 analogRangeList->setCurrentIndex(
530 static_cast<int>(dev->getAnalogRange(type, chan)));
531 analogDownsampleList->setCurrentIndex(analogDownsampleList->findData(
532 QVariant::fromValue(dev->getAnalogDownsample(type, chan)),
534 analogReferenceList->setCurrentIndex(analogReferenceList->findData(
535 QVariant::fromValue(dev->getAnalogReference(type, chan))));
536 analogUnitList->setCurrentIndex(analogUnitList->findData(
537 QVariant::fromValue(dev->getAnalogUnits(type, chan))));
544 while (((tmp >= 1000) && (indx > 0)) || ((tmp < 1) && (indx < 16))) {
553 analogGainEdit->setText(QString::number(gain));
556 analogUnitPrefixList->setCurrentIndex(indx);
560 const double offset = dev->getAnalogZeroOffset(type, chan);
562 while (((tmp >= 1000) && (indx > 0)) || ((tmp < 1) && (indx < 16))) {
571 analogZeroOffsetEdit->setText(QString::number(offset));
573 analogUnitPrefixList2->setCurrentIndex(indx);
578 if (deviceList->count() == 0 || deviceList->currentIndex() < 0) {
581 if (digitalChannelList->count() == 0) {
582 digitalActiveButton->setChecked(
false);
583 digitalActiveButton->setEnabled(
false);
584 digitalChannelList->setEnabled(
false);
585 digitalDirectionList->setEnabled(
false);
588 auto* dev = deviceList->currentData().value<
DAQ::Device*>();
589 auto chan = digitalChannelList->currentData().value<
DAQ::index_t>();
593 digitalActiveButton->setEnabled(
true);
594 digitalChannelList->setEnabled(
true);
595 digitalDirectionList->setCurrentIndex(
596 digitalDirectionList->findData(QVariant::fromValue(direction)));
599 digitalActiveButton->setChecked(dev->getChannelActive(type, chan));
605 return std::make_unique<SystemControl::Plugin>(ev_manager);
virtual double getAnalogGain(ChannelType::type_t type, index_t index) const =0
virtual int setChannelActive(ChannelType::type_t type, index_t index, bool state)=0
void postEvent(Object *event)
void setParam(const std::string ¶m_name, const std::any ¶m_value)
std::any getParam(const std::string ¶m_name) const
void displayAnalogGroup()
Panel(QMainWindow *mw, Event::Manager *ev_manager)
void displayDigitalGroup()
constexpr std::string_view MODULE_NAME
std::array< std::string, 2 > get_default_units()
std::array< analog_range_t, 7 > get_default_ranges()
@ RT_DEVICE_UNPAUSE_EVENT
const int64_t SECONDS_TO_NANOSECONDS
std::unique_ptr< Widgets::Plugin > createRTXIPlugin(Event::Manager *ev_manager)
Widgets::FactoryMethods getFactories()
std::unique_ptr< Widgets::Component > createRTXIComponent(Widgets::Plugin *host_plugin)
Widgets::Panel * createRTXIPanel(QMainWindow *main_window, Event::Manager *ev_manager)