summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/regtools/qeditor/analyser.cpp44
-rw-r--r--utils/regtools/qeditor/analyser.h64
-rw-r--r--utils/regtools/qeditor/backend.cpp156
-rw-r--r--utils/regtools/qeditor/backend.h77
-rw-r--r--utils/regtools/qeditor/main.cpp30
-rw-r--r--utils/regtools/qeditor/mainwindow.cpp108
-rw-r--r--utils/regtools/qeditor/mainwindow.h44
-rw-r--r--utils/regtools/qeditor/qeditor.pro8
-rw-r--r--utils/regtools/qeditor/regtab.cpp392
-rw-r--r--utils/regtools/qeditor/regtab.h85
-rw-r--r--utils/regtools/qeditor/settings.cpp32
-rw-r--r--utils/regtools/qeditor/settings.h21
-rw-r--r--utils/regtools/qeditor/std_analysers.cpp636
-rw-r--r--utils/regtools/qeditor/std_analysers.h95
14 files changed, 1792 insertions, 0 deletions
diff --git a/utils/regtools/qeditor/analyser.cpp b/utils/regtools/qeditor/analyser.cpp
new file mode 100644
index 0000000000..1ab213872b
--- /dev/null
+++ b/utils/regtools/qeditor/analyser.cpp
@@ -0,0 +1,44 @@
+#include "analyser.h"
+
+Analyser::Analyser(const soc_t& soc, IoBackend *backend)
+ :m_soc(soc), m_io_backend(backend)
+{
+}
+
+Analyser::~Analyser()
+{
+}
+
+AnalyserFactory::AnalyserFactory(bool _register)
+{
+ if(_register)
+ RegisterAnalyser(this);
+}
+
+AnalyserFactory::~AnalyserFactory()
+{
+}
+
+QVector< AnalyserFactory * > AnalyserFactory::m_factories;
+
+QStringList AnalyserFactory::GetAnalysersForSoc(const QString& soc_name)
+{
+ QStringList list;
+ for(int i = 0; i < m_factories.size(); i++)
+ if(m_factories[i]->SupportSoc(soc_name))
+ list.append(m_factories[i]->GetName());
+ return list;
+}
+
+AnalyserFactory *AnalyserFactory::GetAnalyserByName(const QString& name)
+{
+ for(int i = 0; i < m_factories.size(); i++)
+ if(m_factories[i]->GetName() == name)
+ return m_factories[i];
+ return 0;
+}
+
+void AnalyserFactory::RegisterAnalyser(AnalyserFactory *factory)
+{
+ m_factories.append(factory);
+}
diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h
new file mode 100644
index 0000000000..33094574c1
--- /dev/null
+++ b/utils/regtools/qeditor/analyser.h
@@ -0,0 +1,64 @@
+#ifndef _ANALYSER_H_
+#define _ANALYSER_H_
+
+#include <QObject>
+#include <QVector>
+#include <QString>
+#include "backend.h"
+
+class Analyser : public QObject
+{
+ Q_OBJECT
+public:
+ Analyser(const soc_t& soc, IoBackend *backend);
+ virtual ~Analyser();
+ virtual QWidget *GetWidget() = 0;
+
+protected:
+ soc_t m_soc;
+ IoBackend *m_io_backend;
+};
+
+class AnalyserFactory
+{
+public:
+ AnalyserFactory(bool _register);
+ virtual ~AnalyserFactory();
+
+ virtual QString GetName() = 0;
+ virtual bool SupportSoc(const QString& soc_name) = 0;
+ // return NULL of soc is not handled by the analyser
+ virtual Analyser *Create(const soc_t& soc, IoBackend *backend) = 0;
+private:
+ QString m_name;
+
+public:
+ static QStringList GetAnalysersForSoc(const QString& soc_name);
+ static AnalyserFactory *GetAnalyserByName(const QString& name);
+ static void RegisterAnalyser(AnalyserFactory *factory);
+
+private:
+ static QVector< AnalyserFactory * > m_factories;
+};
+
+template< typename T >
+class TmplAnalyserFactory : public AnalyserFactory
+{
+public:
+ TmplAnalyserFactory(bool _register, const QString& name) :AnalyserFactory(_register) { m_name = name; }
+ virtual ~TmplAnalyserFactory() {}
+
+ virtual QString GetName() { return m_name; }
+ virtual bool SupportSoc(const QString& soc_name) { return T::SupportSoc(soc_name); }
+ // return NULL of soc is not handled by the analyser
+ virtual T *Create(const soc_t& soc, IoBackend *backend)
+ {
+ if(!T::SupportSoc(soc.name.c_str()))
+ return 0;
+ return new T(soc, backend);
+ }
+private:
+ QString m_name;
+};
+
+#endif /* _ANALYSER_H_ */
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
new file mode 100644
index 0000000000..e011965bd2
--- /dev/null
+++ b/utils/regtools/qeditor/backend.cpp
@@ -0,0 +1,156 @@
+#include <QFile>
+#include <QTextStream>
+#include <QDebug>
+#include "backend.h"
+
+Backend::Backend()
+{
+}
+
+QStringList Backend::GetSocNameList()
+{
+ QStringList sl;
+ for(size_t i = 0; i < m_socs.size(); i++)
+ sl.append(QString(m_socs[i].name.c_str()));
+ return sl;
+}
+
+bool Backend::GetSocByName(const QString& name, soc_t& s)
+{
+ for(size_t i = 0; i < m_socs.size(); i++)
+ if(m_socs[i].name == name.toStdString())
+ {
+ s = m_socs[i];
+ return true;
+ }
+ return false;
+}
+
+bool Backend::LoadSocDesc(const QString& filename)
+{
+ bool ret = soc_desc_parse_xml(filename.toStdString(), m_socs);
+ emit OnSocListChanged();
+ return ret;
+}
+
+IoBackend *Backend::CreateFileIoBackend(const QString& filename)
+{
+ return new FileIoBackend(filename);
+}
+
+IoBackend *Backend::CreateDummyIoBackend()
+{
+ return new DummyIoBackend();
+}
+
+IoBackend::IoBackend()
+{
+}
+
+FileIoBackend::FileIoBackend(const QString& filename)
+{
+ m_filename = filename;
+ Reload();
+}
+
+QString FileIoBackend::GetSocName()
+{
+ return m_soc;
+}
+
+bool FileIoBackend::ReadRegister(const QString& name, soc_word_t& value)
+{
+ if(m_map.find(name) == m_map.end())
+ return false;
+ value = m_map[name];
+ return true;
+}
+
+bool FileIoBackend::Reload()
+{
+ QFile file(m_filename);
+ if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return false;
+ m_map.clear();
+
+ QTextStream in(&file);
+ while(!in.atEnd())
+ {
+ QString line = in.readLine();
+ int idx = line.indexOf('=');
+ if(idx == -1)
+ continue;
+ QString key = line.left(idx).trimmed();
+ bool ok;
+ soc_word_t val = line.mid(idx + 1).trimmed().toULong(&ok, 0);
+ if(key == "HW")
+ m_soc = line.mid(idx + 1).trimmed();
+ else if(ok)
+ m_map[key] = val;
+ }
+ return true;
+}
+
+DummyIoBackend::DummyIoBackend()
+{
+}
+
+QString DummyIoBackend::GetSocName()
+{
+ return "";
+}
+
+bool DummyIoBackend::ReadRegister(const QString& name, soc_word_t& value)
+{
+ (void) name;
+ (void) value;
+ return false;
+}
+
+bool DummyIoBackend::Reload()
+{
+ return true;
+}
+
+BackendHelper::BackendHelper(IoBackend *io_backend, const soc_t& soc)
+ :m_io_backend(io_backend), m_soc(soc)
+{
+}
+
+bool BackendHelper::ReadRegister(const QString& dev, const QString& reg, soc_word_t& v)
+{
+ return m_io_backend->ReadRegister("HW." + dev + "." + reg, v);
+}
+
+bool BackendHelper::ReadRegisterField(const QString& dev, const QString& reg,
+ const QString& field, soc_word_t& v)
+{
+ soc_dev_t *sdev = 0;
+ for(size_t i = 0; i < m_soc.dev.size(); i++)
+ {
+ for(size_t j = 0; j < m_soc.dev[i].addr.size(); j++)
+ if(m_soc.dev[i].addr[j].name.c_str() == dev)
+ sdev = &m_soc.dev[i];
+ }
+ if(sdev == 0)
+ return false;
+ soc_reg_t *sreg = 0;
+ for(size_t i = 0; i < sdev->reg.size(); i++)
+ {
+ for(size_t j = 0; j < sdev->reg[i].addr.size(); j++)
+ if(sdev->reg[i].addr[j].name.c_str() == reg)
+ sreg = &sdev->reg[i];
+ }
+ if(sreg == 0)
+ return false;
+ soc_reg_field_t *sfield = 0;
+ for(size_t i = 0; i < sreg->field.size(); i++)
+ if(sreg->field[i].name.c_str() == field)
+ sfield = &sreg->field[i];
+ if(sfield == 0)
+ return false;
+ if(!ReadRegister(dev, reg, v))
+ return false;
+ v = (v & sfield->bitmask()) >> sfield->first_bit;
+ return true;
+} \ No newline at end of file
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h
new file mode 100644
index 0000000000..536eb8cec5
--- /dev/null
+++ b/utils/regtools/qeditor/backend.h
@@ -0,0 +1,77 @@
+#ifndef __BACKEND_H__
+#define __BACKEND_H__
+
+#include <QObject>
+#include <QStringList>
+#include <QMap>
+#include "soc_desc.hpp"
+
+class IoBackend : public QObject
+{
+ Q_OBJECT
+public:
+ IoBackend();
+
+ virtual QString GetSocName() = 0;
+ virtual bool ReadRegister(const QString& name, soc_word_t& value) = 0;
+ virtual bool Reload() = 0;
+};
+
+class DummyIoBackend : public IoBackend
+{
+ Q_OBJECT
+public:
+ DummyIoBackend();
+
+ virtual QString GetSocName();
+ virtual bool ReadRegister(const QString& name, soc_word_t& value);
+ virtual bool Reload();
+};
+
+class FileIoBackend : public IoBackend
+{
+ Q_OBJECT
+public:
+ FileIoBackend(const QString& filename);
+
+ virtual QString GetSocName();
+ virtual bool ReadRegister(const QString& name, soc_word_t& value);
+ virtual bool Reload();
+
+protected:
+ QString m_filename;
+ QString m_soc;
+ QMap< QString, soc_word_t > m_map;
+};
+
+class Backend : public QObject
+{
+ Q_OBJECT
+public:
+ Backend();
+
+ QStringList GetSocNameList();
+ bool LoadSocDesc(const QString& filename);
+ bool GetSocByName(const QString& name, soc_t& s);
+ IoBackend *CreateDummyIoBackend();
+ IoBackend *CreateFileIoBackend(const QString& filename);
+
+signals:
+ void OnSocListChanged();
+private:
+ std::vector< soc_t > m_socs;
+};
+
+class BackendHelper
+{
+public:
+ BackendHelper(IoBackend *io_backend, const soc_t& soc);
+ bool ReadRegister(const QString& dev, const QString& reg, soc_word_t& v);
+ bool ReadRegisterField(const QString& dev, const QString& reg,
+ const QString& field, soc_word_t& v);
+private:
+ IoBackend *m_io_backend;
+ soc_t m_soc;
+};
+
+#endif /* __BACKEND_H__ */
diff --git a/utils/regtools/qeditor/main.cpp b/utils/regtools/qeditor/main.cpp
new file mode 100644
index 0000000000..cc3ea16066
--- /dev/null
+++ b/utils/regtools/qeditor/main.cpp
@@ -0,0 +1,30 @@
+#include <QApplication>
+#include <QDir>
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ Backend *backend = new Backend;
+ QDir dir(QCoreApplication::applicationDirPath());
+ dir.cdUp();
+ dir.cd("desc");
+ dir.setFilter(QDir::Files);
+ printf("%s\n", dir.absolutePath().toStdString().c_str());
+ QFileInfoList list = dir.entryInfoList();
+ for(int i = 0; i < list.size(); i++)
+ {
+ QFileInfo fileInfo = list.at(i);
+ if(fileInfo.fileName().right(4) != ".xml" || fileInfo.fileName().left(5) != "regs-")
+ continue;
+ backend->LoadSocDesc(fileInfo.absoluteFilePath());
+ }
+
+ QCoreApplication::setOrganizationName("Rockbox");
+ QCoreApplication::setApplicationName("Register Editor");
+ QCoreApplication::setOrganizationDomain("rockbox.com");
+ MainWindow win(backend);
+ win.show();
+ return app.exec();
+}
diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp
new file mode 100644
index 0000000000..1e39dd1a83
--- /dev/null
+++ b/utils/regtools/qeditor/mainwindow.cpp
@@ -0,0 +1,108 @@
+#include <QWidget>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QFileDialog>
+#include <QAction>
+#include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QTabBar>
+#include <QCloseEvent>
+#include <QDebug>
+
+#include "mainwindow.h"
+#include "regtab.h"
+
+MyTabWidget::MyTabWidget()
+{
+ setMovable(true);
+ setTabsClosable(true);
+ connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int)));
+}
+
+void MyTabWidget::OnCloseTab(int index)
+{
+ removeTab(index);
+}
+
+MainWindow::MainWindow(Backend *backend)
+ :m_backend(backend)
+{
+ QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("&Register Tab"), this);
+ QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this);
+ QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this);
+ QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this);
+
+ connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab()));
+ connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc()));
+ connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit()));
+ connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout()));
+
+ QMenu *file_menu = menuBar()->addMenu(tr("&File"));
+ QMenu *new_submenu = file_menu->addMenu(QIcon::fromTheme("document-new"), "&New");
+ QMenu *load_submenu = file_menu->addMenu(QIcon::fromTheme("document-open"), "&Load");
+ file_menu->addAction(quit_act);
+
+ new_submenu->addAction(new_regtab_act);
+
+ load_submenu->addAction(load_desc_act);
+
+ QMenu *about_menu = menuBar()->addMenu(tr("&About"));
+ about_menu->addAction(about_act);
+
+ m_tab = new MyTabWidget();
+
+ setCentralWidget(m_tab);
+
+ ReadSettings();
+}
+
+void MainWindow::ReadSettings()
+{
+ restoreGeometry(Settings::Get()->value("mainwindow/geometry").toByteArray());
+}
+
+void MainWindow::WriteSettings()
+{
+ Settings::Get()->setValue("mainwindow/geometry", saveGeometry());
+}
+
+void MainWindow::OnQuit()
+{
+ WriteSettings();
+}
+
+void MainWindow::OnAbout()
+{
+}
+
+void MainWindow::closeEvent(QCloseEvent *event)
+{
+ WriteSettings();
+ event->accept();
+}
+
+void MainWindow::OnLoadDesc()
+{
+ QFileDialog *fd = new QFileDialog(this);
+ fd->setFilter("XML files (*.xml);;All files (*)");
+ fd->setFileMode(QFileDialog::ExistingFiles);
+ fd->setDirectory(Settings::Get()->value("mainwindow/loaddescdir", QDir::currentPath()).toString());
+ if(fd->exec())
+ {
+ QStringList filenames = fd->selectedFiles();
+ for(int i = 0; i < filenames.size(); i++)
+ if(!m_backend->LoadSocDesc(filenames[i]))
+ {
+ QMessageBox msg;
+ msg.setText(QString("Cannot load ") + filenames[i]);
+ msg.exec();
+ }
+ Settings::Get()->setValue("mainwindow/loaddescdir", fd->directory().absolutePath());
+ }
+}
+
+void MainWindow::OnNewRegTab()
+{
+ new RegTab(m_backend, m_tab);
+}
diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h
new file mode 100644
index 0000000000..2897cde1ca
--- /dev/null
+++ b/utils/regtools/qeditor/mainwindow.h
@@ -0,0 +1,44 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QTabWidget>
+#include <QSettings>
+#include "backend.h"
+#include "settings.h"
+
+class MyTabWidget : public QTabWidget
+{
+ Q_OBJECT
+public:
+ MyTabWidget();
+
+private slots:
+ void OnCloseTab(int index);
+};
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow(Backend *backend);
+ void center();
+ void ReadSettings();
+ void WriteSettings();
+
+private:
+ void closeEvent(QCloseEvent *event);
+
+private slots:
+ void OnQuit();
+ void OnAbout();
+ void OnLoadDesc();
+ void OnNewRegTab();
+
+private:
+ QTabWidget *m_tab;
+ Backend *m_backend;
+};
+
+#endif
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro
new file mode 100644
index 0000000000..4e25a48d89
--- /dev/null
+++ b/utils/regtools/qeditor/qeditor.pro
@@ -0,0 +1,8 @@
+QT += widgets
+
+HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h
+SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp
+LIBS += -L../lib/ -lsocdesc -lxml2
+INCLUDEPATH += ../lib/
+
+CONFIG += debug \ No newline at end of file
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp
new file mode 100644
index 0000000000..d535f6cdff
--- /dev/null
+++ b/utils/regtools/qeditor/regtab.cpp
@@ -0,0 +1,392 @@
+#include "regtab.h"
+
+#include <QSplitter>
+#include <QVBoxLayout>
+#include <QGroupBox>
+#include <QAbstractListModel>
+#include <QMessageBox>
+#include <QSizePolicy>
+#include <QHBoxLayout>
+#include <QStringBuilder>
+#include <QLabel>
+#include <QGridLayout>
+#include <QTableWidget>
+#include <QHeaderView>
+#include <QFileDialog>
+#include "backend.h"
+#include "analyser.h"
+
+RegTreeItem::RegTreeItem(const QString& string, int type)
+ :QTreeWidgetItem(QStringList(string), type)
+{
+}
+
+void RegTreeItem::SetPath(int dev_idx, int dev_addr_idx, int reg_idx, int reg_addr_idx)
+{
+ m_dev_idx = dev_idx;
+ m_dev_addr_idx = dev_addr_idx;
+ m_reg_idx = reg_idx;
+ m_reg_addr_idx = reg_addr_idx;
+}
+
+RegTab::RegTab(Backend *backend, QTabWidget *parent)
+ :m_backend(backend)
+{
+ m_splitter = new QSplitter();
+ QWidget *left = new QWidget;
+ m_splitter->addWidget(left);
+ QVBoxLayout *left_layout = new QVBoxLayout;
+ left->setLayout(left_layout);
+
+ QGroupBox *top_group = new QGroupBox("SOC selection");
+ QVBoxLayout *top_group_layout = new QVBoxLayout;
+ m_soc_selector = new QComboBox;
+ top_group_layout->addWidget(m_soc_selector);
+ top_group->setLayout(top_group_layout);
+
+ m_reg_tree = new QTreeWidget();
+ m_reg_tree->setColumnCount(1);
+ m_reg_tree->setHeaderLabel(QString("Name"));
+
+ m_analysers_list = new QListWidget;
+
+ m_type_selector = new QTabWidget;
+ m_type_selector->addTab(m_reg_tree, "Registers");
+ m_type_selector->addTab(m_analysers_list, "Analyzers");
+ m_type_selector->setTabPosition(QTabWidget::West);
+
+ left_layout->addWidget(top_group);
+ left_layout->addWidget(m_type_selector);
+
+ m_right_panel = new QVBoxLayout;
+ QGroupBox *data_sel_group = new QGroupBox("Data selection");
+ QHBoxLayout *data_sel_layout = new QHBoxLayout;
+ m_data_selector = new QComboBox;
+ m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing));
+ m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile));
+ m_data_sel_edit = new QLineEdit;
+ m_data_sel_edit->setReadOnly(true);
+ m_data_soc_label = new QLabel;
+ QPushButton *data_sel_reload = new QPushButton;
+ data_sel_reload->setIcon(QIcon::fromTheme("view-refresh"));
+ data_sel_layout->addWidget(m_data_selector);
+ data_sel_layout->addWidget(m_data_sel_edit);
+ data_sel_layout->addWidget(m_data_soc_label);
+ data_sel_layout->addWidget(data_sel_reload);
+ data_sel_group->setLayout(data_sel_layout);
+ m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+
+ m_right_panel->addWidget(data_sel_group);
+ m_right_content = new QWidget;
+ QVBoxLayout *l = new QVBoxLayout;
+ l->addStretch();
+ m_right_content->setLayout(l);
+ m_right_panel->addWidget(m_right_content);
+ QWidget *w = new QWidget;
+ w->setLayout(m_right_panel);
+ m_splitter->addWidget(w);
+
+ m_io_backend = m_backend->CreateDummyIoBackend();
+
+ parent->addTab(m_splitter, "Register Tab");
+
+ connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)),
+ this, SLOT(OnSocChanged(const QString&)));
+ connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged()));
+ connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
+ this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
+ connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
+ SLOT(OnRegItemClicked(QTreeWidgetItem *, int)));
+ connect(m_data_selector, SIGNAL(activated(int)),
+ this, SLOT(OnDataSelChanged(int)));
+ connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this,
+ SLOT(OnDataSocActivated(const QString&)));
+ connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
+ this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *)));
+ connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this,
+ SLOT(OnAnalyserClicked(QListWidgetItem *)));
+
+ OnSocListChanged();
+ OnDataSelChanged(DataSelNothing);
+}
+
+void RegTab::SetDataSocName(const QString& socname)
+{
+ if(socname.size() != 0)
+ {
+ m_data_soc_label->setText("<a href=\"" + socname + "\">" + socname + "</a>");
+ m_data_soc_label->setTextFormat(Qt::RichText);
+ m_data_soc_label->show();
+ }
+ else
+ {
+ m_data_soc_label->setText("");
+ m_data_soc_label->hide();
+ }
+}
+
+void RegTab::OnDataSocActivated(const QString& str)
+{
+ int index = m_soc_selector->findText(str);
+ if(index != -1)
+ m_soc_selector->setCurrentIndex(index);
+}
+
+void RegTab::OnDataSelChanged(int index)
+{
+ if(index == -1)
+ return;
+ QVariant var = m_data_selector->itemData(index);
+ if(var == DataSelFile)
+ {
+ QFileDialog *fd = new QFileDialog(m_data_selector);
+ fd->setFilter("Textual files (*.txt);;All files (*)");
+ fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString());
+ if(fd->exec())
+ {
+ QStringList filenames = fd->selectedFiles();
+ delete m_io_backend;
+ m_io_backend = m_backend->CreateFileIoBackend(filenames[0]);
+ m_data_sel_edit->setText(filenames[0]);
+ SetDataSocName(m_io_backend->GetSocName());
+ OnDataSocActivated(m_io_backend->GetSocName());
+ }
+ Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath());
+ }
+ else
+ {
+ delete m_io_backend;
+ m_io_backend = m_backend->CreateDummyIoBackend();
+ SetDataSocName("");
+ }
+ OnDataChanged();
+}
+
+void RegTab::OnDataChanged()
+{
+ OnRegItemChanged(m_reg_tree->currentItem(), m_reg_tree->currentItem());
+}
+
+void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
+{
+ (void) previous;
+ OnRegItemClicked(current, 0);
+}
+
+void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col)
+{
+ (void) col;
+ if(current == 0)
+ return;
+ RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
+ if(item->type() != RegTreeRegType)
+ return;
+ soc_dev_t& dev = m_cur_soc.dev[item->GetDevIndex()];
+ soc_dev_addr_t& dev_addr = dev.addr[item->GetDevAddrIndex()];
+ soc_reg_t& reg = dev.reg[item->GetRegIndex()];
+ soc_reg_addr_t& reg_addr = reg.addr[item->GetRegAddrIndex()];
+
+ DisplayRegister(dev, dev_addr, reg, reg_addr);
+}
+
+void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous)
+{
+ (void) previous;
+ OnAnalyserClicked(current);
+}
+
+void RegTab::OnAnalyserClicked(QListWidgetItem *current)
+{
+ if(current == 0)
+ return;
+ delete m_right_content;
+ AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text());
+ m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget();
+ m_right_panel->addWidget(m_right_content);
+}
+
+void RegTab::DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr,
+ soc_reg_t& reg, soc_reg_addr_t& reg_addr)
+{
+ (void) dev;
+ delete m_right_content;
+
+ QVBoxLayout *right_layout = new QVBoxLayout;
+
+ QString reg_name;
+ reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str());
+ QStringList names;
+ QVector< soc_addr_t > addresses;
+ names.append(reg_name);
+ addresses.append(reg_addr.addr);
+ if(reg.flags & REG_HAS_SCT)
+ {
+ names.append(reg_name + "_SET");
+ names.append(reg_name + "_CLR");
+ names.append(reg_name + "_TOG");
+ addresses.append(reg_addr.addr + 4);
+ addresses.append(reg_addr.addr + 8);
+ addresses.append(reg_addr.addr + 12);
+ }
+
+ QString str;
+ str += "<table align=left>";
+ for(int i = 0; i < names.size(); i++)
+ str += "<tr><td><b>" + names[i] + "</b></td></tr>";
+ str += "</table>";
+ QLabel *label_names = new QLabel;
+ label_names->setTextFormat(Qt::RichText);
+ label_names->setText(str);
+
+ QString str_addr;
+ str_addr += "<table align=left>";
+ for(int i = 0; i < names.size(); i++)
+ str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>";
+ str_addr += "</table>";
+ QLabel *label_addr = new QLabel;
+ label_addr->setTextFormat(Qt::RichText);
+ label_addr->setText(str_addr);
+
+ QHBoxLayout *top_layout = new QHBoxLayout;
+ top_layout->addStretch();
+ top_layout->addWidget(label_names);
+ top_layout->addWidget(label_addr);
+ top_layout->addStretch();
+
+ soc_word_t value;
+ bool has_value = m_io_backend->ReadRegister(QString().sprintf("HW.%s.%s",
+ dev_addr.name.c_str(), reg_addr.name.c_str()), value);
+
+ QHBoxLayout *raw_val_layout = 0;
+ if(has_value)
+ {
+ QLabel *raw_val_name = new QLabel;
+ raw_val_name->setText("Raw value:");
+ QLineEdit *raw_val_edit = new QLineEdit;
+ raw_val_edit->setReadOnly(true);
+ raw_val_edit->setText(QString().sprintf("0x%08x", value));
+ raw_val_edit->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ raw_val_layout = new QHBoxLayout;
+ raw_val_layout->addStretch();
+ raw_val_layout->addWidget(raw_val_name);
+ raw_val_layout->addWidget(raw_val_edit);
+ raw_val_layout->addStretch();
+ }
+
+ QTableWidget *value_table = new QTableWidget;
+ value_table->setRowCount(reg.field.size());
+ value_table->setColumnCount(4);
+ for(size_t i = 0; i < reg.field.size(); i++)
+ {
+ QString bits_str;
+ if(reg.field[i].first_bit == reg.field[i].last_bit)
+ bits_str.sprintf("%d", reg.field[i].first_bit);
+ else
+ bits_str.sprintf("%d:%d", reg.field[i].last_bit, reg.field[i].first_bit);
+ QTableWidgetItem *item = new QTableWidgetItem(bits_str);
+ item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 0, item);
+ item = new QTableWidgetItem(QString(reg.field[i].name.c_str()));
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 1, item);
+ item = new QTableWidgetItem();
+ if(has_value)
+ {
+ const soc_reg_field_t& field = reg.field[i];
+ soc_word_t v = (value & field.bitmask()) >> field.first_bit;
+ QString value_name;
+ for(size_t j = 0; j < field.value.size(); j++)
+ if(v == field.value[j].value)
+ value_name = field.value[j].name.c_str();
+ const char *fmt = "%lu";
+ // heuristic
+ if((field.last_bit - field.first_bit + 1) > 16)
+ fmt = "0x%lx";
+ item->setText(QString().sprintf(fmt, (unsigned long)v));
+ item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+
+ if(value_name.size() != 0)
+ {
+ QTableWidgetItem *t = new QTableWidgetItem(value_name);
+ t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+ t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 3, t);
+ }
+ }
+ item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ value_table->setItem(i, 2, item);
+ }
+ value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits"));
+ value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
+ value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value"));
+ value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning"));
+ value_table->verticalHeader()->setVisible(false);
+ value_table->resizeColumnsToContents();
+ value_table->horizontalHeader()->setStretchLastSection(true);
+ value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ right_layout->addLayout(top_layout);
+ if(raw_val_layout)
+ right_layout->addLayout(raw_val_layout);
+ //right_layout->addWidget(bits_label);
+ right_layout->addWidget(value_table);
+ //right_layout->addStretch();
+
+ m_right_content = new QGroupBox("Register Description");
+ m_right_content->setLayout(right_layout);
+ m_right_panel->addWidget(m_right_content);
+}
+
+void RegTab::OnSocListChanged()
+{
+ m_soc_selector->clear();
+ QStringList socs = m_backend->GetSocNameList();
+ for(int i = 0; i < socs.size(); i++)
+ m_soc_selector->addItem(socs[i]);
+}
+
+void RegTab::FillDevSubTree(RegTreeItem *item)
+{
+ soc_dev_t& sd = m_cur_soc.dev[item->GetDevIndex()];
+ for(size_t i = 0; i < sd.reg.size(); i++)
+ {
+ soc_reg_t& reg = sd.reg[i];
+ for(size_t j = 0; j < reg.addr.size(); j++)
+ {
+ RegTreeItem *reg_item = new RegTreeItem(reg.addr[j].name.c_str(), RegTreeRegType);
+ reg_item->SetPath(item->GetDevIndex(), item->GetDevAddrIndex(), i, j);
+ item->addChild(reg_item);
+ }
+ }
+}
+
+void RegTab::FillRegTree()
+{
+ for(size_t i = 0; i < m_cur_soc.dev.size(); i++)
+ {
+ soc_dev_t& sd = m_cur_soc.dev[i];
+ for(size_t j = 0; j < sd.addr.size(); j++)
+ {
+ RegTreeItem *dev_item = new RegTreeItem(sd.addr[j].name.c_str(), RegTreeDevType);
+ dev_item->SetPath(i, j);
+ FillDevSubTree(dev_item);
+ m_reg_tree->addTopLevelItem(dev_item);
+ }
+ }
+}
+
+void RegTab::FillAnalyserList()
+{
+ m_analysers_list->clear();
+ m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.name.c_str()));
+}
+
+void RegTab::OnSocChanged(const QString& soc)
+{
+ m_reg_tree->clear();
+ if(!m_backend->GetSocByName(soc, m_cur_soc))
+ return;
+ FillRegTree();
+ FillAnalyserList();
+}
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h
new file mode 100644
index 0000000000..7ec8c9009f
--- /dev/null
+++ b/utils/regtools/qeditor/regtab.h
@@ -0,0 +1,85 @@
+#ifndef REGTAB_H
+#define REGTAB_H
+
+#include <QComboBox>
+#include <QEvent>
+#include <QTreeWidget>
+#include <QVBoxLayout>
+#include <QTabWidget>
+#include <QSplitter>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QLabel>
+#include <QListWidget>
+#include <soc_desc.hpp>
+#include "backend.h"
+#include "settings.h"
+
+enum
+{
+ RegTreeDevType = QTreeWidgetItem::UserType,
+ RegTreeRegType
+};
+
+enum
+{
+ DataSelNothing,
+ DataSelFile,
+};
+
+class RegTreeItem : public QTreeWidgetItem
+{
+public:
+ RegTreeItem(const QString& string, int type);
+
+ void SetPath(int dev_idx, int dev_addr_idx, int reg_idx = -1, int reg_addr_idx = -1);
+ int GetDevIndex() const { return m_dev_idx; }
+ int GetDevAddrIndex() const { return m_dev_addr_idx; }
+ int GetRegIndex() const { return m_reg_idx; }
+ int GetRegAddrIndex() const { return m_reg_addr_idx; }
+private:
+ int m_dev_idx, m_dev_addr_idx, m_reg_idx, m_reg_addr_idx;
+};
+
+class RegTab : public QObject
+{
+ Q_OBJECT
+public:
+ RegTab(Backend *backend, QTabWidget *parent);
+
+protected:
+ void FillDevSubTree(RegTreeItem *item);
+ void FillRegTree();
+ void FillAnalyserList();
+ void UpdateSocList();
+ void DisplayRegister(soc_dev_t& dev, soc_dev_addr_t& dev_addr,
+ soc_reg_t& reg, soc_reg_addr_t& reg_addr);
+ void SetDataSocName(const QString& socname);
+ QComboBox *m_soc_selector;
+ Backend *m_backend;
+ QTreeWidget *m_reg_tree;
+ soc_t m_cur_soc;
+ QVBoxLayout *m_right_panel;
+ QWidget *m_right_content;
+ QSplitter *m_splitter;
+ QLineEdit *m_data_sel_edit;
+ QLabel *m_data_soc_label;
+ QPushButton *m_data_sel_reload;
+ QComboBox *m_data_selector;
+ IoBackend *m_io_backend;
+ QTabWidget *m_type_selector;
+ QListWidget *m_analysers_list;
+
+private slots:
+ void OnSocChanged(const QString& text);
+ void OnSocListChanged();
+ void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
+ void OnRegItemClicked(QTreeWidgetItem *clicked, int col);
+ void OnDataSelChanged(int index);
+ void OnDataChanged();
+ void OnDataSocActivated(const QString&);
+ void OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous);
+ void OnAnalyserClicked(QListWidgetItem *clicked);
+};
+
+#endif /* REGTAB_H */ \ No newline at end of file
diff --git a/utils/regtools/qeditor/settings.cpp b/utils/regtools/qeditor/settings.cpp
new file mode 100644
index 0000000000..d72a15f74f
--- /dev/null
+++ b/utils/regtools/qeditor/settings.cpp
@@ -0,0 +1,32 @@
+#include <QCoreApplication>
+#include <QDebug>
+#include "settings.h"
+
+Settings::Settings()
+{
+
+}
+
+Settings::~Settings()
+{
+ if(m_settings)
+ delete m_settings;
+}
+
+QSettings *Settings::GetSettings()
+{
+ if(!m_settings)
+ {
+ QDir dir(QCoreApplication::applicationDirPath());
+ QString filename = dir.filePath(QCoreApplication::organizationDomain() + ".ini");
+ m_settings = new QSettings(filename, QSettings::IniFormat);
+ }
+ return m_settings;
+}
+
+QSettings *Settings::Get()
+{
+ return g_settings.GetSettings();
+}
+
+Settings Settings::g_settings; \ No newline at end of file
diff --git a/utils/regtools/qeditor/settings.h b/utils/regtools/qeditor/settings.h
new file mode 100644
index 0000000000..0776ec3b89
--- /dev/null
+++ b/utils/regtools/qeditor/settings.h
@@ -0,0 +1,21 @@
+#ifndef _SETTINGS_H_
+#define _SETTINGS_H_
+
+#include <QSettings>
+#include <QString>
+#include <QDir>
+
+class Settings
+{
+public:
+ Settings();
+ ~Settings();
+
+ QSettings *GetSettings();
+ static QSettings *Get();
+private:
+ QSettings *m_settings;
+ static Settings g_settings;
+};
+
+#endif /* _SETTINGS_H_ */ \ No newline at end of file
diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp
new file mode 100644
index 0000000000..49df671146
--- /dev/null
+++ b/utils/regtools/qeditor/std_analysers.cpp
@@ -0,0 +1,636 @@
+#include "std_analysers.h"
+
+/**
+ * Clock analyser
+ */
+
+ClockAnalyser::ClockAnalyser(const soc_t& soc, IoBackend *backend)
+ :Analyser(soc, backend)
+{
+ m_group = new QGroupBox("Clock Analyser");
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_group->setLayout(layout);
+ m_tree_widget = new QTreeWidget;
+ layout->addWidget(m_tree_widget);
+
+ m_tree_widget->setColumnCount(2);
+ QStringList list;
+ list << "Name" << "Frequency";
+ m_tree_widget->setHeaderLabels(list);
+
+ FillTree();
+}
+
+ClockAnalyser::~ClockAnalyser()
+{
+}
+
+QWidget *ClockAnalyser::GetWidget()
+{
+ return m_group;
+}
+
+bool ClockAnalyser::SupportSoc(const QString& soc_name)
+{
+ return soc_name == "imx233";
+}
+
+QString ClockAnalyser::GetFreq(unsigned freq)
+{
+ if(freq >= 1000000)
+ {
+ if((freq % 1000000) == 0)
+ return QString().sprintf("%d MHz", freq / 1000000);
+ else
+ return QString().sprintf("%.3f MHz", freq / 1000000.0);
+ }
+ if(freq >= 1000)
+ {
+ if((freq % 1000) == 0)
+ return QString().sprintf("%d KHz", freq / 1000);
+ else
+ return QString().sprintf("%.3f KHz", freq / 1000.0);
+ }
+ return QString().sprintf("%d Hz", freq);
+}
+
+QTreeWidgetItem *ClockAnalyser::AddClock(QTreeWidgetItem *parent, const QString& name, int freq, int mul, int div)
+{
+ if(freq == FROM_PARENT)
+ {
+ int64_t f = GetClockFreq(parent);
+ f *= mul;
+ f /= div;
+ freq = f;
+ }
+ QTreeWidgetItem *item = new QTreeWidgetItem(parent, QStringList() << name
+ << (freq == INVALID ? "<invalid>" : freq == 0 ? "<disabled>" : GetFreq(freq)));
+ item->setData(1, Qt::UserRole, freq);
+ if(freq == DISABLED || freq == INVALID || (parent && parent->isDisabled()))
+ item->setDisabled(true);
+ if(!parent)
+ m_tree_widget->addTopLevelItem(item);
+ return item;
+}
+
+int ClockAnalyser::GetClockFreq(QTreeWidgetItem *item)
+{
+ return item->data(1, Qt::UserRole).toInt();
+}
+
+void ClockAnalyser::FillTree()
+{
+ m_tree_widget->clear();
+ BackendHelper helper(m_io_backend, m_soc);
+ soc_word_t value, value2, value3;
+
+ QTreeWidgetItem *ring_osc = 0;
+ if(helper.ReadRegisterField("POWER", "MINPWR", "ENABLE_OSC", value))
+ ring_osc = AddClock(0, "ring_clk24m", value ? 24000000 : DISABLED);
+ else
+ ring_osc = AddClock(0, "ring_clk24m", INVALID);
+ QTreeWidgetItem *xtal_osc = 0;
+ if(helper.ReadRegisterField("POWER", "MINPWR", "PWD_XTAL24", value))
+ xtal_osc = AddClock(0, "xtal_clk24m", value ? DISABLED : 24000000);
+ else
+ xtal_osc = AddClock(0, "xtal_clk24m", INVALID);
+ QTreeWidgetItem *ref_xtal = 0;
+ if(helper.ReadRegisterField("POWER", "MINPWR", "SELECT_OSC", value))
+ ref_xtal = AddClock(value ? ring_osc : xtal_osc, "ref_xtal", FROM_PARENT);
+ else
+ ref_xtal = AddClock(0, "ref_xtal", INVALID);
+
+ QTreeWidgetItem *ref_pll = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "PLLCTRL0", "POWER", value))
+ ref_pll = AddClock(ref_xtal, "ref_pll", FROM_PARENT, 20);
+ else
+ ref_pll = AddClock(0, "ref_pll", INVALID);
+
+ QTreeWidgetItem *ref_io = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEIO", value) &&
+ helper.ReadRegisterField("CLKCTRL", "FRAC", "IOFRAC", value2))
+ ref_io = AddClock(ref_pll, "ref_io", value ? DISABLED : FROM_PARENT, 18, value2);
+ else
+ ref_io = AddClock(ref_pll, "ref_io", INVALID);
+
+ QTreeWidgetItem *ref_pix = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEPIX", value) &&
+ helper.ReadRegisterField("CLKCTRL", "FRAC", "PIXFRAC", value2))
+ ref_pix = AddClock(ref_pll, "ref_pix", value ? DISABLED : FROM_PARENT, 18, value2);
+ else
+ ref_pix = AddClock(ref_pll, "ref_pix", INVALID);
+
+ QTreeWidgetItem *ref_emi = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATEEMI", value) &&
+ helper.ReadRegisterField("CLKCTRL", "FRAC", "EMIFRAC", value2))
+ ref_emi = AddClock(ref_pll, "ref_emi", value ? DISABLED : FROM_PARENT, 18, value2);
+ else
+ ref_emi = AddClock(ref_pll, "ref_emi", INVALID);
+
+ QTreeWidgetItem *ref_cpu = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "FRAC", "CLKGATECPU", value) &&
+ helper.ReadRegisterField("CLKCTRL", "FRAC", "CPUFRAC", value2))
+ ref_cpu = AddClock(ref_pll, "ref_cpu", value ? DISABLED : FROM_PARENT, 18, value2);
+ else
+ ref_cpu = AddClock(ref_pll, "ref_cpu", INVALID);
+
+ QTreeWidgetItem *clk_p = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_CPU", value))
+ {
+ if(!value)
+ {
+ if(helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_CPU", value2))
+ clk_p = AddClock(ref_cpu, "clk_p", FROM_PARENT, 1, value2);
+ else
+ clk_p = AddClock(ref_cpu, "clk_p", INVALID);
+ }
+ else
+ {
+ if(helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_XTAL_FRAC_EN", value) &&
+ helper.ReadRegisterField("CLKCTRL", "CPU", "DIV_XTAL", value2))
+ clk_p = AddClock(ref_xtal, "clk_p", FROM_PARENT, value ? 1024 : 1, value2);
+ else
+ clk_p = AddClock(ref_xtal, "clk_p", INVALID);
+ }
+ }
+ else
+ clk_p = AddClock(ref_xtal, "clk_p", INVALID);
+
+ QTreeWidgetItem *clk_h = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "HBUS", "DIV_FRAC_EN", value) &&
+ helper.ReadRegisterField("CLKCTRL", "HBUS", "DIV", value2))
+ clk_h = AddClock(clk_p, "clk_h", FROM_PARENT, value ? 32 : 1, value2);
+ else
+ clk_h = AddClock(clk_p, "clk_h", INVALID);
+
+ QTreeWidgetItem *clk_x = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "XBUS", "DIV", value))
+ clk_x = AddClock(ref_xtal, "clk_x", FROM_PARENT, 1, value);
+ else
+ clk_x = AddClock(ref_xtal, "clk_x", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "UART_CLK_GATE", value))
+ AddClock(ref_xtal, "clk_uart", value ? DISABLED : FROM_PARENT);
+ else
+ AddClock(ref_xtal, "clk_uart", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "FILT_CLK24M_GATE", value))
+ AddClock(ref_xtal, "clk_filt24m", value ? DISABLED : FROM_PARENT);
+ else
+ AddClock(ref_xtal, "clk_filt24m", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "PWM_CLK24M_GATE", value))
+ AddClock(ref_xtal, "clk_pwm24m", value ? DISABLED : FROM_PARENT);
+ else
+ AddClock(ref_xtal, "clk_pwm24m", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "DRI_CLK24M_GATE", value))
+ AddClock(ref_xtal, "clk_dri24m", value ? DISABLED : FROM_PARENT);
+ else
+ AddClock(ref_xtal, "clk_dri24m", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "DIGCTRL_CLK1M_GATE", value))
+ AddClock(ref_xtal, "clk_1m", value ? DISABLED : FROM_PARENT, 1, 24);
+ else
+ AddClock(ref_xtal, "clk_1m", INVALID);
+
+ QTreeWidgetItem *clk_32k = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "XTAL", "TIMROT_CLK32K_GATE", value))
+ clk_32k = AddClock(ref_xtal, "clk_32k", value ? DISABLED : FROM_PARENT, 1, 750);
+ else
+ clk_32k = AddClock(ref_xtal, "clk_32k", INVALID);
+
+ AddClock(clk_32k, "clk_adc", FROM_PARENT, 1, 16);
+
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_PIX", value) &&
+ helper.ReadRegisterField("CLKCTRL", "PIX", "DIV", value2))
+ AddClock(value ? ref_xtal : ref_pix, "clk_pix", FROM_PARENT, 1, value2);
+ else
+ AddClock(ref_xtal, "clk_p", INVALID);
+
+ QTreeWidgetItem *clk_ssp = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_SSP", value) &&
+ helper.ReadRegisterField("CLKCTRL", "SSP", "DIV", value2) &&
+ helper.ReadRegisterField("CLKCTRL", "SSP", "CLKGATE", value3))
+ clk_ssp = AddClock(value ? ref_xtal : ref_io, "clk_ssp", value3 ? DISABLED : FROM_PARENT, 1, value2);
+ else
+ clk_ssp = AddClock(ref_xtal, "clk_p", INVALID);
+
+ if(helper.ReadRegisterField("SSP1", "TIMING", "CLOCK_DIVIDE", value) &&
+ helper.ReadRegisterField("SSP1", "TIMING", "CLOCK_RATE", value2) &&
+ helper.ReadRegisterField("SSP1", "CTRL0", "CLKGATE", value3))
+ AddClock(clk_ssp, "clk_ssp1", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2));
+ else
+ AddClock(clk_ssp, "clk_ssp1", INVALID);
+
+ if(helper.ReadRegisterField("SSP2", "TIMING", "CLOCK_DIVIDE", value) &&
+ helper.ReadRegisterField("SSP2", "TIMING", "CLOCK_RATE", value2) &&
+ helper.ReadRegisterField("SSP2", "CTRL0", "CLKGATE", value3))
+ AddClock(clk_ssp, "clk_ssp2", value3 ? DISABLED : FROM_PARENT, 1, value * (1 + value2));
+ else
+ AddClock(clk_ssp, "clk_ssp2", INVALID);
+
+ QTreeWidgetItem *clk_gpmi = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_GPMI", value) &&
+ helper.ReadRegisterField("CLKCTRL", "GPMI", "DIV", value2) &&
+ helper.ReadRegisterField("CLKCTRL", "GPMI", "CLKGATE", value3))
+ clk_gpmi = AddClock(value ? ref_xtal : ref_io, "clk_gpmi", value3 ? DISABLED : FROM_PARENT, 1, value2);
+ else
+ clk_gpmi = AddClock(ref_xtal, "clk_p", INVALID);
+
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value))
+ {
+ if(!value)
+ {
+ if(helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_EMI", value2) &&
+ helper.ReadRegisterField("CLKCTRL", "EMI", "CLKGATE", value3))
+ AddClock(ref_emi, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2);
+ else
+ AddClock(ref_emi, "clk_emi", INVALID);
+ }
+ else
+ {
+ if(helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_XTAL", value2) &&
+ helper.ReadRegisterField("CLKCTRL", "EMI", "CLKGATE", value3))
+ AddClock(ref_xtal, "clk_emi", value3 ? DISABLED : FROM_PARENT, 1, value2);
+ else
+ AddClock(ref_xtal, "clk_emi", INVALID);
+ }
+ }
+ else
+ clk_p = AddClock(ref_xtal, "clk_emi", INVALID);
+
+ QTreeWidgetItem *ref_vid = AddClock(ref_pll, "clk_vid", FROM_PARENT);
+
+ if(helper.ReadRegisterField("CLKCTRL", "TV", "CLK_TV108M_GATE", value) &&
+ helper.ReadRegisterField("CLKCTRL", "TV", "CLK_TV_GATE", value2))
+ {
+ QTreeWidgetItem *clk_tv108m = AddClock(ref_vid, "clk_tv108m", value ? DISABLED : FROM_PARENT, 1, 4);
+ AddClock(clk_tv108m, "clk_tv54m", value2 ? DISABLED : FROM_PARENT, 1, 2);
+ AddClock(clk_tv108m, "clk_tv27m", value2 ? DISABLED : FROM_PARENT, 1, 4);
+ }
+
+ if(helper.ReadRegisterField("CLKCTRL", "PLLCTRL0", "EN_USB_CLKS", value))
+ AddClock(ref_pll, "utmi_clk480m", value ? FROM_PARENT : DISABLED);
+ else
+ AddClock(ref_pll, "utmi_clk480m", INVALID);
+
+ QTreeWidgetItem *xtal_clk32k = 0;
+ if(helper.ReadRegisterField("RTC", "PERSISTENT0", "XTAL32_FREQ", value) &&
+ helper.ReadRegisterField("RTC", "PERSISTENT0", "XTAL32KHZ_PWRUP", value2))
+ xtal_clk32k = AddClock(0, "xtal_clk32k", value2 == 0 ? DISABLED : value ? 32000 : 32768);
+ else
+ xtal_clk32k = AddClock(0, "xtal_clk32k", INVALID);
+
+ if(helper.ReadRegisterField("RTC", "PERSISTENT0", "CLOCKSOURCE", value))
+ AddClock(value ? xtal_clk32k : ref_xtal, "clk_rtc32k", FROM_PARENT, 1, value ? 1 : 768);
+ else
+ AddClock(ref_xtal, "clk_rtc32k", INVALID);
+
+ (void) clk_x;
+ (void) clk_gpmi;
+ (void) clk_h;
+
+ m_tree_widget->expandAll();
+ m_tree_widget->resizeColumnToContents(0);
+}
+
+static TmplAnalyserFactory< ClockAnalyser > g_clock_factory(true, "Clock Analyser");
+
+/**
+ * EMI analyser
+ */
+EmiAnalyser::EmiAnalyser(const soc_t& soc, IoBackend *backend)
+ :Analyser(soc, backend)
+{
+ m_group = new QGroupBox("EMI Analyser");
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_group->setLayout(layout);
+ m_panel = new QToolBox;
+ m_display_selector = new QComboBox;
+ m_display_selector->addItem("Cycles", DisplayCycles);
+ m_display_selector->addItem("Raw Hexadecimal", DisplayRawHex);
+ m_display_selector->addItem("Time", DisplayTime);
+ QHBoxLayout *line_layout = new QHBoxLayout;
+ line_layout->addWidget(new QLabel("Display Mode:"));
+ line_layout->addWidget(m_display_selector);
+ m_emi_freq_label = new QLineEdit;
+ m_emi_freq_label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ m_emi_freq_label->setReadOnly(true);
+ line_layout->addStretch();
+ line_layout->addWidget(new QLabel("Frequency:"));
+ line_layout->addWidget(m_emi_freq_label);
+ line_layout->addWidget(new QLabel("MHz"));
+ line_layout->addStretch();
+ layout->addLayout(line_layout);
+ layout->addWidget(m_panel);
+
+ connect(m_display_selector, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(OnChangeDisplayMode(int)));
+
+ FillTable();
+}
+
+EmiAnalyser::~EmiAnalyser()
+{
+}
+
+QWidget *EmiAnalyser::GetWidget()
+{
+ return m_group;
+}
+
+bool EmiAnalyser::SupportSoc(const QString& soc_name)
+{
+ return soc_name == "imx233";
+}
+
+void EmiAnalyser::OnChangeDisplayMode(int index)
+{
+ m_display_mode = (DisplayMode)m_display_selector->itemData(index).toInt();
+ int idx = m_panel->currentIndex();
+ FillTable();
+ m_panel->setCurrentIndex(idx);
+}
+
+void EmiAnalyser::NewGroup(const QString& name)
+{
+ QTableWidget *table = new QTableWidget;
+ table->setColumnCount(3);
+ table->setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
+ table->setHorizontalHeaderItem(1, new QTableWidgetItem("Value"));
+ table->setHorizontalHeaderItem(2, new QTableWidgetItem("Comment"));
+ table->verticalHeader()->setVisible(false);
+ table->horizontalHeader()->setStretchLastSection(true);
+ m_panel->addItem(table, name);
+}
+
+void EmiAnalyser::AddLine(const QString& name, int value, const QString& unit, const QString& comment)
+{
+ QTableWidget *table = dynamic_cast< QTableWidget* >(m_panel->widget(m_panel->count() - 1));
+ int row = table->rowCount();
+ table->setRowCount(row + 1);
+ table->setItem(row, 0, new QTableWidgetItem(name));
+ QString val;
+ if(value == INVALID)
+ val = "<invalid>";
+ else if(value == NONE)
+ val = unit;
+ else if(m_display_mode == DisplayRawHex && unit.size() == 0)
+ val = QString("0x%1").arg(value, 0, 16);
+ else
+ val = QString("%1%2").arg(value).arg(unit);
+ table->setItem(row, 1, new QTableWidgetItem(val));
+ table->item(row, 1)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+ table->setItem(row, 2, new QTableWidgetItem(comment));
+ table->resizeColumnToContents(0);
+ table->resizeColumnToContents(1);
+}
+
+void EmiAnalyser::AddCycleLine(const QString& name, unsigned raw_val, float val,
+ int digits, const QString& comment)
+{
+ if(m_display_mode == DisplayCycles)
+ {
+ QString str;
+ if(digits == 0)
+ str = QString("%1").arg((int)val);
+ else
+ str = QString("%1").arg(val, 0, 'f', digits);
+ str += " cycles";
+ AddLine(name, NONE, str, comment);
+ }
+ else if(m_display_mode == DisplayRawHex)
+ {
+ QString str = QString("0x%1").arg(raw_val, 0, 16);
+ AddLine(name, NONE, str, comment);
+ }
+ else if(m_display_mode == DisplayTime && m_emi_freq != 0)
+ {
+ float cycle_time_ns = 1000000000.0 / m_emi_freq;
+ val *= cycle_time_ns;
+ QString str;
+ if(val >= 1000)
+ str = QString::fromWCharArray(L"%1 ┬Ás").arg(val / 1000.0, 0, 'f', 2);
+ else
+ str = QString("%1 ns").arg(val, 0, 'f', 2);
+ AddLine(name, NONE, str, comment);
+ }
+ else
+ AddLine(name, raw_val, " cycles", comment);
+}
+
+void EmiAnalyser::FillTable()
+{
+ while(m_panel->count() > 0)
+ m_panel->removeItem(0);
+ BackendHelper helper(m_io_backend, m_soc);
+ soc_word_t value;
+
+ m_emi_freq = 0;
+ if(helper.ReadRegisterField("CLKCTRL", "CLKSEQ", "BYPASS_EMI", value))
+ {
+ bool ret;
+ if(value)
+ {
+ m_emi_freq = 24000000;
+ ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_XTAL", value);
+ }
+ else
+ {
+ m_emi_freq = 480000000;
+ if(helper.ReadRegisterField("CLKCTRL", "FRAC", "EMIFRAC", value))
+ m_emi_freq = 18 * (int64_t)m_emi_freq / value;
+ else
+ m_emi_freq = 0;
+ ret = helper.ReadRegisterField("CLKCTRL", "EMI", "DIV_EMI", value);
+ }
+ if(ret)
+ m_emi_freq /= value;
+ else
+ m_emi_freq = 0;
+ }
+
+ m_emi_freq_label->setText(QString().sprintf("%.3f", m_emi_freq / 1000000.0));
+
+ NewGroup("Control Parameters");
+ if(helper.ReadRegisterField("EMI", "CTRL", "PORT_PRIORITY_ORDER", value))
+ {
+ QStringList ports;
+ ports << "AXI0" << "AHB1" << "AHB2" << "AHB3";
+ QString order;
+ order += ports[value / 6];
+ ports.erase(ports.begin() + value / 6);
+ int ord[6][3] = { {0, 1, 2}, {2, 0, 1}, {1, 2, 0}, {2, 1, 0}, {1, 0, 2}, {0, 2, 1} };
+ for(int i = 0; i < 3; i++)
+ order += ", " + ports[ord[value][i]];
+ AddLine("Port Priority Order", value, "", order);
+ }
+
+ if(helper.ReadRegisterField("EMI", "CTRL", "MEM_WIDTH", value))
+ AddLine("Memory Width", value ? 16 : 8, "-bit");
+
+ if(helper.ReadRegisterField("DRAM", "CTL03", "AP", value))
+ AddLine("Auto Pre-Charge", NONE, value ? "Yes" : "No");
+
+ bool bypass_mode = false;
+ if(helper.ReadRegisterField("DRAM", "CTL04", "DLL_BYPASS_MODE", value))
+ {
+ bypass_mode = value == 1;
+ AddLine("DLL Bypass Mode", NONE, value ? "Yes" : "No");
+ }
+
+ if(helper.ReadRegisterField("DRAM", "CTL05", "EN_LOWPOWER_MODE", value))
+ AddLine("Low Power Mode", NONE, value ? "Enabled" : "Disabled");
+
+ if(helper.ReadRegisterField("DRAM", "CTL08", "SREFRESH", value))
+ AddLine("Self Refresh", NONE, value ? "Yes" : "No");
+
+ if(helper.ReadRegisterField("DRAM", "CTL08", "SDR_MODE", value))
+ AddLine("Mode", NONE, value ? "SDR" : "DDR");
+
+ if(helper.ReadRegisterField("DRAM", "CTL10", "ADDR_PINS", value))
+ AddLine("Address Pins", 13 - value, "");
+
+ if(helper.ReadRegisterField("DRAM", "CTL11", "ADDR_PINS", value))
+ AddLine("Column Size", 12 - value, "-bit");
+
+ if(helper.ReadRegisterField("DRAM", "CTL11", "ADDR_PINS", value))
+ AddLine("Encoded CAS", value, "Memory device dependent");
+
+ if(helper.ReadRegisterField("DRAM", "CTL14", "CS_MAP", value))
+ {
+ QString v;
+ for(int i = 0; i < 4; i++)
+ if(value & (1 << i))
+ {
+ if(v.size() != 0)
+ v += " ";
+ v += QString("%1").arg(i);
+ }
+ AddLine("Chip Select Pins", NONE, v, "");
+ }
+
+ if(helper.ReadRegisterField("DRAM", "CTL37", "TREF_ENABLE", value))
+ AddLine("Refresh Commands", NONE, value ? "Enabled" : "Disabled", "Issue self-refresh every TREF cycles");
+
+ NewGroup("Frequency Parameters");
+
+ if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN_GATE", value))
+ {
+ if(value >= 3 && value <= 10 && value != 9)
+ {
+ float v = (value / 2) + 0.5 * (value % 2);
+ AddCycleLine("CAS Gate", value, v, 1, "");
+ }
+ else
+ AddLine("CAS Gate", NONE, "Reserved", "Reserved value");
+ }
+ if(helper.ReadRegisterField("DRAM", "CTL13", "CASLAT_LIN", value))
+ {
+ if(value >= 3 && value <= 10 && value != 9)
+ {
+ float v = (value / 2) + 0.5 * (value % 2);
+ AddCycleLine("CAS Latency", value, v, 1, "");
+ }
+ else
+ AddLine("CAS Latency", NONE, "Reserved", "Reserved value");
+ }
+
+ if(helper.ReadRegisterField("DRAM", "CTL12", "TCKE", value))
+ AddCycleLine("tCKE", value, value, 0, "Minimum CKE pulse width");
+
+ if(helper.ReadRegisterField("DRAM", "CTL15", "TDAL", value))
+ AddCycleLine("tDAL", value, value, 0, "Auto pre-charge write recovery time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL31", "TDLL", value))
+ AddCycleLine("tDLL", value, value, 0, "DLL lock time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL10", "TEMRS", value))
+ AddCycleLine("tEMRS", value, value, 0, "Extended mode parameter set time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL34", "TINIT", value))
+ AddCycleLine("tINIT", value, value, 0, "Initialisation time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL16", "TMRD", value))
+ AddCycleLine("tMRD", value, value, 0, "Mode register set command time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL40", "TPDEX", value))
+ AddCycleLine("tPDEX", value, value, 0, "Power down exit time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL32", "TRAS_MAX", value))
+ AddCycleLine("tRAS Max", value, value, 0, "Maximum row activate time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL20", "TRAS_MIN", value))
+ AddCycleLine("tRAS Min", value, value, 0, "Minimum row activate time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL17", "TRC", value))
+ AddCycleLine("tRC", value, value, 0, "Activate to activate delay (same bank)");
+
+ if(helper.ReadRegisterField("DRAM", "CTL20", "TRCD_INT", value))
+ AddCycleLine("tRCD", value, value, 0, "RAS to CAS");
+
+ if(helper.ReadRegisterField("DRAM", "CTL26", "TREF", value))
+ AddCycleLine("tREF", value, value, 0, "Refresh to refresh time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL21", "TRFC", value))
+ AddCycleLine("tRFC", value, value, 0, "Refresh command time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL15", "TRP", value))
+ AddCycleLine("tRP", value, value, 0, "Pre-charge command time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL12", "TRRD", value))
+ AddCycleLine("tRRD", value, value, 0, "Activate to activate delay (different banks)");
+
+ if(helper.ReadRegisterField("DRAM", "CTL12", "TWR_INT", value))
+ AddCycleLine("tWR", value, value, 0, "Write recovery time");
+
+ if(helper.ReadRegisterField("DRAM", "CTL13", "TWTR", value))
+ AddCycleLine("tWTR", value, value, 0, "Write to read delay");
+
+ if(helper.ReadRegisterField("DRAM", "CTL32", "TXSNR", value))
+ AddCycleLine("tXSNR", value, value, 0, "");
+
+ if(helper.ReadRegisterField("DRAM", "CTL33", "TXSR", value))
+ AddCycleLine("tXSR", value, value, 0, "Self-refresh exit time");
+
+ NewGroup("DLL Parameters");
+
+ if(bypass_mode)
+ {
+ if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_0_BYPASS", value))
+ AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle (bypass mode)");
+
+ if(helper.ReadRegisterField("DRAM", "CTL19", "DLL_DQS_DELAY_1_BYPASS", value))
+ AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle (bypass mode)");
+
+ if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT_BYPASS", value))
+ AddLine("DQS Out Delay", value, "", "(bypass mode)");
+
+ if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT_BYPASS", value))
+ AddLine("DQS Write Delay", value, "", "(bypass mode)");
+ }
+ else
+ {
+ if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_START_POINT", value))
+ AddLine("DLL Start Point", value, "", "Initial delay count");
+
+ if(helper.ReadRegisterField("DRAM", "CTL17", "DLL_INCREMENT", value))
+ AddLine("DLL Increment", value, "", "Delay increment");
+
+ if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_0", value))
+ AddLine("DLL DQS Delay 0", value, "", "In 1/128 fraction of a cycle");
+
+ if(helper.ReadRegisterField("DRAM", "CTL18", "DLL_DQS_DELAY_1", value))
+ AddLine("DLL DQS Delay 1", value, "", "In 1/128 fraction of a cycle");
+
+ if(helper.ReadRegisterField("DRAM", "CTL19", "DQS_OUT_SHIFT", value))
+ AddLine("DQS Out Delay", value, "", "");
+
+ if(helper.ReadRegisterField("DRAM", "CTL20", "WR_DQS_SHIFT", value))
+ AddLine("DQS Write Delay", value, "", "");
+ }
+
+}
+
+static TmplAnalyserFactory< EmiAnalyser > g_emi_factory(true, "EMI Analyser"); \ No newline at end of file
diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h
new file mode 100644
index 0000000000..98c5fa0f98
--- /dev/null
+++ b/utils/regtools/qeditor/std_analysers.h
@@ -0,0 +1,95 @@
+#ifndef _STDANALYSER_H_
+#define _STDANALYSER_H_
+
+#include "analyser.h"
+
+#include <QGroupBox>
+#include <QTreeWidget>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QTableWidget>
+#include <QHeaderView>
+#include <QToolBox>
+#include <QComboBox>
+#include <QLabel>
+#include <QLineEdit>
+#include "analyser.h"
+#include "collapsiblepanel.h"
+
+/**
+ * Clock analyser
+ */
+
+class ClockAnalyser : public Analyser
+{
+ Q_OBJECT
+public:
+ ClockAnalyser(const soc_t& soc, IoBackend *backend);
+ virtual ~ClockAnalyser();
+ virtual QWidget *GetWidget();
+ static bool SupportSoc(const QString& soc_name);
+
+private:
+ QString GetFreq(unsigned freq);
+
+ enum
+ {
+ DISABLED = 0,
+ INVALID = -1,
+ FROM_PARENT = -2,
+ };
+
+ QTreeWidgetItem *AddClock(QTreeWidgetItem *parent, const QString& name, int freq, int mul = 1, int div = 1);
+ int GetClockFreq(QTreeWidgetItem *item);
+ void FillTree();
+
+private:
+ QGroupBox *m_group;
+ QTreeWidget *m_tree_widget;
+};
+
+/**
+ * EMI analyser
+ */
+class EmiAnalyser : public Analyser
+{
+ Q_OBJECT
+public:
+ EmiAnalyser(const soc_t& soc, IoBackend *backend);
+ virtual ~EmiAnalyser();
+ virtual QWidget *GetWidget();
+
+ static bool SupportSoc(const QString& soc_name);
+
+private slots:
+ void OnChangeDisplayMode(int index);
+
+private:
+ enum DisplayMode
+ {
+ DisplayCycles,
+ DisplayRawHex,
+ DisplayTime,
+ };
+
+ enum
+ {
+ NONE = -999999,
+ INVALID = -1000000
+ };
+
+ void NewGroup(const QString& name);
+ void AddLine(const QString& name, int value, const QString& unit, const QString& comment = "");
+ void AddCycleLine(const QString& name, unsigned raw_val, float val, int digits, const QString& comment = "");
+ void FillTable();
+
+private:
+ QGroupBox *m_group;
+ QComboBox *m_display_selector;
+ QToolBox *m_panel;
+ DisplayMode m_display_mode;
+ unsigned m_emi_freq;
+ QLineEdit *m_emi_freq_label;
+};
+
+#endif /* _STDANALYSER_H_ */