2 * This file is part of the sigrok project.
4 * Copyright (C) 2010-2011 Uwe Hermann <uwe@hermann-uwe.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <sigrokdecode.h>
26 #include <QMessageBox>
27 #include <QFileDialog>
28 #include <QProgressDialog>
29 #include <QDockWidget>
31 #include "mainwindow.h"
32 #include "ui_mainwindow.h"
33 #include "configform.h"
34 #include "ui_configform.h"
35 #include "channelform.h"
36 #include "ui_channelform.h"
37 #include "decodersform.h"
38 #include "ui_decodersform.h"
39 #include "decoderstackform.h"
40 #include "ui_decoderstackform.h"
43 /* __STDC_FORMAT_MACROS is required for PRIu64 and friends (in C++). */
44 #define __STDC_FORMAT_MACROS
49 #include <libsigrok/libsigrok.h>
50 #include <sigrokdecode.h>
53 #define DOCK_VERTICAL 0
54 #define DOCK_HORIZONTAL 1
56 uint64_t limit_samples = 0; /* FIXME */
58 QProgressDialog *progress = NULL;
60 /* TODO: Documentation. */
62 static int logger(void *cb_data, int loglevel, const char *format, va_list args)
66 if (loglevel > srd_log_loglevel_get())
69 s.vsprintf(format, args);
71 MainWindow *mw = (MainWindow *)cb_data;
72 mw->ui->plainTextEdit->appendPlainText(QString("srd: ").append(s));
78 MainWindow::MainWindow(QWidget *parent)
79 : QMainWindow(parent), ui(new Ui::MainWindow)
81 struct sr_dev_driver **drivers;
87 configChannelTitleBarLayout = DOCK_VERTICAL; /* Vertical layout */
88 for (int i = 0; i < NUMCHANNELS; ++i)
89 dockWidgets[i] = NULL;
94 QMainWindow::setCentralWidget(ui->mainWidget);
96 srd_log_loglevel_set(SRD_LOG_SPEW);
98 if (srd_log_callback_set(logger, (void *)this) != SRD_OK) {
99 qDebug() << "ERROR: srd_log_handler_set() failed.";
102 qDebug() << "srd_log_handler_set() call successful.";
104 /* Initialize all libsigrok drivers. */
105 drivers = sr_driver_list();
106 for (i = 0; drivers[i]; i++) {
107 if (sr_driver_init(drivers[i]) != SR_OK) {
108 qDebug("Failed to initialize driver %s", drivers[i]->name);
113 // this->setDockOptions(QMainWindow::AllowNestedDocks);
116 MainWindow::~MainWindow()
124 void MainWindow::setupDockWidgets(void)
126 /* TODO: Do not create new dockWidgets if we already have them. */
128 /* TODO: Kill any old dockWidgets before creating new ones? */
130 for (int i = 0; i < getNumChannels(); ++i) {
131 channelForms[i] = new ChannelForm(this);
132 channelForms[i]->setChannelNumber(i);
134 dockWidgets[i] = new QDockWidget(this);
135 dockWidgets[i]->setAllowedAreas(Qt::BottomDockWidgetArea);
137 QDockWidget::DockWidgetFeatures f;
138 f = QDockWidget::DockWidgetClosable |
139 QDockWidget::DockWidgetMovable |
140 QDockWidget::DockWidgetFloatable;
141 if (configChannelTitleBarLayout == DOCK_VERTICAL)
142 f |= QDockWidget::DockWidgetVerticalTitleBar;
143 dockWidgets[i]->setFeatures(f);
144 dockWidgets[i]->setWidget(channelForms[i]);
145 addDockWidget(Qt::BottomDockWidgetArea, dockWidgets[i],
148 /* Update labels upon changes. */
149 QObject::connect(channelForms[i],
150 SIGNAL(sampleStartChanged(QString)),
151 ui->labelSampleStart, SLOT(setText(QString)));
152 QObject::connect(channelForms[i],
153 SIGNAL(sampleEndChanged(QString)),
154 ui->labelSampleEnd, SLOT(setText(QString)));
155 QObject::connect(channelForms[i],
156 SIGNAL(scaleFactorChanged(QString)),
157 ui->labelScaleFactor, SLOT(setText(QString)));
159 /* Redraw channels upon changes. */
160 QObject::connect(channelForms[i],
161 SIGNAL(sampleStartChanged(QString)),
162 channelForms[i], SLOT(generatePainterPath()));
163 QObject::connect(channelForms[i],
164 SIGNAL(sampleEndChanged(QString)),
165 channelForms[i], SLOT(generatePainterPath()));
166 QObject::connect(channelForms[i],
167 SIGNAL(scaleFactorChanged(QString)),
168 channelForms[i], SLOT(generatePainterPath()));
170 // dockWidgets[i]->show();
173 /* If the user renames a channel, adapt the dock title. */
174 QObject::connect(lineEdits[i], SIGNAL(textChanged(QString)),
175 dockWidgets[i], SLOT(setWindowTitle(QString)));
179 /* For now, display only one scrollbar which scrolls all channels. */
180 QDockWidget* scrollWidget = new QDockWidget(this);
181 scrollWidget->setAllowedAreas(Qt::BottomDockWidgetArea);
182 horizontalScrollBar = new QScrollBar(this);
183 horizontalScrollBar->setOrientation(Qt::Horizontal);
185 QDockWidget::DockWidgetFeatures f;
186 if (configChannelTitleBarLayout == DOCK_VERTICAL)
187 f |= QDockWidget::DockWidgetVerticalTitleBar;
188 scrollWidget->setFeatures(f);
189 scrollWidget->setWidget(horizontalScrollBar);
190 addDockWidget(Qt::BottomDockWidgetArea, scrollWidget,
193 for (int i = 0; i < getNumChannels(); ++i) {
194 /* The scrollbar scrolls all channels. */
195 connect(horizontalScrollBar, SIGNAL(valueChanged(int)),
196 channelForms[i], SLOT(setScrollBarValue(int)));
200 GSList *MainWindow::getDevices(void)
205 void MainWindow::setCurrentLA(int la)
210 int MainWindow::getCurrentLA(void)
215 void MainWindow::setNumChannels(int ch)
220 int MainWindow::getNumChannels(void)
225 void MainWindow::on_actionAbout_triggered()
228 struct sr_dev_driver **drivers;
229 struct sr_input_format **inputs;
230 struct sr_output_format **outputs;
231 struct srd_decoder *dec;
233 QString s = tr("%1 %2<br />%3<br /><a href=\"%4\">%4</a>\n<p>")
234 .arg(QApplication::applicationName())
235 .arg(QApplication::applicationVersion())
236 .arg(tr("GNU GPL, version 2 or later"))
237 .arg(QApplication::organizationDomain());
239 s.append("<b>" + tr("Supported hardware drivers:") + "</b><table>");
240 drivers = sr_driver_list();
241 for (int i = 0; drivers[i]; ++i) {
242 s.append(QString("<tr><td><i>%1</i></td><td>%2</td></tr>")
243 .arg(QString(drivers[i]->name))
244 .arg(QString(drivers[i]->longname)));
246 s.append("</table><p>");
248 s.append("<b>" + tr("Supported input formats:") + "</b><table>");
249 inputs = sr_input_list();
250 for (int i = 0; inputs[i]; ++i) {
251 s.append(QString("<tr><td><i>%1</i></td><td>%2</td></tr>")
252 .arg(QString(inputs[i]->id))
253 .arg(QString(inputs[i]->description)));
255 s.append("</table><p>");
257 s.append("<b>" + tr("Supported output formats:") + "</b><table>");
258 outputs = sr_output_list();
259 for (int i = 0; outputs[i]; ++i) {
260 s.append(QString("<tr><td><i>%1</i></td><td>%2</td></tr>")
261 .arg(QString(outputs[i]->id))
262 .arg(QString(outputs[i]->description)));
264 s.append("</table><p>");
266 s.append("<b>" + tr("Supported protocol decoders:") + "</b><table>");
267 for (l = srd_decoder_list(); l; l = l->next) {
268 dec = (struct srd_decoder *)l->data;
269 s.append(QString("<tr><td><i>%1</i></td><td>%2</td></tr>")
270 .arg(QString(dec->id))
271 .arg(QString(dec->longname)));
273 s.append("</table>");
275 QMessageBox::about(this, tr("About"), s);
278 void MainWindow::on_actionAbout_Qt_triggered()
280 QMessageBox::aboutQt(this, tr("About Qt"));
283 void MainWindow::on_actionPreferences_triggered()
285 ConfigForm *form = new ConfigForm();
289 void MainWindow::on_actionScan_triggered()
293 int num_devs, pos, i;
294 struct sr_dev_driver **drivers;
295 struct sr_dev_inst *sdi;
296 char *di_num_probes, *str;
297 struct sr_samplerates *samplerates;
298 const static float mult[] = { 2.f, 2.5f, 2.f };
300 statusBar()->showMessage(tr("Scanning for logic analyzers..."), 2000);
303 /* TODO: tell drivers to clean up all instances */
308 /* Scan all drivers for all devices. */
309 drivers = sr_driver_list();
310 for (i = 0; drivers[i]; i++) {
311 tmpdevs = sr_driver_scan(drivers[i], NULL);
312 for (l = tmpdevs; l; l = l->next)
313 devices = g_slist_append(devices, l->data);
314 g_slist_free(tmpdevs);
316 num_devs = g_slist_length(devices);
318 ui->comboBoxLA->clear();
319 for (int i = 0; i < num_devs; ++i) {
320 sdi = (struct sr_dev_inst *)g_slist_nth_data(devices, i);
321 ui->comboBoxLA->addItem(sdi->driver->name); /* TODO: Full name */
325 s = tr("No supported logic analyzer found.");
326 statusBar()->showMessage(s, 2000);
328 } else if (num_devs == 1) {
329 s = tr("Found supported logic analyzer: ");
330 sdi = (struct sr_dev_inst *)g_slist_nth_data(devices, 0 /* opt_dev */);
331 s.append(sdi->driver->name);
332 statusBar()->showMessage(s, 2000);
334 /* TODO: Allow user to select one of the devices. */
335 s = tr("Found multiple logic analyzers: ");
336 for (int i = 0; i < num_devs; ++i) {
337 sdi = (struct sr_dev_inst *)g_slist_nth_data(devices, i);
338 s.append(sdi->driver->name);
339 if (i != num_devs - 1)
342 statusBar()->showMessage(s, 2000);
346 sdi = (struct sr_dev_inst *)g_slist_nth_data(devices, 0 /* opt_dev */);
348 setCurrentLA(0 /* TODO */);
350 if (sr_info_get(sdi->driver, SR_DI_NUM_PROBES,
351 (const void **)&di_num_probes, sdi) == SR_OK)
352 setNumChannels(GPOINTER_TO_INT(di_num_probes));
354 setNumChannels(8); /* FIXME: Error handling. */
356 ui->comboBoxLA->clear();
357 ui->comboBoxLA->addItem(sdi->driver->name); /* TODO: Full name */
359 s = QString(tr("Channels: %1")).arg(getNumChannels());
360 ui->labelChannels->setText(s);
362 if (sr_info_get(sdi->driver, SR_DI_SAMPLERATES,
363 (const void **)&samplerates, sdi) != SR_OK || !samplerates) {
364 /* TODO: Error handling. */
367 /* Populate the combobox with supported samplerates. */
368 ui->comboBoxSampleRate->clear();
370 ui->comboBoxSampleRate->addItem("No samplerate");
371 ui->comboBoxSampleRate->setEnabled(false);
372 } else if (samplerates->list != NULL) {
373 for (int i = 0; samplerates->list[i]; ++i) {
374 str = sr_samplerate_string(samplerates->list[i]);
377 ui->comboBoxSampleRate->insertItem(0, s,
378 QVariant::fromValue(samplerates->list[i]));
380 ui->comboBoxSampleRate->setEnabled(true);
383 for (uint64_t r = samplerates->low; r <= samplerates->high; ) {
384 str = sr_samplerate_string(r);
387 ui->comboBoxSampleRate->insertItem(0, s,
388 QVariant::fromValue(r));
392 ui->comboBoxSampleRate->setEnabled(true);
394 ui->comboBoxSampleRate->setCurrentIndex(0);
397 ui->comboBoxNumSamples->clear();
398 ui->comboBoxNumSamples->addItem("100", 100); /* For testing... */
399 ui->comboBoxNumSamples->addItem("3000000", 3000000);
400 ui->comboBoxNumSamples->addItem("2000000", 2000000);
401 ui->comboBoxNumSamples->addItem("1000000", 1000000);
403 ui->comboBoxNumSamples->setEditable(true);
405 if (getCurrentLA() >= 0)
408 /* Enable all relevant fields now (i.e. make them non-gray). */
409 ui->comboBoxNumSamples->setEnabled(true);
410 ui->labelChannels->setEnabled(true);
411 ui->action_Get_samples->setEnabled(true);
414 void MainWindow::on_action_Open_triggered()
417 QString fileName = QFileDialog::getOpenFileName(this,
418 tr("Open sample file"), ".",
419 tr("Raw sample files (*.raw *.bin);;"
420 "Gnuplot data files (*.dat);;"
421 "VCD files (*.vcd);;"
424 if (fileName == NULL)
427 QFile file(fileName);
428 file.open(QIODevice::ReadOnly);
429 QDataStream in(&file);
431 /* TODO: Implement support for loading different input formats. */
433 sample_buffer = (uint8_t *)malloc(file.size());
434 if (sample_buffer == NULL) {
435 /* TODO: Error handling. */
438 in.readRawData((char *)sample_buffer, file.size());
440 setNumSamples(file.size());
441 setNumChannels(8); /* FIXME */
447 ui->comboBoxLA->clear();
448 ui->comboBoxLA->addItem(tr("File"));
450 /* FIXME: Store number of channels in the file or allow user config. */
451 s = QString(tr("Channels: %1")).arg(getNumChannels());
452 ui->labelChannels->setText(s);
453 ui->labelChannels->setEnabled(false);
455 ui->comboBoxSampleRate->clear();
456 ui->comboBoxSampleRate->setEnabled(false); /* FIXME */
458 ui->comboBoxNumSamples->clear();
459 ui->comboBoxNumSamples->addItem(QString::number(getNumSamples()),
460 QVariant::fromValue(getNumSamples()));
461 ui->comboBoxNumSamples->setEnabled(true);
463 ui->labelSampleStart->setText(tr("Start sample: "));
464 ui->labelSampleStart->setEnabled(true);
466 ui->labelSampleEnd->setText(tr("End sample: "));
467 ui->labelSampleEnd->setEnabled(true);
469 ui->labelScaleFactor->setText(tr("Scale factor: "));
470 ui->labelScaleFactor->setEnabled(true);
472 ui->action_Save_as->setEnabled(true);
473 ui->action_Get_samples->setEnabled(false);
475 for (int i = 0; i < getNumChannels(); ++i) {
476 channelForms[i]->setNumSamples(file.size());
478 channelForms[i]->update();
482 void MainWindow::on_action_Save_as_triggered()
484 QString fileName = QFileDialog::getSaveFileName(this,
485 tr("Save sample file"), ".",
486 tr("Raw sample files (*.raw *.bin);;All files (*)"));
488 if (fileName == NULL)
491 QFile file(fileName);
492 file.open(QIODevice::WriteOnly);
493 QDataStream out(&file);
495 /* TODO: Implement support for saving to different output formats. */
497 out.writeRawData((const char *)sample_buffer,
498 getNumSamples() * (getNumChannels() / 8));
502 void datafeed_in(const struct sr_dev_inst *sdi,
503 struct sr_datafeed_packet *packet)
505 static int num_probes = 0;
506 static int logic_probelist[SR_MAX_NUM_PROBES + 1] = { -1 };
507 static uint64_t received_samples = 0;
508 static int triggered = 0;
509 static int unitsize = 0;
510 struct sr_probe *probe;
511 static struct sr_datafeed_header *header;
512 struct sr_datafeed_meta_logic *meta_logic;
513 struct sr_datafeed_logic *logic;
514 int num_enabled_probes, sample_size, ret;
516 uint64_t filter_out_len;
519 /* If the first packet to come in isn't a header, don't even try. */
520 // if (packet->type != SR_DF_HEADER && o == NULL)
523 /* TODO: Also check elsewhere? */
524 /* TODO: Abort acquisition too, if user pressed cancel. */
525 if (progress && progress->wasCanceled())
530 switch (packet->type) {
532 qDebug("SR_DF_HEADER");
533 header = (struct sr_datafeed_header *)packet->payload;
537 // progress->setValue(received_samples); /* FIXME */
540 qDebug("SR_DF_TRIGGER");
544 case SR_DF_META_LOGIC:
545 qDebug("SR_DF_META_LOGIC");
546 meta_logic = (struct sr_datafeed_meta_logic *)packet->payload;
547 num_probes = meta_logic->num_probes;
548 num_enabled_probes = 0;
549 for (int i = 0; i < meta_logic->num_probes; ++i) {
550 probe = (struct sr_probe *)g_slist_nth_data(sdi->probes, i);
552 logic_probelist[num_enabled_probes++] = probe->index;
554 logic_probelist[num_enabled_probes] = -1;
556 qDebug() << "Acquisition with" << num_enabled_probes << "/"
557 << num_probes << "probes at"
558 << sr_samplerate_string(meta_logic->samplerate)
559 << "starting at" << ctime(&header->starttime.tv_sec)
560 << "(" << limit_samples << "samples)";
562 /* TODO: realloc() */
565 logic = (sr_datafeed_logic *)packet->payload;
566 qDebug() << "SR_DF_LOGIC (length =" << logic->length
567 << ", unitsize = " << logic->unitsize << ")";
568 sample_size = logic->unitsize;
570 if (sample_size == -1)
573 /* Don't store any samples until triggered. */
574 // if (opt_wait_trigger && !triggered)
577 if (received_samples >= limit_samples)
581 ret = sr_filter_probes(sample_size, 1 /* unitsize */, logic_probelist,
582 (uint8_t *)logic->data, logic->length,
583 &filter_out, &filter_out_len);
587 for (uint64_t i = 0; i < filter_out_len; ++i) {
588 sample = filter_out[i];
589 sample_buffer[i] = (uint8_t)(sample & 0xff); /* FIXME */
590 // qDebug("Sample %" PRIu64 ": 0x%x", i, sample);
592 received_samples += logic->length / sample_size;
594 progress->setValue(received_samples);
597 qDebug("SR_DF_XXXX, not yet handled");
602 void MainWindow::on_action_Get_samples_triggered()
607 struct sr_dev_inst *sdi;
608 QComboBox *n = ui->comboBoxNumSamples;
610 opt_dev = 0; /* FIXME */
613 * The number of samples to get is a drop-down list, but you can also
614 * manually enter a value. If the latter, we have to get the value from
615 * the lineEdit object, otherwise via itemData() and the list index.
617 if (n->lineEdit() != NULL) {
618 limit_samples = n->lineEdit()->text().toLongLong();
620 limit_samples = n->itemData(n->currentIndex()).toLongLong();
623 samplerate = ui->comboBoxSampleRate->itemData(
624 ui->comboBoxSampleRate->currentIndex()).toLongLong();
626 /* TODO: Sanity checks. */
628 /* TODO: Assumes unitsize == 1. */
629 if (!(sample_buffer = (uint8_t *)malloc(limit_samples))) {
630 /* TODO: Error handling. */
635 sr_session_datafeed_callback_add(datafeed_in);
637 sdi = (struct sr_dev_inst *)g_slist_nth_data(devices, opt_dev);
639 /* Set the number of samples we want to get from the device. */
640 if (sr_dev_config_set(sdi, SR_HWCAP_LIMIT_SAMPLES,
641 &limit_samples) != SR_OK) {
642 qDebug("Failed to set sample limit.");
643 sr_session_destroy();
647 if (sr_session_dev_add(sdi) != SR_OK) {
648 qDebug("Failed to use device.");
649 sr_session_destroy();
653 /* Set the samplerate. */
654 if (sr_dev_config_set(sdi, SR_HWCAP_SAMPLERATE, &samplerate) != SR_OK) {
655 qDebug("Failed to set samplerate.");
656 sr_session_destroy();
660 if (sr_session_start() != SR_OK) {
661 qDebug("Failed to start session.");
662 sr_session_destroy();
666 progress = new QProgressDialog("Getting samples from logic analyzer...",
667 "Abort", 0, limit_samples, this);
668 progress->setWindowModality(Qt::WindowModal);
669 progress->setMinimumDuration(100);
672 sr_session_destroy();
674 for (int i = 0; i < getNumChannels(); ++i) {
675 channelForms[i]->setNumSamples(limit_samples);
676 // channelForms[i]->setSampleStart(0);
677 // channelForms[i]->setSampleEnd(limit_samples);
679 /* If any of the scale factors change, update all of them.. */
680 connect(channelForms[i], SIGNAL(scaleFactorChanged(float)),
681 w, SLOT(updateScaleFactors(float)));
683 channelForms[i]->generatePainterPath();
684 // channelForms[i]->update();
687 setNumSamples(limit_samples);
689 /* Enable the relevant labels/buttons. */
690 ui->labelSampleStart->setEnabled(true);
691 ui->labelSampleEnd->setEnabled(true);
692 ui->labelScaleFactor->setEnabled(true);
693 ui->action_Save_as->setEnabled(true);
695 // sr_hw_get_samples_shutdown(&ctx, 1000);
698 void MainWindow::setSampleRate(uint64_t s)
703 uint64_t MainWindow::getSampleRate(void)
708 void MainWindow::setNumSamples(uint64_t s)
714 void MainWindow::updateScrollBar(void)
716 int stepSize = channelForms[0]->getStepSize();
717 float scaleFactor = channelForms[0]->getScaleFactor();
719 uint64_t viewport = channelForms[0]->getNumSamplesVisible() * stepSize / scaleFactor;
720 uint64_t length = numSamples * stepSize / scaleFactor;
722 horizontalScrollBar->setMinimum(0);
723 horizontalScrollBar->setPageStep(viewport);
724 if (viewport < length)
726 horizontalScrollBar->setMaximum(length - viewport / 2);
728 horizontalScrollBar->setMaximum(0);
733 uint64_t MainWindow::getNumSamples(void)
738 void MainWindow::on_action_New_triggered()
740 for (int i = 0; i < NUMCHANNELS; ++i) {
741 if (dockWidgets[i]) {
742 /* TODO: Check if all childs are also killed. */
743 delete dockWidgets[i];
744 dockWidgets[i] = NULL;
748 ui->comboBoxLA->clear();
749 ui->comboBoxLA->addItem(tr("No LA detected"));
751 ui->labelChannels->setText(tr("Channels: "));
752 ui->labelChannels->setEnabled(false);
754 ui->comboBoxSampleRate->clear();
755 ui->comboBoxSampleRate->setEnabled(false);
757 ui->comboBoxNumSamples->clear();
758 ui->comboBoxNumSamples->setEnabled(false);
760 ui->labelSampleStart->setText(tr("Start sample: "));
761 ui->labelSampleStart->setEnabled(false);
763 ui->labelSampleEnd->setText(tr("End sample: "));
764 ui->labelSampleEnd->setEnabled(false);
766 ui->labelScaleFactor->setText(tr("Scale factor: "));
767 ui->labelScaleFactor->setEnabled(false);
769 ui->action_Save_as->setEnabled(false);
770 ui->action_Get_samples->setEnabled(false);
774 /* TODO: More cleanups. */
775 /* TODO: Free sample buffer(s). */
778 void MainWindow::configChannelTitleBarLayoutChanged(int index)
780 QDockWidget::DockWidgetFeatures f =
781 QDockWidget::DockWidgetClosable |
782 QDockWidget::DockWidgetMovable |
783 QDockWidget::DockWidgetFloatable;
785 configChannelTitleBarLayout = index;
787 if (configChannelTitleBarLayout == DOCK_VERTICAL)
788 f |= QDockWidget::DockWidgetVerticalTitleBar;
790 for (int i = 0; i < getNumChannels(); ++i)
791 dockWidgets[i]->setFeatures(f);
795 void MainWindow::updateScaleFactors(float value)
799 /* TODO: There must be a better way to do this. */
804 for (int i = 0; i < getNumChannels(); ++i) {
805 // qDebug("updating scaleFactor %d", i);
806 channelForms[i]->setScaleFactor(value);
807 // qDebug("updating scaleFactor %d (DONE)", i);
813 void MainWindow::on_actionConfigure_triggered()
815 DecodersForm *form = new DecodersForm();
819 void MainWindow::on_actionProtocol_decoder_stacks_triggered()
821 DecoderStackForm *form = new DecoderStackForm();
825 extern "C" void show_pd_annotation(struct srd_proto_data *pdata, void *cb_data)
829 annotations = (char **)pdata->data;
831 MainWindow *mw = (MainWindow *)cb_data;
833 mw->ui->plainTextEdit->appendPlainText(
834 QString("%1-%2: %3: %4").arg(pdata->start_sample)
835 .arg(pdata->end_sample).arg(pdata->pdo->proto_id)
836 .arg((char *)annotations[0]));
839 void MainWindow::on_actionQUICK_HACK_PD_TEST_triggered()
843 struct srd_decoder_inst *di;
844 GHashTable *pd_opthash;
845 uint8_t *buf = (uint8_t *)malloc(N + 1);
847 pd_opthash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
850 /* Hardcode a specific I2C probe mapping. */
851 g_hash_table_insert(pd_opthash, g_strdup("scl"), g_strdup("5"));
852 g_hash_table_insert(pd_opthash, g_strdup("sda"), g_strdup("7"));
855 * Get data from a hardcoded binary file.
856 * (converted to binary from melexis_mlx90614_5s_24deg.sr.
858 QFile file("foo.bin");
859 int ret = file.open(QIODevice::ReadOnly);
860 ret = file.read((char *)buf, N);
862 // sr_log_loglevel_set(SR_LOG_NONE);
863 // srd_log_loglevel_set(SRD_LOG_NONE);
865 if (!(di = srd_inst_new("i2c", pd_opthash))) {
866 ui->plainTextEdit->appendPlainText("ERROR: srd_inst_new");
870 if (srd_inst_probe_set_all(di, pd_opthash) != SRD_OK) {
871 ui->plainTextEdit->appendPlainText("ERROR: srd_inst_set_probes");
875 if (srd_pd_output_callback_add(SRD_OUTPUT_ANN,
876 (srd_pd_output_callback_t)show_pd_annotation, (void *)this) != SRD_OK) {
877 ui->plainTextEdit->appendPlainText("ERROR: srd_pd_output_callback_add");
881 if (srd_session_start(8, 1, 1000000) != SRD_OK) {
882 ui->plainTextEdit->appendPlainText("ERROR: srd_session_start");
886 if (srd_session_send(0, buf, N) != SRD_OK) {
887 ui->plainTextEdit->appendPlainText("ERROR: srd_session_send");