dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
configoutputwidget.cpp
Go to the documentation of this file.
1 
13 /*
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  *
27  * Additional note on redistribution: The copyright and license notices above
28  * must be maintained in each individual source file that is a derivative work
29  * of this source file; otherwise redistribution is prohibited.
30  */
31 
32 #include "configoutputwidget.h"
33 #include "outputchannelform.h"
35 
37 
38 #include <QDebug>
39 #include <QStringList>
40 #include <QWidget>
41 #include <QTextEdit>
42 #include <QVBoxLayout>
43 #include <QPushButton>
44 #include <QMessageBox>
45 #include <QDesktopServices>
46 #include <QUrl>
47 #include "mixersettings.h"
48 #include "actuatorcommand.h"
49 #include "actuatorsettings.h"
50 #include "systemalarms.h"
51 #include "systemsettings.h"
54 #include <coreplugin/modemanager.h>
55 #include <coreplugin/imode.h>
56 
58  : ConfigTaskWidget(parent)
59 {
60  m_config = new Ui_OutputWidget();
61  m_config->setupUi(this);
62 
63  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
64 
65  /* There's lots of situations where it's unsafe to run tests.
66  * Import/export:
67  */
68  UAVSettingsImportExportManager *importexportplugin =
69  pm->getObject<UAVSettingsImportExportManager>();
70  connect(importexportplugin, &UAVSettingsImportExportManager::importAboutToBegin, this,
71  &ConfigOutputWidget::stopTests);
72 
73  /* Board connection/disconnection: */
74  TelemetryManager *telMngr = pm->getObject<TelemetryManager>();
75  connect(telMngr, &TelemetryManager::connected, this, &ConfigOutputWidget::stopTests);
76  connect(telMngr, &TelemetryManager::disconnected, this, &ConfigOutputWidget::stopTests);
77 
78  /* When we go into wizards, etc.. time to stop this too. */
80  connect(modeMngr, &Core::ModeManager::currentModeAboutToChange, this,
81  &ConfigOutputWidget::stopTests);
82  connect(modeMngr, &Core::ModeManager::currentModeChanged, this, &ConfigOutputWidget::stopTests);
83 
84  // NOTE: we have channel indices from 0 to 9, but the convention for OP is Channel 1 to Channel
85  // 10.
86  // Register for ActuatorSettings changes:
87  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
88  OutputChannelForm *outputForm = new OutputChannelForm(i, this, i == 0);
89  m_config->channelLayout->addWidget(outputForm);
90 
91  connect(m_config->channelOutTest, &QAbstractButton::toggled, outputForm,
93  connect(outputForm, &OutputChannelForm::channelChanged, this,
94  &ConfigOutputWidget::sendChannelTest);
95 
96  connect(outputForm, &OutputChannelForm::formChanged, this,
97  &ConfigOutputWidget::do_SetDirty);
98  }
99 
100  connect(m_config->channelOutTest, &QAbstractButton::toggled, this,
101  &ConfigOutputWidget::runChannelTests);
102  connect(m_config->calibrateESC, &QAbstractButton::clicked, this,
103  &ConfigOutputWidget::startESCCalibration);
104 
105  // Cache all the combo boxes and labels
106  lblList.clear();
107  lblList << m_config->chBank1 << m_config->chBank2 << m_config->chBank3 << m_config->chBank4
108  << m_config->chBank5 << m_config->chBank6;
109  rateList.clear();
110  rateList << m_config->cb_outputRate1 << m_config->cb_outputRate2 << m_config->cb_outputRate3
111  << m_config->cb_outputRate4 << m_config->cb_outputRate5 << m_config->cb_outputRate6;
112 
114  for (rateIter = rateList.begin(); rateIter != rateList.end(); rateIter++) {
115  QComboBox *rate = *rateIter;
116 
117  connect(rate, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
118  &ConfigOutputWidget::refreshWidgetRanges);
119  }
120 
121  UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
122  UAVObject *obj = objManager->getObject(QString("ActuatorCommand"));
124  this->setEnabled(false);
125  connect(SystemSettings::GetInstance(objManager), &UAVObject::objectUpdated, this,
126  &ConfigOutputWidget::assignOutputChannels);
127 
128  autoLoadWidgets();
129  refreshWidgetsValues();
130 
131  // track dirty state of these since they're managed manually
132  // note: must come after autoLoadWidgets because it will choke with no object
133  // TODO: make a cleaner mechanism for just tracking dirtiness
134  addWidget(m_config->cb_outputRate6);
135  addWidget(m_config->cb_outputRate5);
136  addWidget(m_config->cb_outputRate4);
137  addWidget(m_config->cb_outputRate3);
138  addWidget(m_config->cb_outputRate2);
139  addWidget(m_config->cb_outputRate1);
140  addWidget(m_config->spinningArmed);
141  addUAVObject("ActuatorSettings");
142 }
143 
145 {
147  if (!enable)
148  m_config->channelOutTest->setChecked(false);
149  m_config->channelOutTest->setEnabled(enable);
150  m_config->calibrateESC->setEnabled(enable);
151  m_config->motorCurveFit->setEnabled(enable);
152  m_config->motorPowerGain->setEnabled(enable);
153 }
154 
156 {
157  // Do nothing
158 }
159 
160 // ************************************
161 
166 void ConfigOutputWidget::runChannelTests(bool state)
167 {
168  SystemAlarms *systemAlarmsObj = SystemAlarms::GetInstance(getObjectManager());
169  SystemAlarms::DataFields systemAlarms = systemAlarmsObj->getData();
170 
171  if (state && ((systemAlarms.Alarm[SystemAlarms::ALARM_ACTUATOR] == SystemAlarms::ALARM_ERROR)
172  || (systemAlarms.Alarm[SystemAlarms::ALARM_ACTUATOR]
173  == SystemAlarms::ALARM_CRITICAL))) {
174  (void) QMessageBox::critical(this, tr("Actuator error"),
175  tr("The actuator module is in an error state. "
176  "Please fix these before testing outputs."));
177 
178  // Unfortunately must cache this since callback will reoccur
179  accInitialData = ActuatorCommand::GetInstance(getObjectManager())->getMetadata();
180 
181  m_config->channelOutTest->setChecked(false);
182  return;
183  }
184 
185  // Confirm this is definitely what they want
186  if (state) {
187  int retval = QMessageBox::warning(this, tr("Actuator test"),
188  tr("This option will start your motors by the amount selected on the "
189  "sliders regardless of transmitter. It is recommended to remove "
190  "any blades from motors. Are you sure you want to do this?"),
191  QMessageBox::Yes | QMessageBox::No);
192 
193  if (retval != QMessageBox::Yes) {
194  state = false;
195  m_config->channelOutTest->setChecked(false);
196  return;
197  }
198  }
199 
200  ActuatorCommand *obj = ActuatorCommand::GetInstance(getObjectManager());
201  UAVObject::Metadata mdata = obj->getMetadata();
202  if (state) {
203  accInitialData = mdata;
206  UAVObject::SetGcsTelemetryAcked(mdata, false);
208  mdata.gcsTelemetryUpdatePeriod = 100;
209  } else {
210  mdata = accInitialData; // Restore metadata
211  }
212  obj->setMetadata(mdata);
213  obj->updated();
214 }
215 
216 OutputChannelForm *ConfigOutputWidget::getOutputChannelForm(const int index) const
217 {
218  QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
219  foreach (OutputChannelForm *outputChannelForm, outputChannelForms) {
220  if (outputChannelForm->index() == index)
221  return outputChannelForm;
222  }
223 
224  // no OutputChannelForm found with given index
225  return NULL;
226 }
227 
233 void ConfigOutputWidget::assignOutputChannels(UAVObject *obj)
234 {
235  Q_UNUSED(obj);
236 
237  // Get UAVO
238  ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
239  ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
240 
241  // Get channel descriptions
242  QStringList ChannelDesc = ConfigVehicleTypeWidget::getChannelDescriptions();
243 
244  // Find all output forms in the tab, and set the text and min/max values
245  QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
246  foreach (OutputChannelForm *outputChannelForm, outputChannelForms) {
247  outputChannelForm->setAssignment(ChannelDesc[outputChannelForm->index()]);
248 
249  // init min,max,neutral
250  quint32 minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()];
251  quint32 maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()];
252  outputChannelForm->setMinmax(minValue, maxValue);
253 
254  quint32 neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()];
255  outputChannelForm->setNeutral(neutral);
256  }
257 
258  refreshWidgetRanges();
259 }
260 
265 void ConfigOutputWidget::sendChannelTest(int index, int value)
266 {
267  if (!m_config->channelOutTest->isChecked())
268  return;
269 
270  if (index < 0 || (unsigned)index >= ActuatorCommand::CHANNEL_NUMELEM)
271  return;
272 
273  ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
274  Q_ASSERT(actuatorCommand);
275  ActuatorCommand::DataFields actuatorCommandFields = actuatorCommand->getData();
276  actuatorCommandFields.Channel[index] = value;
277  actuatorCommand->setData(actuatorCommandFields);
278 }
279 
280 bool showOutputChannelSelectWindow(bool (&selectedChannels)[ActuatorCommand::CHANNEL_NUMELEM])
281 {
282  // Get channel descriptions
283  QStringList ChannelDesc = ConfigVehicleTypeWidget::getChannelDescriptions();
284 
285  // Build up dialog
286  QDialog dialog;
287  QVBoxLayout layout;
288  QCheckBox *checkBoxes[ActuatorCommand::CHANNEL_NUMELEM];
289  QLabel infoLabel("Select output channels to calibrate: ");
290  layout.addWidget(&infoLabel);
291  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
292  checkBoxes[i] = new QCheckBox();
293  checkBoxes[i]->setText(QString("Channel ") + QString::number(i + 1) + QString(" (")
294  + ChannelDesc[i] + QString(")"));
295  checkBoxes[i]->setChecked(false);
296  layout.addWidget(checkBoxes[i]);
297  }
298 
299  QHBoxLayout horizontalLayout;
300  QPushButton buttonOk("Ok");
301  QPushButton buttonCancel("Cancel");
302  horizontalLayout.addWidget(&buttonOk);
303  horizontalLayout.addWidget(&buttonCancel);
304  layout.addLayout(&horizontalLayout);
305 
306  // Connect buttons with dialog slots
307  dialog.connect(&buttonOk, &QAbstractButton::clicked, &dialog, &QDialog::accept);
308  dialog.connect(&buttonCancel, &QAbstractButton::clicked, &dialog, &QDialog::reject);
309 
310  // Show dialog
311  dialog.setLayout(&layout);
312  int retCode = dialog.exec();
313  if (retCode == dialog.Accepted) {
314  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++)
315  selectedChannels[i] = checkBoxes[i]->isChecked();
316  return true;
317  } else
318  return false;
319 }
320 
324 void ConfigOutputWidget::startESCCalibration()
325 {
326  bool channelsToCalibrate[ActuatorCommand::CHANNEL_NUMELEM];
327  if (!showOutputChannelSelectWindow(channelsToCalibrate))
328  return;
329 
330  QMessageBox mbox(this);
331  mbox.setText(QString(tr("Starting ESC calibration.<br/><b>Please remove all propellers and "
332  "disconnect battery from ESCs.</b>")));
333  mbox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
334  mbox.setDefaultButton(QMessageBox::Cancel);
335 
336  if (mbox.exec() != QMessageBox::Ok)
337  return;
338 
339  // Get access to actuator command (for setting actual value)
340  ActuatorCommand *actuatorCommand = ActuatorCommand::GetInstance(getObjectManager());
341  Q_ASSERT(actuatorCommand);
342  ActuatorCommand::DataFields actuatorCommandFields = actuatorCommand->getData();
343  UAVObject::Metadata mdata = actuatorCommand->getMetadata();
344  // Get access to actuator settings (for min / max values)
345  ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
346  Q_ASSERT(actuatorSettings);
347  ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
348 
349  // Save previous metadata
350  accInitialData = mdata;
351 
352  // Change settings for period of calibration
355  UAVObject::SetGcsTelemetryAcked(mdata, false);
357  mdata.gcsTelemetryUpdatePeriod = 100;
358  actuatorCommand->setMetadata(mdata);
359  actuatorCommand->updated();
360 
361  mbox.setText(QString(tr("Please wait...")));
362 
363  // Set output for motors to nil to disarm
364  // Should not be necessary; battery is supposed to be disconnected, etc.
365  // But this makes it moderately safer if the user does not obey.
366  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
367  // Check if the output channel was selected
368  if (!channelsToCalibrate[i])
369  continue;
370 
371  actuatorCommandFields.Channel[i] = 0;
372  }
373 
374  actuatorCommand->setData(actuatorCommandFields);
375 
376  QEventLoop loop;
377 
378  QTimer timeout;
379  timeout.setSingleShot(true);
380  connect(&timeout, &QTimer::timeout, &loop, &QEventLoop::quit);
381  timeout.start(1250); // 1.25 seconds
382  loop.exec();
383 
384  // Increase output for all motors
385  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
386  // Check if the output channel was selected
387  if (!channelsToCalibrate[i])
388  continue;
389 
390  actuatorCommandFields.Channel[i] = actuatorSettingsData.ChannelMax[i];
391  }
392 
393  actuatorCommand->setData(actuatorCommandFields);
394 
395  mbox.setText(QString(tr("Motors outputs were increased to maximum. "
396  "Reconnect the battery and wait for notification from ESCs that they "
397  "recognized high throttle position.<br/>"
398  "<b>Immediately after that proceed to next step.</b>")));
399  if (mbox.exec() == QMessageBox::Ok) {
400  // Decrease output for all motors
401  for (unsigned int i = 0; i < ActuatorCommand::CHANNEL_NUMELEM; i++) {
402  // Check if the output channel was selected
403  if (!channelsToCalibrate[i])
404  continue;
405 
406  // calibrate the minimum of the range
407  // to be a little off what we send at idle. Blheli takes the value
408  // we give verbatim as the minimum, and small amounts of jitter
409  // can cause the motor to tick over.
410  double range = actuatorSettingsData.ChannelMax[i] - actuatorSettingsData.ChannelMin[i];
411  actuatorCommandFields.Channel[i] = actuatorSettingsData.ChannelMin[i]
412  + std::copysign(std::min(5.0, std::abs(range) / 40.0 + 0.5), range);
413  }
414  actuatorCommand->setData(actuatorCommandFields);
415 
416  mbox.setStandardButtons(QMessageBox::Ok);
417  mbox.setDefaultButton(QMessageBox::Ok);
418  mbox.setText(QString(tr("Motors outputs were decreased to minimum.<br/>Wait for "
419  "notification from ESCs that calibration is finished.")));
420  mbox.exec();
421  }
422 
423  // Restore metadata
424  actuatorCommand->setMetadata(accInitialData);
425  actuatorCommand->updated();
426 }
427 
428 /********************************
429  * Output settings
430  *******************************/
431 
436 void ConfigOutputWidget::refreshWidgetsValues(UAVObject *obj)
437 {
438  Q_UNUSED(obj);
439 
440  // Get Actuator Settings
441  ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
442  Q_ASSERT(actuatorSettings);
443  ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
444 
445  // Fill output forms
446  assignOutputChannels(actuatorSettings);
447 
448  // Get the SpinWhileArmed setting
449  m_config->spinningArmed->setChecked(actuatorSettingsData.MotorsSpinWhileArmed
450  == ActuatorSettings::MOTORSSPINWHILEARMED_TRUE);
451 
452  // Get Output rates for all channel banks
453  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
454  Q_ASSERT(pm);
456  if (utilMngr) {
457  Core::IBoardType *board = utilMngr->getBoardType();
458  if (board != NULL) {
459  QStringList banks = board->queryChannelBanks();
460 
461  // First reset & disable all channel fields/outputs, then repopulate (because
462  // we might be for instance connecting various board types one after another)
463  for (int i = 0; i < 6; i++) {
464  lblList.at(i)->setText("-");
465  rateList.at(i)->setEnabled(false);
466  }
467 
468  // Now repopulate based on board capabilities:
469  for (int i = 0; i < banks.length(); i++) {
470  lblList.at(i)->setText(banks.at(i));
471  QComboBox *ccmb = rateList.at(i);
472  ccmb->setEnabled(true);
473 
474  QString setting = timerFreqToString(actuatorSettingsData.TimerUpdateFreq[i]);
475  if (ccmb->findText(setting) == -1) {
476  ccmb->addItem(setting);
477  }
478  ccmb->setCurrentIndex(ccmb->findText(setting));
479  }
480  }
481  }
482 
483  m_config->motorCurveFit->setValue(actuatorSettingsData.MotorInputOutputCurveFit);
484  m_config->motorPowerGain->setValue(actuatorSettingsData.MotorInputOutputGain * 100);
485 
486  // Get Channel ranges:
487  QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
488  foreach (OutputChannelForm *outputChannelForm, outputChannelForms) {
489  quint32 minValue = actuatorSettingsData.ChannelMin[outputChannelForm->index()];
490  quint32 maxValue = actuatorSettingsData.ChannelMax[outputChannelForm->index()];
491 
492  outputChannelForm->setMinmax(minValue, maxValue);
493 
494  quint32 neutral = actuatorSettingsData.ChannelNeutral[outputChannelForm->index()];
495  outputChannelForm->setNeutral(neutral);
496  }
497 
498  refreshWidgetRanges();
499 }
500 
501 void ConfigOutputWidget::refreshWidgetRanges()
502 {
503  QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
504 
505  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
506  Q_ASSERT(pm);
507  UAVObjectUtilManager *utilMngr = pm->getObject<UAVObjectUtilManager>();
508 
509  if (utilMngr) {
510  Core::IBoardType *board = utilMngr->getBoardType();
511  if (board != NULL) {
512  QVector<QVector<qint32>> banks = board->getChannelBanks();
513 
514  for (int i = 0; i < banks.size(); i++) {
515  QVector<int> bank = banks[i];
516 
517  // Pull out the parameters relating to this bank, and
518  // calculate the maximum value.
519  //
520  QComboBox *ccmb = rateList.at(i);
521  quint32 timerFreq = timerStringToFreq(ccmb->currentText());
522 
523  // First saturate at the timer period and UAVO maximum value.
524  double maxPulseWidth, timerPeriodUs = UINT16_MAX;
525  int minPulseWidth = 0;
526  bool digital = false;
527 
528  switch (timerFreq) {
529  case RATE_SYNCPWM:
530  // only the timer period provides bounding
531  maxPulseWidth = timerPeriodUs;
532  break;
533  case RATE_DSHOT300:
534  case RATE_DSHOT600:
535  case RATE_DSHOT1200:
536  // 1-47 reserved for commands
537  minPulseWidth = 48;
538  // 11-bit value
539  maxPulseWidth = 2047;
540  // don't allow min/max to be changed
541  digital = true;
542  break;
543  default:
544  maxPulseWidth = 1000000 / timerFreq;
545 
546  // Should never happen, but here in case we ever have a
547  // < 16Hz PWM mode.
548  if (maxPulseWidth > timerPeriodUs)
549  maxPulseWidth = timerPeriodUs;
550  break;
551  }
552 
553  // For each of the channels...
554  for (auto channel : bank) {
555  // Find its form line and set the limit.
556  for (auto outputChannelForm : outputChannelForms) {
557  // Don't like the bogus index adjustments
558  if (outputChannelForm->index() != (channel - 1))
559  continue;
560  outputChannelForm->updateChannelLimits(
561  minPulseWidth, static_cast<int>(maxPulseWidth), digital);
562  }
563  }
564  }
565  }
566  }
567 }
568 
573 void ConfigOutputWidget::updateObjectsFromWidgets()
574 {
576 
577  ActuatorSettings *actuatorSettings = ActuatorSettings::GetInstance(getObjectManager());
578  Q_ASSERT(actuatorSettings);
579  if (actuatorSettings) {
580  ActuatorSettings::DataFields actuatorSettingsData = actuatorSettings->getData();
581  QList<OutputChannelForm *> outputChannelForms = findChildren<OutputChannelForm *>();
582 
583  foreach (OutputChannelForm *outputChannelForm, outputChannelForms) {
584  actuatorSettingsData.ChannelMax[outputChannelForm->index()] = outputChannelForm->max();
585  actuatorSettingsData.ChannelMin[outputChannelForm->index()] = outputChannelForm->min();
586  actuatorSettingsData.ChannelNeutral[outputChannelForm->index()] =
587  outputChannelForm->neutral();
588  }
589 
590  // Set update rates
591  actuatorSettingsData.TimerUpdateFreq[0] =
592  timerStringToFreq(m_config->cb_outputRate1->currentText());
593  actuatorSettingsData.TimerUpdateFreq[1] =
594  timerStringToFreq(m_config->cb_outputRate2->currentText());
595  actuatorSettingsData.TimerUpdateFreq[2] =
596  timerStringToFreq(m_config->cb_outputRate3->currentText());
597  actuatorSettingsData.TimerUpdateFreq[3] =
598  timerStringToFreq(m_config->cb_outputRate4->currentText());
599  actuatorSettingsData.TimerUpdateFreq[4] =
600  timerStringToFreq(m_config->cb_outputRate5->currentText());
601  actuatorSettingsData.TimerUpdateFreq[5] =
602  timerStringToFreq(m_config->cb_outputRate6->currentText());
603 
604  actuatorSettingsData.MotorInputOutputCurveFit = m_config->motorCurveFit->value();
605  actuatorSettingsData.MotorInputOutputGain = m_config->motorPowerGain->value() * 0.01;
606 
607  if (m_config->spinningArmed->isChecked() == true)
608  actuatorSettingsData.MotorsSpinWhileArmed = ActuatorSettings::MOTORSSPINWHILEARMED_TRUE;
609  else
610  actuatorSettingsData.MotorsSpinWhileArmed =
611  ActuatorSettings::MOTORSSPINWHILEARMED_FALSE;
612 
613  // Apply settings
614  actuatorSettings->setData(actuatorSettingsData);
615  }
616 
617  refreshWidgetRanges();
618 }
619 
620 QString ConfigOutputWidget::timerFreqToString(quint32 freq) const
621 {
622  static const QMap<quint32, QString> mapping{
623  { RATE_SYNCPWM, tr("SyncPWM") },
624  { RATE_DSHOT300, tr("Dshot300") },
625  { RATE_DSHOT600, tr("Dshot600") },
626  { RATE_DSHOT1200, tr("Dshot1200") },
627  };
628  return mapping.value(freq, QString::number(freq));
629 }
630 
631 quint32 ConfigOutputWidget::timerStringToFreq(QString str) const
632 {
633  static const QMap<QString, quint32> mapping{
634  { tr("SyncPWM"), RATE_SYNCPWM },
635  { tr("Dshot300"), RATE_DSHOT300 },
636  { tr("Dshot600"), RATE_DSHOT600 },
637  { tr("Dshot1200"), RATE_DSHOT1200 },
638  };
639  return mapping.value(str, str.toUInt());
640 }
641 
642 void ConfigOutputWidget::tabSwitchingAway()
643 {
644  stopTests();
645 }
646 
647 void ConfigOutputWidget::stopTests()
648 {
649  if (m_config->channelOutTest->isChecked()) {
650  qDebug() << "Output testing stopped by signal of incompatible mode";
651  }
652 
653  m_config->channelOutTest->setChecked(false);
654 }
655 
659 void ConfigOutputWidget::do_SetDirty()
660 {
661  setDirty(true);
662 }
void setDirty(bool value)
UAVObjectUtilManager * utilMngr
static ModeManager * instance()
Definition: modemanager.h:62
void addWidget(QWidget *widget)
virtual QVector< QVector< int > > getChannelBanks()
Get banks of output PWM channels banks on the board.
Definition: iboardtype.h:121
static void SetFlightAccess(Metadata &meta, AccessMode mode)
Definition: uavobject.cpp:387
void currentModeAboutToChange(Core::IMode *mode)
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
void channelChanged(int index, int value)
void setMinmax(int minimum, int maximum)
void setAssignment(const QString &assignment)
static void SetGcsTelemetryAcked(Metadata &meta, quint8 val)
Definition: uavobject.cpp:447
static UpdateMode GetGcsTelemetryUpdateMode(const Metadata &meta)
Definition: uavobject.cpp:479
for i
Definition: OPPlots.m:140
virtual QStringList queryChannelBanks()
Query number & names of output PWM channels banks on the board.
Definition: iboardtype.cpp:13
void objectUpdated(UAVObject *obj)
Signal sent whenever any field of the object is updated.
void enableControls(bool enable)
static void SetFlightTelemetryUpdateMode(Metadata &meta, UpdateMode val)
Definition: uavobject.cpp:468
ConfigOutputWidget(QWidget *parent=nullptr)
void updateObjectsFromWidgetsRequested()
void enableChannelTest(bool state)
void updateChannelLimits(int minPulse, int maxPulse, bool digitalProtocol=false)
bool showOutputChannelSelectWindow(bool(&selectedChannels)[ActuatorCommand::CHANNEL_NUMELEM])
void addUAVObject(QString objectName, QList< int > *reloadGroups=NULL)
int neutral() const
void(NAME)
virtual void enableControls(bool enable)
Definition: icore.h:39
void setNeutral(int value)
static void SetGcsTelemetryUpdateMode(Metadata &meta, UpdateMode val)
Definition: uavobject.cpp:490
void currentModeChanged(Core::IMode *mode)
UAVObject * getObject(const QString &name, quint32 instId=0)
Core::IBoardType * getBoardType()
Get the IBoardType corresponding to the connected board.
UAVObjectManager * getObjectManager()
ConfigTaskWidget::getObjectManager Utility function to get a pointer to the object manager...
static QStringList getChannelDescriptions()