From 3af398d7f9d62f5c78a350afe5d1f8e69f1eea41 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Thu, 15 Sep 2011 00:38:18 +0300 Subject: [PATCH 01/72] initial changes --- ground/ground.pro.user.2.1pre1 | 311 ++++++++++++++++++ .../internals/projections/lks94projection.h | 2 +- .../src/plugins/notify/NotificationItem.h | 154 +++++++++ .../src/plugins/notify/notify.pro | 4 +- .../src/plugins/notify/notifyitemdelegate.cpp | 225 +++++++------ .../src/plugins/notify/notifyitemdelegate.h | 28 +- .../src/plugins/notify/notifyplugin.cpp | 137 ++++---- .../src/plugins/notify/notifyplugin.h | 34 +- .../notify/notifypluginconfiguration.cpp | 118 ++++--- .../notify/notifypluginconfiguration.h | 122 ------- .../notify/notifypluginoptionspage.cpp | 210 +++++------- .../plugins/notify/notifypluginoptionspage.h | 21 +- .../plugins/notify/notifypluginoptionspage.ui | 18 +- .../src/plugins/notify/notifytablemodel.cpp | 47 +-- .../src/plugins/notify/notifytablemodel.h | 24 +- openpilotgcs.bat | 3 + 16 files changed, 865 insertions(+), 593 deletions(-) create mode 100644 ground/ground.pro.user.2.1pre1 create mode 100644 ground/openpilotgcs/src/plugins/notify/NotificationItem.h delete mode 100644 ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.h create mode 100644 openpilotgcs.bat diff --git a/ground/ground.pro.user.2.1pre1 b/ground/ground.pro.user.2.1pre1 new file mode 100644 index 000000000..0a2acf277 --- /dev/null +++ b/ground/ground.pro.user.2.1pre1 @@ -0,0 +1,311 @@ + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + System + + + + ProjectExplorer.Project.Target.0 + + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt in PATH Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/!Work/OpenSource/OpenPilot/op/OpenPilot/ground-build + 2 + 2 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Qt in PATH Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/!Work/OpenSource/OpenPilot/op/OpenPilot/ground-build + 2 + 2 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + 4.6.2 Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/!Work/OpenSource/OpenPilot/op/OpenPilot/ground-build + 13 + 2 + true + + + + qmake + QtProjectManager.QMakeBuildStep + + + + Make + Qt4ProjectManager.MakeStep + false + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + 4.6.2 Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/!Work/OpenSource/OpenPilot/op/OpenPilot/ground-build + 13 + 2 + true + + 4 + + bin + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/bin/bin.pro + false + false + + false + false + + + + translations + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/share/openpilotgcs/translations/translations.pro + false + false + + false + false + + + + uavobjgenerator + Qt4ProjectManager.Qt4RunConfiguration + 2 + + uavobjgenerator/uavobjgenerator.pro + false + false + + false + false + + + + app + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/app/app.pro + false + false + + false + false + + + + berkeley + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/berkeley/berkeley.pro + false + false + + false + false + + + + designer + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/designer/designer.pro + false + false + + false + false + + + + gui + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/gui/gui.pro + false + false + + false + false + + + + network + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/network/network.pro + false + false + + false + false + + + + sql + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/sql/sql.pro + false + false + + false + false + + + + web + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/web/web.pro + false + false + + false + false + + + + zeroconf + Qt4ProjectManager.Qt4RunConfiguration + 2 + + openpilotgcs/src/libs/libqxt/src/zeroconf/zeroconf.pro + false + false + + false + false + + + 11 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 4 + + diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h index 4eee20aaa..dc895f04c 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h @@ -28,7 +28,7 @@ #define LKS94PROJECTION_H #include #include "cmath" -#include "../pureprojection.h" +#include "D:\!Work\OpenSource\OpenPilot\OpenPilot\ground\openpilotgcs\src\libs\opmapcontrol\src\internals\pureprojection.h" namespace projections { diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h new file mode 100644 index 000000000..c09e64982 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -0,0 +1,154 @@ +/** + ****************************************************************************** + * + * @file NotificationItem.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Notify Plugin configuration header + * @see The GNU Public License (GPL) Version 3 + * @defgroup notifyplugin + * @{ + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef NOTIFICATION_ITEM_H +#define NOTIFICATION_ITEM_H + +#include +#include "qsettings.h" +#include +#include + +using namespace Core; + +#define DECLARE_SOUND(number) \ + QString getSound##number() const { return _sound##number; } \ + void setSound##number(QString text) { _sound##number = text; } \ + +// QString getSound2() const { return _sound2; } +// void setSound2(QString text) { _sound2 = text; } + +// QString getSound3() const { return _sound3; } +// void setSound3(QString text) { _sound3 = text; } + +class NotificationItem : public QObject +{ + Q_OBJECT +public: + explicit NotificationItem(QObject *parent = 0); + + void copyTo(NotificationItem*) const; + + DECLARE_SOUND(1) + DECLARE_SOUND(2) + DECLARE_SOUND(3) + + QString getValue() const { return _dataValue; } + void setValue(QString text) { _dataValue = text; } + + QString getSayOrder() const { return _sayOrder; } + void setSayOrder(QString text) { _sayOrder = text; } + + double getSpinBoxValue() const { return _spinBoxValue; } + void setSpinBoxValue(double value) { _spinBoxValue = value; } + + + QString getDataObject() const { return _dataObject; } + void setDataObject(QString text) { _dataObject = text; } + + QString getObjectField() const { return _objectField; } + void setObjectField(QString text) { _objectField = text; } + + QString getSoundCollectionPath() const { return _soundCollectionPath; } + void setSoundCollectionPath(QString path) { _soundCollectionPath = path; } + + QString getCurrentLanguage() const { return _currentLanguage; } + void setCurrentLanguage(QString text) { _currentLanguage = text; } + + QStringList getMessageSequence() const { return _messageSequence; } + void setMessageSequence(QStringList sequence) { _messageSequence = sequence; } + + QString getRepeatFlag() const { return _repeatString; } + void setRepeatFlag(QString value) { _repeatString = value; } + + bool getRepeatTimeout() const { return _repeatTimeout; } + void setRepeatTimeout(bool value) { _repeatTimeout = value; } + + int getExpireTimeout() const { return _expireTimeout; } + void setExpireTimeout(int value) { _expireTimeout = value; } + + bool getEnableFlag() const { return _enableFlag; } + void setEnableFlag(bool value) { _enableFlag = value; } + + void saveState(QSettings* settings) const; + void restoreState(QSettings* settings); + QString parseNotifyMessage(); + + QTimer* timer; + QTimer* expireTimer; + bool isNowPlaying; // + bool firstStart; + +private: + + QStringList _messageSequence; + + //! path to folder with sound files + QString _soundCollectionPath; + + //! language in what notifications will be spelled + QString _currentLanguage; + + //! one UAV object per one notification + QString _dataObject; + + //! one field value change can be assigned to one notification + QString _objectField; + + //! poled UAV field value + QString _dataValue; + + //! possible sounds(at least one required to play notification) + QString _sound1; + QString _sound2; + QString _sound3; + + //! order in what sounds 1-3 will be played + QString _sayOrder; + + double _spinBoxValue; + + QString _repeatString; + + //! time when next notification must be fired + bool _repeatTimeout; + + //! how often or what periodicaly notification should be played + int _repeatTimerValue; + + //! time after event occured till notification became invalid + //! and will be removed from list + int _expireTimeout; + + //! enables/disables playing of current notification + bool _enableFlag; +}; + +Q_DECLARE_METATYPE(NotificationItem*) + +#endif // NotificationItem_H diff --git a/ground/openpilotgcs/src/plugins/notify/notify.pro b/ground/openpilotgcs/src/plugins/notify/notify.pro index 9ebebfa22..e70392a6a 100644 --- a/ground/openpilotgcs/src/plugins/notify/notify.pro +++ b/ground/openpilotgcs/src/plugins/notify/notify.pro @@ -10,9 +10,9 @@ QT += phonon HEADERS += notifyplugin.h \ notifypluginoptionspage.h \ - notifypluginconfiguration.h \ notifyitemdelegate.h \ - notifytablemodel.h + notifytablemodel.h \ + NotificationItem.h SOURCES += notifyplugin.cpp \ notifypluginoptionspage.cpp \ diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp index 7a2fc2ef4..d6e5161fc 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp @@ -25,136 +25,135 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "notifyitemdelegate.h" #include +#include "notifyitemdelegate.h" +#include "notifytablemodel.h" - NotifyItemDelegate::NotifyItemDelegate(QStringList items,QObject *parent) - : QItemDelegate(parent), - m_parent(parent), - m_items(items) { +NotifyItemDelegate::NotifyItemDelegate(QStringList items, QObject* parent) + : QItemDelegate(parent) + , _parent(parent) + , _items(items) +{ - } +} - QWidget *NotifyItemDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &, - const QModelIndex &index) const - { - if (index.column() == 1) { - QComboBox* editor = new QComboBox(parent); - editor->clear(); - editor->addItems(m_items); - //repeatEditor->setCurrentIndex(0); - //repeatEditor->setItemDelegate(new RepeatCounterDelegate()); - - //connect(repeatEditor,SIGNAL(activated (const QString& )),this,SLOT(selectRow(const QString& ))); - //QTableWidgetItem* item = qobject_cast(parent); - //((QTableWidgetItem*)parent)->setSelected(true); -// connect(editor, SIGNAL(editingFinished()), -// this, SLOT(commitAndCloseEditor())); - return editor; - } else - { - if(index.column() == 2) - { - QSpinBox* editor = new QSpinBox(parent); - connect(editor, SIGNAL(editingFinished()), - this, SLOT(commitAndCloseEditor())); - return editor; - } - - } - QLineEdit *editor = new QLineEdit(parent); -// connect(editor, SIGNAL(editingFinished()), -// this, SLOT(commitAndCloseEditor())); - return editor; - } - - void NotifyItemDelegate::commitAndCloseEditor() - { - QLineEdit *editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - - } else { - QComboBox* editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - } else { - QSpinBox* editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - } - } - } - } - - void NotifyItemDelegate::setEditorData(QWidget *editor, - const QModelIndex &index) const - { - QLineEdit *edit = qobject_cast(editor); - if (edit) { - edit->setText(index.model()->data(index, Qt::EditRole).toString()); - } else { - QComboBox * repeatEditor = qobject_cast(editor); - if (repeatEditor) - repeatEditor->setCurrentIndex(repeatEditor->findText(index.model()->data(index, Qt::EditRole).toString())); - else { - QSpinBox * expireEditor = qobject_cast(editor); - if (expireEditor) - expireEditor->setValue(index.model()->data(index, Qt::EditRole).toInt()); - } - } - } - - void NotifyItemDelegate::setModelData(QWidget *editor, - QAbstractItemModel *model, const QModelIndex &index) const - { - QLineEdit *edit = qobject_cast(editor); - if (edit) { - model->setData(index, edit->text()); - } else { - QComboBox * repeatEditor = qobject_cast(editor); - if (repeatEditor) { - model->setData(index, repeatEditor->currentText()); - - } else { - QSpinBox * expireEditor = qobject_cast(editor); - if (expireEditor) { - //expireEditor->interpretText(); - model->setData(index, expireEditor->value(), Qt::EditRole); +QWidget *NotifyItemDelegate::createEditor(QWidget* parent, + const QStyleOptionViewItem& /*none*/, + const QModelIndex& index) const +{ + if(eREPEAT_VALUE == index.column()) { + QComboBox* editor = new QComboBox(parent); + editor->clear(); + editor->addItems(_items); + return editor; + } else { + if(eEXPIRE_TIME == index.column()) { + QSpinBox* editor = new QSpinBox(parent); + connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); + return editor; + } else { + if(eENABLE_NOTIFICATION == index.column()) { + QCheckBox* editor = new QCheckBox(parent); + connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); + return editor; } - } - } - } + } + } + QLineEdit *editor = new QLineEdit(parent); + return editor; +} +void NotifyItemDelegate::commitAndCloseEditor() +{ + QLineEdit* editor = qobject_cast(sender()); + if (editor) { + emit commitData(editor); + emit closeEditor(editor); + } else { + QComboBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } else { + QSpinBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } else { + QCheckBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } + } + } + } +} + +void NotifyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QLineEdit* edit = qobject_cast(editor); + if(edit) { + edit->setText(index.model()->data(index, Qt::EditRole).toString()); + } else { + QComboBox* repeatEditor = qobject_cast(editor); + if(repeatEditor) + repeatEditor->setCurrentIndex(repeatEditor->findText(index.model()->data(index, Qt::EditRole).toString())); + else { + QSpinBox* expireEditor = qobject_cast(editor); + if(expireEditor) + expireEditor->setValue(index.model()->data(index, Qt::EditRole).toInt()); + else { + QCheckBox* enablePlayEditor = qobject_cast(editor); + if (enablePlayEditor) + enablePlayEditor->setChecked(index.model()->data(index, Qt::EditRole).toBool()); + } + } + } +} + +void NotifyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const +{ + QLineEdit *edit = qobject_cast(editor); + if(edit) { + model->setData(index, edit->text()); + } else { + QComboBox * repeatEditor = qobject_cast(editor); + if(repeatEditor) { + model->setData(index, repeatEditor->currentText()); + } else { + QSpinBox * expireEditor = qobject_cast(editor); + if(expireEditor) { + model->setData(index, expireEditor->value(), Qt::EditRole); + } else { + QCheckBox* enablePlayEditor = qobject_cast(editor); + if (enablePlayEditor) { + model->setData(index, enablePlayEditor->isChecked(), Qt::EditRole); + } + } + } + } +} void NotifyItemDelegate::selectRow(const QString & text) { - //QList list = ((QTableWidget*)(sender()->parent()))->findItems(text,Qt::MatchExactly); QComboBox* combo = qobject_cast(sender()); QTableWidget* table = new QTableWidget; table = (QTableWidget*)(combo->parent()); - qDebug()<columnCount(); - qDebug()<rowCount(); - qDebug()<currentRow(); - //table->setCurrentIndex(1); - //table->findItems(text,Qt::MatchExactly); - //item->model()->index() - //item->setSelected(true); + + qDebug() << table->columnCount(); + qDebug() << table->rowCount(); + qDebug() << table->currentRow(); } -QSize NotifyItemDelegate::sizeHint ( const QStyleOptionViewItem & option, - const QModelIndex & index ) const +QSize NotifyItemDelegate::sizeHint(const QStyleOptionViewItem & option, + const QModelIndex & index) const { QSize s = QItemDelegate::sizeHint(option, index); s.setHeight(10); - return s; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h index 40d6ced20..01fa0794d 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h @@ -31,21 +31,6 @@ #include #include -//class RepeatCounterDelegate : public QItemDelegate -//{ -// Q_OBJECT - -//public: -// RepeatCounterDelegate(QObject *parent = 0); -// QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, -// const QModelIndex &index) const; -// void setEditorData(QWidget *editor, const QModelIndex &index) const; -// void setModelData(QWidget *editor, QAbstractItemModel *model, -// const QModelIndex &index) const; - -//private slots: -// void commitAndCloseEditor(); -//}; class NotifyItemDelegate : public QItemDelegate { @@ -58,19 +43,16 @@ public: void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; -// bool editorEvent(QEvent * event, QAbstractItemModel * model, -// const QStyleOptionViewItem & option, const QModelIndex & index ); QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; -private: - QObject* m_parent; - QStringList m_items; - QComboBox* repeatEditor; - - private slots: void selectRow(const QString & text); void commitAndCloseEditor(); + +private: + QObject* _parent; + QStringList _items; + }; #endif // NOTIFYITEMDELEGATE_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 8735f8b60..c959925b4 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -26,7 +26,7 @@ */ #include "notifyplugin.h" -#include "notifypluginconfiguration.h" +#include "notificationitem.h" #include "notifypluginoptionspage.h" #include #include @@ -37,15 +37,29 @@ #include #include "qxttimer.h" +#include "backendcapabilities.h" static const QString VERSION = "1.0.0"; //#define DEBUG_NOTIFIES +#ifdef DEBUG_NOTIFIES +QDebug qNotifyDebug() +#endif +#ifndef DEBUG_NOTIFIES +QNoDebug qNotifyDebug() +#endif +{ +#ifdef DEBUG_NOTIFIES + return qDebug(); +#endif + return QNoDebug(); +} + SoundNotifyPlugin::SoundNotifyPlugin() { - phonon.mo = NULL; - configured = false; + phonon.mo = NULL; + configured = false; // Do nothing } @@ -121,7 +135,7 @@ void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo *configIn int size = settings->beginReadArray("listNotifies"); for (int i = 0; i < size; ++i) { settings->setArrayIndex(i); - NotifyPluginConfiguration* notification = new NotifyPluginConfiguration; + NotificationItem* notification = new NotificationItem; notification->restoreState(settings); lstNotifications.append(notification); } @@ -145,7 +159,7 @@ void SoundNotifyPlugin::readConfig_0_0_0(){ int size = settings->beginReadArray("listNotifies"); for (int i = 0; i < size; ++i) { settings->setArrayIndex(i); - NotifyPluginConfiguration* notification = new NotifyPluginConfiguration; + NotificationItem* notification = new NotificationItem; notification->restoreState(settings); lstNotifications.append(notification); } @@ -185,7 +199,7 @@ void SoundNotifyPlugin::onAutopilotDisconnect() void SoundNotifyPlugin::resetNotification(void) { //first, reject empty args and unknown fields. - foreach(NotifyPluginConfiguration* notify,lstNotifications) { + foreach(NotificationItem* notify,lstNotifications) { if(notify->timer) { disconnect(notify->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); @@ -207,7 +221,7 @@ void SoundNotifyPlugin::resetNotification(void) update list of notifies; will be perform on OK or APPLY press of option page */ -void SoundNotifyPlugin::updateNotificationList(QList list) +void SoundNotifyPlugin::updateNotificationList(QList list) { removedNotifies.clear(); resetNotification(); @@ -224,10 +238,10 @@ void SoundNotifyPlugin::connectNotifications() if (obj != NULL) disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(appendNotification(UAVObject*))); } - if(phonon.mo != NULL) { - delete phonon.mo; - phonon.mo = NULL; - } + if(phonon.mo != NULL) { + delete phonon.mo; + phonon.mo = NULL; + } if(!enableSound) return; @@ -240,25 +254,10 @@ void SoundNotifyPlugin::connectNotifications() removedNotifies.clear(); //first, reject empty args and unknown fields. - foreach(NotifyPluginConfiguration* notify,lstNotifications) { + foreach(NotificationItem* notify, lstNotifications) { notify->firstStart=true; notify->isNowPlaying=false; -// if(notify->timer) -// { -// disconnect(notify->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); -// notify->timer->stop(); -// delete notify->timer; -// notify->timer = NULL; -// } -// if(notify->expireTimer) -// { -// disconnect(notify->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); -// notify->expireTimer->stop(); -// delete notify->expireTimer; -// notify->expireTimer = NULL; -// } - UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); if (obj != NULL ) { if(!lstNotifiedUAVObjects.contains(obj)) { @@ -269,27 +268,25 @@ void SoundNotifyPlugin::connectNotifications() std::cout << "Error: Object is unknown (" << notify->getDataObject().toStdString() << ")." << std::endl; } - if(lstNotifications.isEmpty()) return; - // set notification message to current event - phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory); - phonon.mo->clearQueue(); - phonon.firstPlay = true; -#ifdef DEBUG_NOTIFIES - QList audioOutputDevices = - Phonon::BackendCapabilities::availableAudioOutputDevices(); - foreach(Phonon::AudioOutputDevice dev, audioOutputDevices) { - qDebug() << "Notify: Audio Output device: " << dev.name() << " - " << dev.description(); - } -#endif - connect(phonon.mo,SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(stateChanged(Phonon::State,Phonon::State))); + if(lstNotifications.isEmpty()) return; + // set notification message to current event + phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory); + phonon.mo->clearQueue(); + phonon.firstPlay = true; + QList audioOutputDevices = + Phonon::BackendCapabilities::availableAudioOutputDevices(); + foreach(Phonon::AudioOutputDevice dev, audioOutputDevices) { + qNotifyDebug() << "Notify: Audio Output device: " << dev.name() << " - " << dev.description(); + } + connect(phonon.mo, SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this, SLOT(stateChanged(Phonon::State,Phonon::State))); } void SoundNotifyPlugin::appendNotification(UAVObject *object) { disconnect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); - foreach(NotifyPluginConfiguration* notification, lstNotifications) { + foreach(NotificationItem* notification, lstNotifications) { if(object->getName()!=notification->getDataObject()) continue; @@ -306,7 +303,7 @@ void SoundNotifyPlugin::appendNotification(UAVObject *object) } -void SoundNotifyPlugin::checkNotificationRule(NotifyPluginConfiguration* notification, UAVObject* object) +void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) { bool condition=false; double threshold; @@ -350,7 +347,7 @@ void SoundNotifyPlugin::checkNotificationRule(NotifyPluginConfiguration* notific #endif // if audio is busy, start expiration timer //ms = (notification->getExpiredTimeout()[in sec])*1000 - //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotifyPluginConfiguration*)), qVariantFromValue(notification)); + //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); pendingNotifications.append(notification); if(!notification->expireTimer) { @@ -363,21 +360,22 @@ void SoundNotifyPlugin::checkNotificationRule(NotifyPluginConfiguration* notific } } -bool SoundNotifyPlugin::playNotification(NotifyPluginConfiguration* notification) +bool SoundNotifyPlugin::playNotification(NotificationItem* notification) { // Check: race condition, if phonon.mo got deleted don't go further if (phonon.mo == NULL) return false; + if(!notification->getEnableFlag()) return true; + #ifdef DEBUG_NOTIFIES qDebug() << "Phonon State: " << phonon.mo->state(); #endif - if((phonon.mo->state()==Phonon::PausedState) || - (phonon.mo->state()==Phonon::StoppedState) || - phonon.firstPlay) + if((phonon.mo->state()==Phonon::PausedState) + || (phonon.mo->state()==Phonon::StoppedState) + || phonon.firstPlay) { // don't fire expire timer - //notification->expire = false; nowPlayingConfiguration = notification; if(notification->expireTimer) notification->expireTimer->stop(); @@ -385,7 +383,6 @@ bool SoundNotifyPlugin::playNotification(NotifyPluginConfiguration* notification if(notification->getRepeatFlag()=="Repeat Once") { removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); - //if(!notification->firstStart) return true; } else { if(notification->getRepeatFlag()!="Repeat Instantly") @@ -407,24 +404,21 @@ bool SoundNotifyPlugin::playNotification(NotifyPluginConfiguration* notification } if(!notification->timer->isActive()) notification->timer->start(); - - //QxtTimer::singleShot(timer_value, this, SLOT(repeatTimerHandler(NotifyPluginConfiguration*)), qVariantFromValue(notification)); } } notification->firstStart=false; - phonon.mo->clear(); + phonon.mo->clear(); QString str = notification->parseNotifyMessage(); -#ifdef DEBUG_NOTIFIES - qDebug() << "play notification - " << str; -#endif - foreach(QString item, notification->getNotifyMessageList()) { - Phonon::MediaSource *ms = new Phonon::MediaSource(item); - ms->setAutoDelete(true); - phonon.mo->enqueue(*ms); - } + qNotifyDebug() << "play notification - " << str; + + foreach(QString item, notification->getMessageSequence()) { + Phonon::MediaSource *ms = new Phonon::MediaSource(item); + ms->setAutoDelete(true); + phonon.mo->enqueue(*ms); + } phonon.mo->play(); - phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before - // the state is not "Loading" anymore. + phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before + // the state is not "Loading" anymore. } else return false; // if audio is busy @@ -432,20 +426,9 @@ bool SoundNotifyPlugin::playNotification(NotifyPluginConfiguration* notification return true; } -//void SoundNotifyPlugin::repeatTimerHandler(NotifyPluginConfiguration* notification) -//{ -// qDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); - -// ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); -// UAVObjectManager *objManager = pm->getObject(); -// UAVObject* object = objManager->getObject(notification->getDataObject()); -// if(object) -// checkNotificationRule(notification,object); -//} - void SoundNotifyPlugin::repeatTimerHandler() { - NotifyPluginConfiguration* notification = static_cast(sender()->parent()); + NotificationItem* notification = static_cast(sender()->parent()); #ifdef DEBUG_NOTIFIES qDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); #endif @@ -459,7 +442,7 @@ void SoundNotifyPlugin::repeatTimerHandler() void SoundNotifyPlugin::expireTimerHandler() { // fire expire timer - NotifyPluginConfiguration* notification = static_cast(sender()->parent()); + NotificationItem* notification = static_cast(sender()->parent()); notification->expireTimer->stop(); if(!pendingNotifications.isEmpty()) @@ -494,7 +477,7 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst nowPlayingConfiguration=NULL; if(!pendingNotifications.isEmpty()) { - NotifyPluginConfiguration* notification = pendingNotifications.takeFirst(); + NotificationItem* notification = pendingNotifications.takeFirst(); #ifdef DEBUG_NOTIFIES qDebug() << "play audioFree - " << notification->parseNotifyMessage(); #endif diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h index 0d0eb50d8..afd68fecc 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h @@ -32,7 +32,7 @@ #include "uavtalk/telemetrymanager.h" #include "uavobjectmanager.h" #include "uavobject.h" -#include "notifypluginconfiguration.h" +#include "notificationitem.h" #include #include @@ -44,10 +44,12 @@ class NotifyPluginOptionsPage; typedef struct { Phonon::MediaObject* mo; - NotifyPluginConfiguration* notify; - bool firstPlay; + NotificationItem* notify; + bool firstPlay; } PhononObject, *pPhononObject; + + class SoundNotifyPlugin : public Core::IConfigurablePlugin { Q_OBJECT @@ -62,48 +64,42 @@ public: void shutdown(); - QList getListNotifications() { return lstNotifications; } - //void setListNotifications(QList& list_notify) { } - NotifyPluginConfiguration* getCurrentNotification(){ return ¤tNotification;} + QList getListNotifications() { return lstNotifications; } + NotificationItem* getCurrentNotification(){ return ¤tNotification;} bool getEnableSound() const { return enableSound; } void setEnableSound(bool value) {enableSound = value; } - - private: bool configured; // just for migration,delete later bool enableSound; QList< QList* > lstMediaSource; QStringList mediaSource; - //QMap mapMediaObjects; QMultiMap mapMediaObjects; - QSettings* settings; QList lstNotifiedUAVObjects; + QList lstNotifications; + QList pendingNotifications; + QList removedNotifies; - QList lstNotifications; - QList pendingNotifications; - QList removedNotifies; - - NotifyPluginConfiguration currentNotification; - NotifyPluginConfiguration* nowPlayingConfiguration; + NotificationItem currentNotification; + NotificationItem* nowPlayingConfiguration; QString m_field; PhononObject phonon; NotifyPluginOptionsPage *mop; TelemetryManager* telMngr; - bool playNotification(NotifyPluginConfiguration* notification); - void checkNotificationRule(NotifyPluginConfiguration* notification, UAVObject* object); + bool playNotification(NotificationItem* notification); + void checkNotificationRule(NotificationItem* notification, UAVObject* object); void readConfig_0_0_0(); private slots: void onTelemetryManagerAdded(QObject* obj); void onAutopilotDisconnect(); void connectNotifications(); - void updateNotificationList(QList list); + void updateNotificationList(QList list); void resetNotification(void); void appendNotification(UAVObject *object); void repeatTimerHandler(void); diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp index 94b88421e..8d5cb25e3 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp @@ -1,7 +1,7 @@ /** ****************************************************************************** * - * @file notifyPluginConfiguration.cpp + * @file NotificationItem.cpp * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Notify Plugin configuration * @see The GNU Public License (GPL) Version 3 @@ -25,60 +25,60 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "notifypluginconfiguration.h" +#include "NotificationItem.h" #include #include #include "utils/pathutils.h" -NotifyPluginConfiguration::NotifyPluginConfiguration(QObject *parent) : +NotificationItem::NotificationItem(QObject *parent) : QObject(parent), isNowPlaying(0), firstStart(1), - soundCollectionPath(""), - currentLanguage("default"), - dataObject(""), - objectField(""), - value("Equal to"), - sound1(""), - sound2(""), - sound3(""), - sayOrder("Never"), - spinBoxValue(0), - repeatString("Repeat Instantly"), - repeatTimeout(true), - expireTimeout(15) + _soundCollectionPath(""), + _currentLanguage("default"), + _dataObject(""), + _objectField(""), + _dataValue("Equal to"), + _sound1(""), + _sound2(""), + _sound3(""), + _sayOrder("Never"), + _spinBoxValue(0), + _repeatString("Repeat Instantly"), + _repeatTimeout(true), + _expireTimeout(15) { timer = NULL; expireTimer = NULL; } -void NotifyPluginConfiguration::copyTo(NotifyPluginConfiguration* that) const +void NotificationItem::copyTo(NotificationItem* that) const { that->isNowPlaying = isNowPlaying; that->firstStart = firstStart; - that->soundCollectionPath = soundCollectionPath; - that->currentLanguage = currentLanguage; - that->soundCollectionPath = soundCollectionPath; - that->dataObject = dataObject; - that->objectField = objectField; - that->value = value; - that->sound1 = sound1; - that->sound2 = sound2; - that->sound3 = sound3; - that->sayOrder = sayOrder; - that->spinBoxValue = spinBoxValue; - that->repeatString = repeatString; - that->repeatTimeout = repeatTimeout; - that->expireTimeout = expireTimeout; + that->_soundCollectionPath = _soundCollectionPath; + that->_currentLanguage = _currentLanguage; + that->_soundCollectionPath = _soundCollectionPath; + that->_dataObject = _dataObject; + that->_objectField = _objectField; + that->_dataValue = _dataValue; + that->_sound1 = _sound1; + that->_sound2 = _sound2; + that->_sound3 = _sound3; + that->_sayOrder = _sayOrder; + that->_spinBoxValue = _spinBoxValue; + that->_repeatString = _repeatString; + that->_repeatTimeout = _repeatTimeout; + that->_expireTimeout = _expireTimeout; } -void NotifyPluginConfiguration::saveState(QSettings* settings) const +void NotificationItem::saveState(QSettings* settings) const { - settings->setValue("SoundCollectionPath", Utils::PathUtils().RemoveDataPath(getSoundCollectionPath())); + settings->setValue("SoundCollectionPath", Utils::PathUtils().RemoveDataPath(getSoundCollectionPath())); settings->setValue(QLatin1String("CurrentLanguage"), getCurrentLanguage()); settings->setValue(QLatin1String("ObjectField"), getObjectField()); settings->setValue(QLatin1String("DataObject"), getDataObject()); @@ -92,7 +92,7 @@ void NotifyPluginConfiguration::saveState(QSettings* settings) const settings->setValue(QLatin1String("ExpireTimeout"), getExpireTimeout()); } -void NotifyPluginConfiguration::restoreState(QSettings* settings) +void NotificationItem::restoreState(QSettings* settings) { //settings = Core::ICore::instance()->settings(); setSoundCollectionPath(Utils::PathUtils().InsertDataPath(settings->value(QLatin1String("SoundCollectionPath"), tr("")).toString())); @@ -110,7 +110,7 @@ void NotifyPluginConfiguration::restoreState(QSettings* settings) } -QString NotifyPluginConfiguration::parseNotifyMessage() +QString NotificationItem::parseNotifyMessage() { // tips: // check of *.wav files exist needed for playing phonon queues; @@ -121,30 +121,30 @@ QString NotifyPluginConfiguration::parseNotifyMessage() str = QString("%L1 ").arg(getSpinBoxValue()); int position = 0xFF; // generate queue of sound files to play - notifyMessageList.clear(); + _messageSequence.clear(); - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav")); else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav")); - if(getSound2()!="") + if("" != getSound2()) { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav")); else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav")); } - if(getSound3()!="") + if("" != getSound3()) { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav")); else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav"))) - notifyMessageList.append(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav")); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav"))) + _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav")); } switch(str1.at(0).toAscii()) @@ -178,7 +178,7 @@ QString NotifyPluginConfiguration::parseNotifyMessage() break; } - if(position!=0xFF) + if(position != 0xFF) { QStringList numberParts = QString("%1").arg(getSpinBoxValue()).trimmed().split("."); QStringList numberFiles; @@ -212,9 +212,9 @@ QString NotifyPluginConfiguration::parseNotifyMessage() } } - if(numberParts.size()>1) { + if(1 < numberParts.size()) { numberFiles.append("point"); - if((numberParts.at(1).size()==1) /*|| (numberParts.at(1).toInt()<20)*/) + if((numberParts.at(1).size()==1)) numberFiles.append(numberParts.at(1)); else { if(numberParts.at(1).left(1)=="0") @@ -226,20 +226,18 @@ QString NotifyPluginConfiguration::parseNotifyMessage() } foreach(QString fileName,numberFiles) { fileName+=".wav"; - QString filePath = QDir::toNativeSeparators(getSoundCollectionPath()+"/"+ getCurrentLanguage()+"/"+fileName); + QString filePath = QDir::toNativeSeparators(getSoundCollectionPath()+"/"+ getCurrentLanguage()+"/"+fileName); if(QFile::exists(filePath)) - notifyMessageList.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+ "/"+getCurrentLanguage()+"/"+fileName)); + _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+ "/"+getCurrentLanguage()+"/"+fileName)); else { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName))) - notifyMessageList.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName)); + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName))) + _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName)); else { - notifyMessageList.clear(); + _messageSequence.clear(); break; // if no some of *.wav files, then don't play number! } } } } - - //str.replace(QString(".wav | .mp3"), QString("")); return str; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.h b/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.h deleted file mode 100644 index ad13a82a0..000000000 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - ****************************************************************************** - * - * @file notifypluginconfiguration.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Notify Plugin configuration header - * @see The GNU Public License (GPL) Version 3 - * @defgroup notifyplugin - * @{ - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef NOTIFYPLUGINCONFIGURATION_H -#define NOTIFYPLUGINCONFIGURATION_H -#include -#include "qsettings.h" -#include -#include - -using namespace Core; - -class NotifyPluginConfiguration : public QObject -{ - Q_OBJECT -public: - explicit NotifyPluginConfiguration(QObject *parent = 0); - - QTimer* timer; - QTimer* expireTimer; - bool isNowPlaying; // - bool firstStart; - - void copyTo(NotifyPluginConfiguration*) const; - - QString getSound1() const { return sound1; } - void setSound1(QString text) {sound1 = text; } - - QString getSound2() const { return sound2; } - void setSound2(QString text) {sound2 = text; } - - QString getSound3() const { return sound3; } - void setSound3(QString text) {sound3 = text; } - - QString getValue() const { return value; } - void setValue(QString text) {value = text; } - - QString getSayOrder() const { return sayOrder; } - void setSayOrder(QString text) {sayOrder = text; } - - double getSpinBoxValue() const { return spinBoxValue; } - void setSpinBoxValue(double value) {spinBoxValue = value; } - - - QString getDataObject() const { return dataObject; } - void setDataObject(QString text) {dataObject = text; } - - QString getObjectField() const { return objectField; } - void setObjectField(QString text) { objectField = text; } - - QString getSoundCollectionPath() const { return soundCollectionPath; } - void setSoundCollectionPath(QString text) { soundCollectionPath = text; } - - QString getCurrentLanguage() const { return currentLanguage; } - void setCurrentLanguage(QString text) { currentLanguage = text; } - - QStringList getNotifyMessageList() const { return notifyMessageList; } - void setNotifyMessageList(QStringList text) { notifyMessageList = text; } - - QString getRepeatFlag() const { return repeatString; } - void setRepeatFlag(QString value) { repeatString = value; } - - bool getRepeatTimeout() const { return repeatTimeout; } - void setRepeatTimeout(bool value) { repeatTimeout = value; } - - int getExpireTimeout() const { return expireTimeout; } - void setExpireTimeout(int value) { expireTimeout = value; } - - - - void saveState(QSettings* settings) const; - void restoreState(QSettings* settings); - QString parseNotifyMessage(); - -private: - QStringList notifyMessageList; - QString soundCollectionPath; - QString currentLanguage; - QString dataObject; - QString objectField; - - QString value; - QString sound1; - QString sound2; - QString sound3; - QString sayOrder; - double spinBoxValue; - QString repeatString; - bool repeatTimeout; - int repeatTimerValue; - int expireTimeout; - -}; - -Q_DECLARE_METATYPE(NotifyPluginConfiguration*) - -#endif // NOTIFYPLUGINCONFIGURATION_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 5dee5678a..48d8f9132 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -27,7 +27,7 @@ #include "notifypluginoptionspage.h" #include -#include "notifypluginconfiguration.h" +#include "notificationitem.h" #include "ui_notifypluginoptionspage.h" #include "extensionsystem/pluginmanager.h" #include "utils/pathutils.h" @@ -44,7 +44,7 @@ #include "notifyitemdelegate.h" #include "notifytablemodel.h" -NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotifyPluginConfiguration *config,*/ QObject *parent) : +NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) : IOptionsPage(parent), owner((SoundNotifyPlugin*)parent), currentCollectionPath(""), @@ -95,36 +95,29 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); -// connect(options_page->buttonTestSound1, SIGNAL(clicked()), this, SLOT(on_buttonTestSound1_clicked())); -// connect(options_page->buttonTestSound2, SIGNAL(clicked()), this, SLOT(on_buttonTestSound2_clicked())); connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); - connect(this, SIGNAL(updateNotifications(QList)), - owner, SLOT(updateNotificationList(QList))); + connect(this, SIGNAL(updateNotifications(QList)), + owner, SLOT(updateNotificationList(QList))); connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); //emit resetNotification(); + privListNotifications.clear(); - privListNotifications.clear(); - - for (int i = 0; i < owner->getListNotifications().size(); ++i) { - NotifyPluginConfiguration* notification = new NotifyPluginConfiguration(); - owner->getListNotifications().at(i)->copyTo(notification); - privListNotifications.append(notification); + for (int i = 0; i < owner->getListNotifications().size(); ++i) { + NotificationItem* notification = new NotificationItem(); + owner->getListNotifications().at(i)->copyTo(notification); + privListNotifications.append(notification); } - updateConfigView(owner->getCurrentNotification()); + updateConfigView(owner->getCurrentNotification()); - options_page->chkEnableSound->setChecked(owner->getEnableSound()); + options_page->chkEnableSound->setChecked(owner->getEnableSound()); - QStringList headerStrings; - headerStrings << "Name" << "Repeats" << "Lifetime,sec"; - - notifyRulesModel = new NotifyTableModel(&privListNotifications,headerStrings); + notifyRulesModel = new NotifyTableModel(&privListNotifications); options_page->notifyRulesView->setModel(notifyRulesModel); options_page->notifyRulesView->resizeRowsToContents(); notifyRulesSelection = new QItemSelectionModel(notifyRulesModel); @@ -135,50 +128,28 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) connect(this, SIGNAL(entryAdded(int)), notifyRulesModel, SLOT(entryAdded(int))); + options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); - options_page->notifyRulesView->setColumnWidth(0,200); - options_page->notifyRulesView->setColumnWidth(1,150); - options_page->notifyRulesView->setColumnWidth(2,100); + options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); + options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); + options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); + options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); options_page->buttonModify->setEnabled(false); options_page->buttonDelete->setEnabled(false); options_page->buttonPlayNotification->setEnabled(false); -// sound1 = Phonon::createPlayer(Phonon::NotificationCategory); -// sound2 = Phonon::createPlayer(Phonon::NotificationCategory); notifySound = Phonon::createPlayer(Phonon::NotificationCategory); -// audioOutput = new Phonon::AudioOutput(Phonon::NotificationCategory, this); -// Phonon::createPath(sound1, audioOutput); -// Phonon::createPath(sound2, audioOutput); -// Phonon::createPath(notifySound, audioOutput); - -// connect(sound1,SIGNAL(stateChanged(Phonon::State,Phonon::State)),SLOT(changeButtonText(Phonon::State,Phonon::State))); -// connect(sound2,SIGNAL(stateChanged(Phonon::State,Phonon::State)),SLOT(changeButtonText(Phonon::State,Phonon::State))); connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); return optionsPageWidget; } -void NotifyPluginOptionsPage::showPersistentComboBox( const QModelIndex & parent, int start, int end ) -{ -// for (int i=start; itableNotifications->openPersistentEditor(options_page->tableNotifications->item(i,1)); -// } -} - -void NotifyPluginOptionsPage::showPersistentComboBox2( const QModelIndex & topLeft, const QModelIndex & bottomRight ) -{ - //for (QModelIndex i=topLeft; itableNotifications->openPersistentEditor(options_page->tableNotifications->item(options_page->tableNotifications->currentRow(),1)); - } -} - - -void NotifyPluginOptionsPage::getOptionsPageValues(NotifyPluginConfiguration* notification) +void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); @@ -191,26 +162,16 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotifyPluginConfiguration* no notification->setValue(options_page->Value->currentText()); notification->setSpinBoxValue(options_page->ValueSpinBox->value()); -// if(notifyRulesSelection->currentIndex().row()>-1) -// { -// //qDebug() << "delegate value:" << options_page->tableNotifications->item(options_page->tableNotifications->currentRow(),1)->data(Qt::EditRole); -// notification->setRepeatFlag(notifyRulesModel->data(notifyRulesSelection->currentIndex(),Qt::DisplayRole).toString()); -// } } -//////////////////////////////////////////// -// Called when the user presses apply or OK. -// -// Saves the current values -// -//////////////////////////////////////////// +/*! +* Called when the user presses apply or OK. +* Saves the current values +*/ void NotifyPluginOptionsPage::apply() { - - getOptionsPageValues(owner->getCurrentNotification()); - + getOptionsPageValues(owner->getCurrentNotification()); owner->setEnableSound(options_page->chkEnableSound->isChecked()); - //owner->setListNotifications(privListNotifications); emit updateNotifications(privListNotifications); } @@ -218,25 +179,22 @@ void NotifyPluginOptionsPage::finish() { disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - if(notifySound) - { + if (notifySound) { notifySound->stop(); notifySound->clear(); } - - delete options_page; + if (options_page) + delete options_page; } - - ////////////////////////////////////////////////////////////////////////////// // Fills in the combo box when value is changed in the // combo box ////////////////////////////////////////////////////////////////////////////// void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { options_page->UAVObjectField->clear(); - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager* objManager = pm->getObject(); UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); QList fieldList = obj->getFields(); foreach (UAVObjectField* field, fieldList) { @@ -258,8 +216,8 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) { options_page->SoundCollectionList->setCurrentIndex(index); - currentCollectionPath = options_page->SoundDirectoryPathChooser->path() + - QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); + currentCollectionPath = options_page->SoundDirectoryPathChooser->path() + + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); QDir dirPath(currentCollectionPath); QStringList filters; @@ -280,30 +238,38 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) { - if(newstate == Phonon::PausedState || newstate == Phonon::StoppedState){ + Q_ASSERT(Phonon::ErrorState != newstate); + + if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { options_page->buttonPlayNotification->setText("Play"); options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); - } - else - if(newstate == Phonon::PlayingState) { - options_page->buttonPlayNotification->setText("Stop"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + } else { + if (newstate == Phonon::PlayingState) { + options_page->buttonPlayNotification->setText("Stop"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + } } } +void NotifyPluginOptionsPage::onFinishedPlaying() +{ + notifySound->clear(); +} void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() { - // QList messageNotify; - NotifyPluginConfiguration *notification; + NotificationItem* notification = NULL; - if(notifyRulesSelection->currentIndex().row()==-1) return; - - notifySound->clearQueue(); + if (-1 == notifyRulesSelection->currentIndex().row()) + return; + notifySound->clearQueue(); notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); notification->parseNotifyMessage(); - foreach(QString item, notification->getNotifyMessageList()) - notifySound->enqueue(Phonon::MediaSource(item)); + QStringList sequence = notification->getMessageSequence(); + Q_ASSERT(!!sequence.size()); + foreach(QString item, sequence) + notifySound->enqueue(Phonon::MediaSource(item)); + notifySound->play(); } @@ -316,25 +282,24 @@ void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) audioOutput->setMuted(state1); } -void NotifyPluginOptionsPage::updateConfigView(NotifyPluginConfiguration* notification) +void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { QString path = notification->getSoundCollectionPath(); - if(path=="") - { + if (path == "") { //QDir dir = QDir::currentPath(); //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; - path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); + path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); } + options_page->SoundDirectoryPathChooser->setPath(path); - if(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())!=-1){ + if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); - } - else + } else { options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + } - - if(options_page->UAVObject->findText(notification->getDataObject())!=-1){ + if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); } @@ -349,15 +314,13 @@ void NotifyPluginOptionsPage::updateConfigView(NotifyPluginConfiguration* notifi } } - if(options_page->UAVObjectField->findText(notification->getObjectField())!=-1){ + if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); } - if(options_page->Sound1->findText(notification->getSound1())!=-1){ + if (-1 != options_page->Sound1->findText(notification->getSound1())) { options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); - } - else - { + } else { // show item from default location options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); @@ -366,10 +329,9 @@ void NotifyPluginOptionsPage::updateConfigView(NotifyPluginConfiguration* notifi //options_page->Sound1->setCurrentIndex(-1); } - if(options_page->Sound2->findText(notification->getSound2())!=-1) { + if (-1 != options_page->Sound2->findText(notification->getSound2())) { options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); - } - else { + } else { // show item from default location options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); @@ -378,33 +340,33 @@ void NotifyPluginOptionsPage::updateConfigView(NotifyPluginConfiguration* notifi //options_page->Sound2->setCurrentIndex(-1); } - if(options_page->Sound3->findText(notification->getSound3())!=-1) { + if (-1 != options_page->Sound3->findText(notification->getSound3())) { options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); - } - else { + } else { // show item from default location options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); } - if(options_page->Value->findText(notification->getValue())!=-1) { + if (-1 != options_page->Value->findText(notification->getValue())) { options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); } - if(options_page->SayOrder->findText(notification->getSayOrder())!=-1) { + if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); } + options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); } void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) { - bool select = true; + bool select = false; notifySound->stop(); - if(selected.indexes().size()) + if (selected.indexes().size()) { + select = true; updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); - else - select = false; + } options_page->buttonModify->setEnabled(select); options_page->buttonDelete->setEnabled(select); @@ -412,13 +374,11 @@ void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemS } - void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() { - NotifyPluginConfiguration* notification = new NotifyPluginConfiguration; + NotificationItem* notification = new NotificationItem; - if(options_page->SoundDirectoryPathChooser->path()=="") - { + if (options_page->SoundDirectoryPathChooser->path()=="") { QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); options_page->SoundDirectoryPathChooser->setPalette(textPalette); @@ -433,20 +393,20 @@ void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() notification->setValue(options_page->Value->currentText()); notification->setSpinBoxValue(options_page->ValueSpinBox->value()); - if(options_page->Sound1->currentText()!="") + if (options_page->Sound1->currentText().size() > 0) notification->setSound1(options_page->Sound1->currentText()); notification->setSound2(options_page->Sound2->currentText()); notification->setSound3(options_page->Sound3->currentText()); - if(((options_page->Sound2->currentText()=="")&&(options_page->SayOrder->currentText()=="After second")) - || ((options_page->Sound3->currentText()=="")&&(options_page->SayOrder->currentText()=="After third"))) + if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) + || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { return; - else + } else { notification->setSayOrder(options_page->SayOrder->currentText()); - + } privListNotifications.append(notification); - emit entryAdded(privListNotifications.size()-1); + emit entryAdded(privListNotifications.size() - 1); notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } @@ -455,7 +415,9 @@ void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() { notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); - if(!notifyRulesModel->rowCount() && (notifyRulesSelection->currentIndex().row() > 0 && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount())) + if (!notifyRulesModel->rowCount() + && (notifyRulesSelection->currentIndex().row() > 0 + && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) { options_page->buttonDelete->setEnabled(false); options_page->buttonModify->setEnabled(false); @@ -466,7 +428,7 @@ void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() { - NotifyPluginConfiguration* notification = new NotifyPluginConfiguration; + NotificationItem* notification = new NotificationItem; getOptionsPageValues(notification); notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 9d159e2a4..31da8373f 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -45,7 +45,7 @@ class NotifyTableModel; -class NotifyPluginConfiguration; +class NotificationItem; class SoundNotifyPlugin; namespace Ui { @@ -59,7 +59,7 @@ class NotifyPluginOptionsPage : public IOptionsPage { Q_OBJECT public: - explicit NotifyPluginOptionsPage(/*NotifyPluginConfiguration *config, */QObject *parent = 0); + explicit NotifyPluginOptionsPage(/*NotificationItem *config, */QObject *parent = 0); QString id() const { return QLatin1String("settings"); } QString trName() const { return tr("settings"); } @@ -73,8 +73,8 @@ public: void finish(); void restoreFromSettings(); - void updateConfigView(NotifyPluginConfiguration* notification); - void getOptionsPageValues(NotifyPluginConfiguration* notification); + void updateConfigView(NotificationItem* notification); + void getOptionsPageValues(NotificationItem* notification); private: UAVObjectManager *objManager; @@ -90,24 +90,18 @@ private: QStringList delegateItems; NotifyTableModel* notifyRulesModel; QItemSelectionModel *notifyRulesSelection; - QList privListNotifications; + QList privListNotifications; Ui::NotifyPluginOptionsPage *options_page; - //NotifyPluginConfiguration *notify; signals: - void updateNotifications(QList list); + void updateNotifications(QList list); void resetNotification(void); void entryUpdated(int index); void entryAdded(int position); private slots: - void showPersistentComboBox( const QModelIndex & parent, int start, int end ); - void showPersistentComboBox2 ( const QModelIndex & topLeft, const QModelIndex & bottomRight ); - -// void on_buttonTestSound1_clicked(); -// void on_buttonTestSound2_clicked(); void on_buttonTestSoundNotification_clicked(); void on_buttonAddNotification_clicked(); @@ -119,6 +113,9 @@ private slots: void on_UAVObject_indexChanged(QString val); void changeButtonText(Phonon::State newstate, Phonon::State oldstate); void on_chkEnableSound_toggled(bool state); + + void onFinishedPlaying(void); + }; #endif // NOTIFYPLUGINOPTIONSPAGE_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui index b3f48432a..4645bd14a 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui @@ -24,7 +24,7 @@ 10 10 - 501 + 551 81 @@ -36,7 +36,7 @@ 10 20 - 481 + 531 51 @@ -89,7 +89,7 @@ p, li { white-space: pre-wrap; } 10 220 - 501 + 551 211 @@ -101,7 +101,7 @@ p, li { white-space: pre-wrap; } 10 180 - 481 + 531 26 @@ -203,7 +203,7 @@ p, li { white-space: pre-wrap; } 10 20 - 481 + 531 151 @@ -226,7 +226,7 @@ p, li { white-space: pre-wrap; } 10 100 - 501 + 551 31 @@ -272,7 +272,7 @@ p, li { white-space: pre-wrap; } 7 130 - 501 + 551 20 @@ -285,7 +285,7 @@ p, li { white-space: pre-wrap; } 10 180 - 501 + 551 31 @@ -390,7 +390,7 @@ p, li { white-space: pre-wrap; } 10 150 - 501 + 551 31 diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index 6f0584d70..6e503cbd8 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -26,17 +26,30 @@ */ #include "notifytablemodel.h" +#include + +NotifyTableModel::NotifyTableModel(QList* parentList, QObject* parent) + : QAbstractTableModel(parent) +{ + _headerStrings << "Name" << "Repeats" << "Lifetime,sec" << "Enable"; + _list.reset(parentList); +} + bool NotifyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::EditRole) { - if(index.column()==1) + if(eREPEAT_VALUE == index.column()) _list->at(index.row())->setRepeatFlag(value.toString()); - else - if(index.column()==2) + else { + if(eEXPIRE_TIME == index.column()) _list->at(index.row())->setExpireTimeout(value.toInt()); - + else { + if(eENABLE_NOTIFICATION == index.column()) + _list->at(index.row())->setEnableFlag(value.toBool()); + } + } emit dataChanged(index, index); return true; } @@ -45,9 +58,10 @@ bool NotifyTableModel::setData(const QModelIndex &index, QVariant NotifyTableModel::data(const QModelIndex &index, int role) const { - - if (!index.isValid()) + if (!index.isValid()) { + qWarning() << "NotifyTableModel::data - index.isValid()"; return QVariant(); + } if (index.row() >= _list->size()) return QVariant(); @@ -56,15 +70,18 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const { switch(index.column()) { - case 0: + case eMESSAGE_NAME: return _list->at(index.row())->parseNotifyMessage(); - case 1: + case eREPEAT_VALUE: return _list->at(index.row())->getRepeatFlag(); - case 2: + case eEXPIRE_TIME: return _list->at(index.row())->getExpireTimeout(); + case eENABLE_NOTIFICATION: + return _list->at(index.row())->getEnableFlag(); + default: return QVariant(); } @@ -72,12 +89,8 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const else { if (Qt::SizeHintRole == role){ - //QVariant size = data(index, Qt::SizeHintRole); return QVariant(10); } - // if(role == Qt::DecorationRole) - // if (index.column() == 0) - // return defectsIcons[defectList->at(index.row()).id-1]; } return QVariant(); } @@ -88,7 +101,7 @@ QVariant NotifyTableModel::headerData(int section, Qt::Orientation orientation, return QVariant(); if (orientation == Qt::Horizontal) - return headerStrings.at(section); + return _headerStrings.at(section); else if(orientation == Qt::Vertical) return QString("%1").arg(section); @@ -100,12 +113,6 @@ bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex &ind { Q_UNUSED(index); beginInsertRows(QModelIndex(), position, position+rows-1); - -// for (int row=0; row < rows; ++row) { -// _list->append(position); -// } - - endInsertRows(); return true; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index 65aa82a86..978605fbe 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -31,26 +31,28 @@ #include #include -#include "notifypluginconfiguration.h" +#include "notificationitem.h" + +enum ColumnNames { eMESSAGE_NAME, eREPEAT_VALUE, eEXPIRE_TIME, eENABLE_NOTIFICATION }; class NotifyTableModel : public QAbstractTableModel { Q_OBJECT - public: - NotifyTableModel(QList *parentList, const QStringList& parentHeaderList, QObject *parent = 0) - : QAbstractTableModel(parent), - _list(parentList), - headerStrings(parentHeaderList) - { } - int rowCount(const QModelIndex &parent = QModelIndex()) const + enum {eColumnCount = 4 }; + +public: + + NotifyTableModel(QList* parentList, QObject* parent = 0); + + int rowCount(const QModelIndex& parent = QModelIndex()) const { return _list->count(); } int columnCount(const QModelIndex &/*parent*/) const { - return 3; + return eColumnCount; } Qt::ItemFlags flags(const QModelIndex &index) const @@ -71,8 +73,8 @@ private slots: void entryUpdated(int offset); void entryAdded(int position); private: - QList *_list; - QStringList headerStrings; + QScopedPointer > _list; + QStringList _headerStrings; }; diff --git a/openpilotgcs.bat b/openpilotgcs.bat new file mode 100644 index 000000000..a656aa85b --- /dev/null +++ b/openpilotgcs.bat @@ -0,0 +1,3 @@ +cd D:\Qt\4.7.3\bin\ + +call D:\!Work\OpenSource\OpenPilot\OpenPilot\build\ground\openpilotgcs\bin\openpilotgcs.exe \ No newline at end of file From e14e0a763b409d83b69bec98ddfef0e44f9225fc Mon Sep 17 00:00:00 2001 From: Nickolay Date: Thu, 15 Sep 2011 01:35:19 +0300 Subject: [PATCH 02/72] - temporary remove assert in finished callback; --- .../openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 48d8f9132..686c59c3b 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -238,7 +238,7 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) { - Q_ASSERT(Phonon::ErrorState != newstate); + //Q_ASSERT(Phonon::ErrorState != newstate); if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { options_page->buttonPlayNotification->setText("Play"); From c16e386e6375538b5be59f637ef65f0c408cfa05 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Fri, 16 Sep 2011 02:24:35 +0300 Subject: [PATCH 03/72] +reordering of table items - experimenting with D&D --- ...configuration.cpp => notificationitem.cpp} | 0 .../src/plugins/notify/notify.pro | 6 +- .../src/plugins/notify/notifyplugin.h | 35 +++--- .../notify/notifypluginoptionspage.cpp | 111 ++++++++++-------- .../plugins/notify/notifypluginoptionspage.h | 22 ++-- .../src/plugins/notify/notifytablemodel.cpp | 30 ++--- .../src/plugins/notify/notifytablemodel.h | 9 +- 7 files changed, 120 insertions(+), 93 deletions(-) rename ground/openpilotgcs/src/plugins/notify/{notifypluginconfiguration.cpp => notificationitem.cpp} (100%) diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp similarity index 100% rename from ground/openpilotgcs/src/plugins/notify/notifypluginconfiguration.cpp rename to ground/openpilotgcs/src/plugins/notify/notificationitem.cpp diff --git a/ground/openpilotgcs/src/plugins/notify/notify.pro b/ground/openpilotgcs/src/plugins/notify/notify.pro index e70392a6a..b8eeb35fd 100644 --- a/ground/openpilotgcs/src/plugins/notify/notify.pro +++ b/ground/openpilotgcs/src/plugins/notify/notify.pro @@ -12,13 +12,13 @@ HEADERS += notifyplugin.h \ notifypluginoptionspage.h \ notifyitemdelegate.h \ notifytablemodel.h \ - NotificationItem.h + notificationitem.h SOURCES += notifyplugin.cpp \ notifypluginoptionspage.cpp \ - notifypluginconfiguration.cpp \ notifyitemdelegate.cpp \ - notifytablemodel.cpp + notifytablemodel.cpp \ + notificationitem.cpp OTHER_FILES += NotifyPlugin.pluginspec diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h index afd68fecc..c1e0ce620 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h @@ -71,6 +71,26 @@ public: void setEnableSound(bool value) {enableSound = value; } private: + SoundNotifyPlugin(const SoundNotifyPlugin& rhs); + SoundNotifyPlugin& operator= (const SoundNotifyPlugin& rhs); + + bool playNotification(NotificationItem* notification); + void checkNotificationRule(NotificationItem* notification, UAVObject* object); + void readConfig_0_0_0(); + +private slots: + void onTelemetryManagerAdded(QObject* obj); + void onAutopilotDisconnect(); + void connectNotifications(); + void updateNotificationList(QList list); + void resetNotification(void); + void appendNotification(UAVObject *object); + void repeatTimerHandler(void); + void expireTimerHandler(void); + void stateChanged(Phonon::State newstate, Phonon::State oldstate); + +private: + bool configured; // just for migration,delete later bool enableSound; QList< QList* > lstMediaSource; @@ -90,21 +110,6 @@ private: PhononObject phonon; NotifyPluginOptionsPage *mop; TelemetryManager* telMngr; - - bool playNotification(NotificationItem* notification); - void checkNotificationRule(NotificationItem* notification, UAVObject* object); - void readConfig_0_0_0(); - -private slots: - void onTelemetryManagerAdded(QObject* obj); - void onAutopilotDisconnect(); - void connectNotifications(); - void updateNotificationList(QList list); - void resetNotification(void); - void appendNotification(UAVObject *object); - void repeatTimerHandler(void); - void expireTimerHandler(void); - void stateChanged(Phonon::State newstate, Phonon::State oldstate); }; #endif // SOUNDNOTIFYPLUGIN_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 686c59c3b..cee9a4027 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -44,24 +44,26 @@ #include "notifyitemdelegate.h" #include "notifytablemodel.h" -NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) : - IOptionsPage(parent), - owner((SoundNotifyPlugin*)parent), - currentCollectionPath(""), - privListNotifications(((SoundNotifyPlugin*)parent)->getListNotifications()) +NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) + : IOptionsPage(parent) + , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) + , owner(qobject_cast(parent)) + , currentCollectionPath("") + , privListNotifications((qobject_cast(parent))->getListNotifications()) { - } +NotifyPluginOptionsPage::~NotifyPluginOptionsPage() +{ +} //creates options page widget (uses the UI file) QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) { - - options_page = new Ui::NotifyPluginOptionsPage(); - //main widget - QWidget *optionsPageWidget = new QWidget; - //main layout + options_page.reset(new Ui::NotifyPluginOptionsPage()); + //main widget + QWidget *optionsPageWidget = new QWidget; + //main layout options_page->setupUi(optionsPageWidget); delegateItems.clear(); @@ -73,17 +75,11 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) << "Repeat 30 seconds" << "Repeat 1 minute"; - options_page->chkEnableSound->setChecked(owner->getEnableSound()); options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); - - - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - objManager = pm->getObject(); - // Fills the combo boxes for the UAVObjects - QList< QList > objList = objManager->getDataObjects(); + QList< QList > objList = objManager.getDataObjects(); foreach (QList list, objList) { foreach (UAVDataObject* obj, list) { options_page->UAVObject->addItem(obj->getName()); @@ -92,13 +88,8 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); - connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); - connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); - connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); - connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); - connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + connect(this, SIGNAL(updateNotifications(QList)), owner, SLOT(updateNotificationList(QList))); connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); @@ -115,20 +106,52 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) updateConfigView(owner->getCurrentNotification()); + initButtons(); + initRulesTableModel(); + initRulesTableView(); + initPhononPlayer(); + + return optionsPageWidget; +} + +void NotifyPluginOptionsPage::initButtons() +{ options_page->chkEnableSound->setChecked(owner->getEnableSound()); + connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - notifyRulesModel = new NotifyTableModel(&privListNotifications); - options_page->notifyRulesView->setModel(notifyRulesModel); + options_page->buttonModify->setEnabled(false); + options_page->buttonDelete->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); + connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); + connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); + connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); +} + +void NotifyPluginOptionsPage::initPhononPlayer() +{ + notifySound = Phonon::createPlayer(Phonon::NotificationCategory); + connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); +} + +void NotifyPluginOptionsPage::initRulesTableModel() +{ + notifyRulesModel.reset(new NotifyTableModel(&privListNotifications)); + notifyRulesSelection = new QItemSelectionModel(notifyRulesModel.data()); + connect(notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), + this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); + connect(this, SIGNAL(entryUpdated(int)), + notifyRulesModel.data(), SLOT(entryUpdated(int))); + connect(this, SIGNAL(entryAdded(int)), + notifyRulesModel.data(), SLOT(entryAdded(int))); +} + +void NotifyPluginOptionsPage::initRulesTableView() +{ + options_page->notifyRulesView->setModel(notifyRulesModel.data()); options_page->notifyRulesView->resizeRowsToContents(); - notifyRulesSelection = new QItemSelectionModel(notifyRulesModel); - connect(notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), - this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); - connect(this, SIGNAL(entryUpdated(int)), - notifyRulesModel, SLOT(entryUpdated(int))); - connect(this, SIGNAL(entryAdded(int)), - notifyRulesModel, SLOT(entryAdded(int))); - - options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); @@ -136,17 +159,9 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); - - options_page->buttonModify->setEnabled(false); - options_page->buttonDelete->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - - notifySound = Phonon::createPlayer(Phonon::NotificationCategory); - connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); - - return optionsPageWidget; + options_page->notifyRulesView->setDragEnabled(true); + options_page->notifyRulesView->setAcceptDrops(true); + options_page->notifyRulesView->setDropIndicatorShown(true); } void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) @@ -183,8 +198,6 @@ void NotifyPluginOptionsPage::finish() notifySound->stop(); notifySound->clear(); } - if (options_page) - delete options_page; } ////////////////////////////////////////////////////////////////////////////// @@ -306,7 +319,7 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) // Now load the object field values: options_page->UAVObjectField->clear(); QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast( objManager->getObject(uavDataObject/*objList.at(0).at(0)->getName()*/) ); + UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); if (obj != NULL ) { QList fieldList = obj->getFields(); foreach (UAVObjectField* field, fieldList) { diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 31da8373f..521cf9874 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -42,16 +42,13 @@ #include #include #include +#include "ui_notifypluginoptionspage.h" +//#include "notifytablemodel.h" class NotifyTableModel; - class NotificationItem; class SoundNotifyPlugin; -namespace Ui { - class NotifyPluginOptionsPage; -} - using namespace Core; @@ -60,7 +57,7 @@ class NotifyPluginOptionsPage : public IOptionsPage Q_OBJECT public: explicit NotifyPluginOptionsPage(/*NotificationItem *config, */QObject *parent = 0); - + ~NotifyPluginOptionsPage(); QString id() const { return QLatin1String("settings"); } QString trName() const { return tr("settings"); } QString category() const { return QLatin1String("Notify Plugin");} @@ -77,7 +74,14 @@ public: void getOptionsPageValues(NotificationItem* notification); private: - UAVObjectManager *objManager; + //Q_DISABLE_COPY(NotifyPluginOptionsPage) + void initButtons(); + void initPhononPlayer(); + void initRulesTableModel(); + void initRulesTableView(); + +private: + UAVObjectManager& objManager; SoundNotifyPlugin* owner; QStringList listDirCollections; QStringList listSoundFiles; @@ -88,11 +92,11 @@ private: Phonon::MediaObject *notifySound; Phonon::AudioOutput *audioOutput; QStringList delegateItems; - NotifyTableModel* notifyRulesModel; + QScopedPointer notifyRulesModel; QItemSelectionModel *notifyRulesSelection; QList privListNotifications; - Ui::NotifyPluginOptionsPage *options_page; + QScopedPointer options_page; signals: void updateNotifications(QList list); diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index 6e503cbd8..f3c89b5b7 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -109,26 +109,26 @@ QVariant NotifyTableModel::headerData(int section, Qt::Orientation orientation, return QVariant(); } -bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex &index) +bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex& index) { - Q_UNUSED(index); - beginInsertRows(QModelIndex(), position, position+rows-1); - endInsertRows(); - return true; + Q_UNUSED(index); + beginInsertRows(QModelIndex(), position, position+rows-1); + endInsertRows(); + return true; } - bool NotifyTableModel::removeRows(int position, int rows, const QModelIndex &index) - { - Q_UNUSED(index); - beginRemoveRows(QModelIndex(), position, position+rows-1); +bool NotifyTableModel::removeRows(int position, int rows, const QModelIndex& index) +{ + Q_UNUSED(index); + beginRemoveRows(QModelIndex(), position, position+rows-1); - for (int row=0; row < rows; ++row) { - _list->removeAt(position); - } + for (int row=0; row < rows; ++row) { + _list->removeAt(position); + } - endRemoveRows(); - return true; - } + endRemoveRows(); + return true; +} void NotifyTableModel::entryUpdated(int offset) { diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index 978605fbe..affae25da 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -58,11 +58,16 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const { if (!index.isValid()) - return Qt::ItemIsEnabled; + return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; - return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } + Qt::DropActions supportedDropActions() const + { + return Qt::MoveAction; + } + bool setData(const QModelIndex &index, const QVariant &value, int role); QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; From 56e71cd82ec0fbe0040d8dce03ee8097f70f8d37 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Sep 2011 18:39:20 +0300 Subject: [PATCH 04/72] +removed public members in notificationitem; +cosmetic changes; +fixed indentation; --- .../internals/projections/lks94projection.h | 2 +- .../src/plugins/notify/NotificationItem.h | 156 +++--- .../src/plugins/notify/notificationitem.cpp | 420 ++++++++------- .../src/plugins/notify/notify.pro | 8 +- .../src/plugins/notify/notifyitemdelegate.cpp | 202 ++++---- .../src/plugins/notify/notifylogging.cpp | 42 ++ .../src/plugins/notify/notifylogging.h | 42 ++ .../src/plugins/notify/notifyplugin.cpp | 488 ++++++++---------- .../src/plugins/notify/notifyplugin.h | 1 - .../notify/notifypluginoptionspage.cpp | 469 +++++++++-------- .../notify/notifypluginoptionspage.cpp.orig | 465 +++++++++++++++++ .../plugins/notify/notifypluginoptionspage.h | 2 +- .../src/plugins/notify/notifytablemodel.cpp | 114 ++-- 13 files changed, 1493 insertions(+), 918 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/notify/notifylogging.cpp create mode 100644 ground/openpilotgcs/src/plugins/notify/notifylogging.h create mode 100644 ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h index dc895f04c..efbe9c394 100644 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h +++ b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h @@ -28,7 +28,7 @@ #define LKS94PROJECTION_H #include #include "cmath" -#include "D:\!Work\OpenSource\OpenPilot\OpenPilot\ground\openpilotgcs\src\libs\opmapcontrol\src\internals\pureprojection.h" +#include "D:\!Work\OpenPilot\OpenPilot\ground\openpilotgcs\src\libs\opmapcontrol\src\internals\pureprojection.h" namespace projections { diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index c09e64982..ad7250060 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -40,113 +40,129 @@ using namespace Core; QString getSound##number() const { return _sound##number; } \ void setSound##number(QString text) { _sound##number = text; } \ -// QString getSound2() const { return _sound2; } -// void setSound2(QString text) { _sound2 = text; } - -// QString getSound3() const { return _sound3; } -// void setSound3(QString text) { _sound3 = text; } class NotificationItem : public QObject { - Q_OBJECT + Q_OBJECT public: - explicit NotificationItem(QObject *parent = 0); + explicit NotificationItem(QObject *parent = 0); - void copyTo(NotificationItem*) const; + void copyTo(NotificationItem*) const; - DECLARE_SOUND(1) - DECLARE_SOUND(2) - DECLARE_SOUND(3) + DECLARE_SOUND(1) + DECLARE_SOUND(2) + DECLARE_SOUND(3) - QString getValue() const { return _dataValue; } - void setValue(QString text) { _dataValue = text; } + QString getValue() const { return _dataValue; } + void setValue(QString text) { _dataValue = text; } - QString getSayOrder() const { return _sayOrder; } - void setSayOrder(QString text) { _sayOrder = text; } + QString getSayOrder() const { return _sayOrder; } + void setSayOrder(QString text) { _sayOrder = text; } - double getSpinBoxValue() const { return _spinBoxValue; } - void setSpinBoxValue(double value) { _spinBoxValue = value; } + double getSpinBoxValue() const { return _spinBoxValue; } + void setSpinBoxValue(double value) { _spinBoxValue = value; } - QString getDataObject() const { return _dataObject; } - void setDataObject(QString text) { _dataObject = text; } + QString getDataObject() const { return _dataObject; } + void setDataObject(QString text) { _dataObject = text; } - QString getObjectField() const { return _objectField; } - void setObjectField(QString text) { _objectField = text; } + QString getObjectField() const { return _objectField; } + void setObjectField(QString text) { _objectField = text; } - QString getSoundCollectionPath() const { return _soundCollectionPath; } - void setSoundCollectionPath(QString path) { _soundCollectionPath = path; } + QString getSoundCollectionPath() const { return _soundCollectionPath; } + void setSoundCollectionPath(QString path) { _soundCollectionPath = path; } - QString getCurrentLanguage() const { return _currentLanguage; } - void setCurrentLanguage(QString text) { _currentLanguage = text; } + QString getCurrentLanguage() const { return _currentLanguage; } + void setCurrentLanguage(QString text) { _currentLanguage = text; } - QStringList getMessageSequence() const { return _messageSequence; } - void setMessageSequence(QStringList sequence) { _messageSequence = sequence; } + QStringList getMessageSequence() const { return _messageSequence; } + void setMessageSequence(QStringList sequence) { _messageSequence = sequence; } - QString getRepeatFlag() const { return _repeatString; } - void setRepeatFlag(QString value) { _repeatString = value; } + QString getRepeatFlag() const { return _repeatString; } + void setRepeatFlag(QString value) { _repeatString = value; } - bool getRepeatTimeout() const { return _repeatTimeout; } - void setRepeatTimeout(bool value) { _repeatTimeout = value; } + bool getRepeatTimeout() const { return _repeatTimeout; } + void setRepeatTimeout(bool value) { _repeatTimeout = value; } - int getExpireTimeout() const { return _expireTimeout; } - void setExpireTimeout(int value) { _expireTimeout = value; } + int getExpireTimeout() const { return _expireTimeout; } + void setExpireTimeout(int value) { _expireTimeout = value; } - bool getEnableFlag() const { return _enableFlag; } - void setEnableFlag(bool value) { _enableFlag = value; } + bool getEnableFlag() const { return _enableFlag; } + void setEnableFlag(bool value) { _enableFlag = value; } - void saveState(QSettings* settings) const; - void restoreState(QSettings* settings); - QString parseNotifyMessage(); + void saveState(QSettings* settings) const; + void restoreState(QSettings* settings); - QTimer* timer; - QTimer* expireTimer; - bool isNowPlaying; // - bool firstStart; + QString parseNotifyMessage(); + + QTimer* getTimer() const { return _timer; } + void startTimer(int value); + void stopTimer(); + void disposeTimer(); + + QTimer* getExpireTimer() const { return _expireTimer; } + void startExpireTimer(); + void stopExpireTimer(); + + void disposeExpireTimer(); + + bool isNowPlaying; + bool firstStart; private: + void checkSoundFilesExisting(); - QStringList _messageSequence; +private: + QTimer* _timer; - //! path to folder with sound files - QString _soundCollectionPath; + //! time from putting notification in queue till moment when notification became out-of-date + //! NOTE: each notification has it lifetime, this time setups individually for each notification + //! according to its priority + QTimer* _expireTimer; - //! language in what notifications will be spelled - QString _currentLanguage; - //! one UAV object per one notification - QString _dataObject; - //! one field value change can be assigned to one notification - QString _objectField; + QStringList _messageSequence; - //! poled UAV field value - QString _dataValue; + //! path to folder with sound files + QString _soundCollectionPath; - //! possible sounds(at least one required to play notification) - QString _sound1; - QString _sound2; - QString _sound3; + //! language in what notifications will be spelled + QString _currentLanguage; - //! order in what sounds 1-3 will be played - QString _sayOrder; + //! one UAV object per one notification + QString _dataObject; - double _spinBoxValue; + //! one field value change can be assigned to one notification + QString _objectField; - QString _repeatString; + //! poled UAV field value + QString _dataValue; - //! time when next notification must be fired - bool _repeatTimeout; + //! possible sounds(at least one required to play notification) + QString _sound1; + QString _sound2; + QString _sound3; - //! how often or what periodicaly notification should be played - int _repeatTimerValue; + //! order in what sounds 1-3 will be played + QString _sayOrder; - //! time after event occured till notification became invalid - //! and will be removed from list - int _expireTimeout; + double _spinBoxValue; - //! enables/disables playing of current notification - bool _enableFlag; + QString _repeatString; + + //! time when next notification must be fired + bool _repeatTimeout; + + //! how often or what periodicaly notification should be played + int _repeatTimerValue; + + //! time after event occured till notification became invalid + //! and will be removed from list + int _expireTimeout; + + //! enables/disables playing of current notification + bool _enableFlag; }; Q_DECLARE_METATYPE(NotificationItem*) diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 8d5cb25e3..69f085620 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -25,219 +25,277 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "NotificationItem.h" +#include "notificationitem.h" +#include "notifylogging.h" #include #include #include "utils/pathutils.h" -NotificationItem::NotificationItem(QObject *parent) : - QObject(parent), - isNowPlaying(0), - firstStart(1), - _soundCollectionPath(""), - _currentLanguage("default"), - _dataObject(""), - _objectField(""), - _dataValue("Equal to"), - _sound1(""), - _sound2(""), - _sound3(""), - _sayOrder("Never"), - _spinBoxValue(0), - _repeatString("Repeat Instantly"), - _repeatTimeout(true), - _expireTimeout(15) +NotificationItem::NotificationItem(QObject *parent) + : QObject(parent) + , isNowPlaying(0) + , firstStart(true) + , _soundCollectionPath("") + , _currentLanguage("default") + , _dataObject("") + , _objectField("") + , _dataValue("Equal to") + , _sound1("") + , _sound2("") + , _sound3("") + , _sayOrder("Never") + , _spinBoxValue(0) + , _repeatString("Repeat Instantly") + , _repeatTimeout(true) + , _expireTimeout(15) { - timer = NULL; - expireTimer = NULL; + _timer = NULL; + _expireTimer = NULL; } void NotificationItem::copyTo(NotificationItem* that) const { - - that->isNowPlaying = isNowPlaying; - that->firstStart = firstStart; - that->_soundCollectionPath = _soundCollectionPath; - that->_currentLanguage = _currentLanguage; - that->_soundCollectionPath = _soundCollectionPath; - that->_dataObject = _dataObject; - that->_objectField = _objectField; - that->_dataValue = _dataValue; - that->_sound1 = _sound1; - that->_sound2 = _sound2; - that->_sound3 = _sound3; - that->_sayOrder = _sayOrder; - that->_spinBoxValue = _spinBoxValue; - that->_repeatString = _repeatString; - that->_repeatTimeout = _repeatTimeout; - that->_expireTimeout = _expireTimeout; + that->isNowPlaying = isNowPlaying; + that->firstStart = firstStart; + that->_soundCollectionPath = _soundCollectionPath; + that->_currentLanguage = _currentLanguage; + that->_soundCollectionPath = _soundCollectionPath; + that->_dataObject = _dataObject; + that->_objectField = _objectField; + that->_dataValue = _dataValue; + that->_sound1 = _sound1; + that->_sound2 = _sound2; + that->_sound3 = _sound3; + that->_sayOrder = _sayOrder; + that->_spinBoxValue = _spinBoxValue; + that->_repeatString = _repeatString; + that->_repeatTimeout = _repeatTimeout; + that->_expireTimeout = _expireTimeout; } void NotificationItem::saveState(QSettings* settings) const { - settings->setValue("SoundCollectionPath", Utils::PathUtils().RemoveDataPath(getSoundCollectionPath())); - settings->setValue(QLatin1String("CurrentLanguage"), getCurrentLanguage()); - settings->setValue(QLatin1String("ObjectField"), getObjectField()); - settings->setValue(QLatin1String("DataObject"), getDataObject()); - settings->setValue(QLatin1String("Value"), getValue()); - settings->setValue(QLatin1String("ValueSpinBox"), getSpinBoxValue()); - settings->setValue(QLatin1String("Sound1"), getSound1()); - settings->setValue(QLatin1String("Sound2"), getSound2()); - settings->setValue(QLatin1String("Sound3"), getSound3()); - settings->setValue(QLatin1String("SayOrder"), getSayOrder()); - settings->setValue(QLatin1String("Repeat"), getRepeatFlag()); - settings->setValue(QLatin1String("ExpireTimeout"), getExpireTimeout()); + settings->setValue("SoundCollectionPath", Utils::PathUtils().RemoveDataPath(getSoundCollectionPath())); + settings->setValue(QLatin1String("CurrentLanguage"), getCurrentLanguage()); + settings->setValue(QLatin1String("ObjectField"), getObjectField()); + settings->setValue(QLatin1String("DataObject"), getDataObject()); + settings->setValue(QLatin1String("Value"), getValue()); + settings->setValue(QLatin1String("ValueSpinBox"), getSpinBoxValue()); + settings->setValue(QLatin1String("Sound1"), getSound1()); + settings->setValue(QLatin1String("Sound2"), getSound2()); + settings->setValue(QLatin1String("Sound3"), getSound3()); + settings->setValue(QLatin1String("SayOrder"), getSayOrder()); + settings->setValue(QLatin1String("Repeat"), getRepeatFlag()); + settings->setValue(QLatin1String("ExpireTimeout"), getExpireTimeout()); } void NotificationItem::restoreState(QSettings* settings) { - //settings = Core::ICore::instance()->settings(); - setSoundCollectionPath(Utils::PathUtils().InsertDataPath(settings->value(QLatin1String("SoundCollectionPath"), tr("")).toString())); - setCurrentLanguage(settings->value(QLatin1String("CurrentLanguage"), tr("")).toString()); - setDataObject(settings->value(QLatin1String("DataObject"), tr("")).toString()); - setObjectField(settings->value(QLatin1String("ObjectField"), tr("")).toString()); - setValue(settings->value(QLatin1String("Value"), tr("")).toString()); - setSound1(settings->value(QLatin1String("Sound1"), tr("")).toString()); - setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); - setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); - setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); - setSpinBoxValue(settings->value(QLatin1String("ValueSpinBox"), tr("")).toDouble()); - setRepeatFlag(settings->value(QLatin1String("Repeat"), tr("")).toString()); - setExpireTimeout(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); + //settings = Core::ICore::instance()->settings(); + setSoundCollectionPath(Utils::PathUtils().InsertDataPath(settings->value(QLatin1String("SoundCollectionPath"), tr("")).toString())); + setCurrentLanguage(settings->value(QLatin1String("CurrentLanguage"), tr("")).toString()); + setDataObject(settings->value(QLatin1String("DataObject"), tr("")).toString()); + setObjectField(settings->value(QLatin1String("ObjectField"), tr("")).toString()); + setValue(settings->value(QLatin1String("Value"), tr("")).toString()); + setSound1(settings->value(QLatin1String("Sound1"), tr("")).toString()); + setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); + setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); + setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); + setSpinBoxValue(settings->value(QLatin1String("ValueSpinBox"), tr("")).toDouble()); + setRepeatFlag(settings->value(QLatin1String("Repeat"), tr("")).toString()); + setExpireTimeout(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); } +void NotificationItem::startTimer(int value) { + if (!_timer) { + _timer = new QTimer(this); + _timer->setInterval(value); + } + if (!_timer->isActive()) + _timer->start(); +} + +void NotificationItem::stopTimer() { + if (_timer) { + if (_timer->isActive()) + _timer->stop(); + } +} + +void NotificationItem::disposeTimer() { + if (_timer) { + _timer->stop(); + delete _timer; + _timer = NULL; + } +} + +void NotificationItem::startExpireTimer() { + if (!_expireTimer) + { + _expireTimer = new QTimer(this); + } + _expireTimer->start(_expireTimeout * 1000); +} + +void NotificationItem::stopExpireTimer() { + if (_expireTimer) { + if (_expireTimer) + _expireTimer->stop(); + } +} + +void NotificationItem::disposeExpireTimer() { + if (_expireTimer) { + _expireTimer->stop(); + delete _expireTimer; + _expireTimer = NULL; + } +} + QString NotificationItem::parseNotifyMessage() { - // tips: - // check of *.wav files exist needed for playing phonon queues; - // if phonon player don't find next file in queue, it buzz + // tips: + // check of *.wav files exist needed for playing phonon queues; + // if phonon player don't find next file in queue, it buzz - QString str,str1; - str1= getSayOrder(); - str = QString("%L1 ").arg(getSpinBoxValue()); - int position = 0xFF; - // generate queue of sound files to play - _messageSequence.clear(); + QString str,str1; + str1= getSayOrder(); + str = QString("%L1 ").arg(getSpinBoxValue()); + int position = 0xFF; + // generate queue of sound files to play + _messageSequence.clear(); - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav")); - else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav")); + checkSoundFilesExisting(); - if("" != getSound2()) - { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav")); - else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav")); - } + if(!_messageSequence.size()) { + qNotifyDebug() << "no any files in message queue"; + } - if("" != getSound3()) - { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav")); - else - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav")); - } + switch(str1.at(0).toAscii()) + { + case 'N'://NEVER: + str = getSound1()+" "+getSound2()+" "+getSound3(); + position = 0xFF; + break; - switch(str1.at(0).toAscii()) - { - case 'N'://NEVER: - str = getSound1()+" "+getSound2()+" "+getSound3(); - position = 0xFF; - break; + case 'B'://BEFORE: + str = QString("%L1 ").arg(getSpinBoxValue())+getSound1()+" "+getSound2()+" "+getSound3(); + position = 0; + break; - case 'B'://BEFORE: - str = QString("%L1 ").arg(getSpinBoxValue())+getSound1()+" "+getSound2()+" "+getSound3(); - position = 0; - break; + case 'A'://AFTER: + switch(str1.at(6).toAscii()) + { + case 'f': + str = getSound1()+QString(" %L1 ").arg(getSpinBoxValue())+getSound2()+" "+getSound3(); + position = 1; + break; + case 's': + str = getSound1()+" "+getSound2()+QString(" %L1").arg(getSpinBoxValue())+" "+getSound3(); + position = 2; + break; + case 't': + str = getSound1()+" "+getSound2()+" "+getSound3()+QString(" %L1").arg(getSpinBoxValue()); + position = 3; + break; + } + break; + } - case 'A'://AFTER: - switch(str1.at(6).toAscii()) - { - case 'f': - str = getSound1()+QString(" %L1 ").arg(getSpinBoxValue())+getSound2()+" "+getSound3(); - position = 1; - break; - case 's': - str = getSound1()+" "+getSound2()+QString(" %L1").arg(getSpinBoxValue())+" "+getSound3(); - position = 2; - break; - case 't': - str = getSound1()+" "+getSound2()+" "+getSound3()+QString(" %L1").arg(getSpinBoxValue()); - position = 3; - break; - } - break; - } + if(position != 0xFF) + { + QStringList numberParts = QString("%1").arg(getSpinBoxValue()).trimmed().split("."); + QStringList numberFiles; - if(position != 0xFF) - { - QStringList numberParts = QString("%1").arg(getSpinBoxValue()).trimmed().split("."); - QStringList numberFiles; + if((numberParts.at(0).size()==1) || (numberParts.at(0).toInt()<20)) + { + //if(numberParts.at(0)!="0") + numberFiles.append(numberParts.at(0)); + } else { + int i=0; + if(numberParts.at(0).right(2).toInt()<20 && numberParts.at(0).right(2).toInt()!=0) { + if(numberParts.at(0).right(2).toInt()<10) + numberFiles.append(numberParts.at(0).right(1)); + else + numberFiles.append(numberParts.at(0).right(2)); + i=2; + } + for(;i #include "notifyitemdelegate.h" #include "notifytablemodel.h" - +#include "notifylogging.h" NotifyItemDelegate::NotifyItemDelegate(QStringList items, QObject* parent) - : QItemDelegate(parent) - , _parent(parent) - , _items(items) + : QItemDelegate(parent) + , _parent(parent) + , _items(items) { } -QWidget *NotifyItemDelegate::createEditor(QWidget* parent, - const QStyleOptionViewItem& /*none*/, - const QModelIndex& index) const +QWidget *NotifyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& /*none*/, + const QModelIndex& index) const { - if(eREPEAT_VALUE == index.column()) { - QComboBox* editor = new QComboBox(parent); - editor->clear(); - editor->addItems(_items); - return editor; - } else { - if(eEXPIRE_TIME == index.column()) { - QSpinBox* editor = new QSpinBox(parent); - connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); - return editor; - } else { - if(eENABLE_NOTIFICATION == index.column()) { - QCheckBox* editor = new QCheckBox(parent); - connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); - return editor; - } - } - } - QLineEdit *editor = new QLineEdit(parent); - return editor; + if (eREPEAT_VALUE == index.column()) { + QComboBox* editor = new QComboBox(parent); + editor->clear(); + editor->addItems(_items); + return editor; + } else { + if (eEXPIRE_TIME == index.column()) { + QSpinBox* editor = new QSpinBox(parent); + connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); + return editor; + } else { + if (eENABLE_NOTIFICATION == index.column()) { + QCheckBox* editor = new QCheckBox(parent); + connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); + return editor; + } + } + } + QLineEdit *editor = new QLineEdit(parent); + return editor; } void NotifyItemDelegate::commitAndCloseEditor() { - QLineEdit* editor = qobject_cast(sender()); - if (editor) { - emit commitData(editor); - emit closeEditor(editor); - } else { - QComboBox* editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - } else { - QSpinBox* editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - } else { - QCheckBox* editor = qobject_cast(sender()); - if (editor) - { - emit commitData(editor); - emit closeEditor(editor); - } - } - } - } + QLineEdit* editor = qobject_cast(sender()); + if (editor) { + emit commitData(editor); + emit closeEditor(editor); + } else { + QComboBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } else { + QSpinBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } else { + QCheckBox* editor = qobject_cast(sender()); + if (editor) + { + emit commitData(editor); + emit closeEditor(editor); + } + } + } + } } void NotifyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { - QLineEdit* edit = qobject_cast(editor); - if(edit) { - edit->setText(index.model()->data(index, Qt::EditRole).toString()); - } else { - QComboBox* repeatEditor = qobject_cast(editor); - if(repeatEditor) - repeatEditor->setCurrentIndex(repeatEditor->findText(index.model()->data(index, Qt::EditRole).toString())); - else { - QSpinBox* expireEditor = qobject_cast(editor); - if(expireEditor) - expireEditor->setValue(index.model()->data(index, Qt::EditRole).toInt()); - else { - QCheckBox* enablePlayEditor = qobject_cast(editor); - if (enablePlayEditor) - enablePlayEditor->setChecked(index.model()->data(index, Qt::EditRole).toBool()); - } - } - } + QLineEdit* edit = qobject_cast(editor); + if (edit) { + edit->setText(index.model()->data(index, Qt::EditRole).toString()); + } else { + QComboBox* repeatEditor = qobject_cast(editor); + if (repeatEditor) + repeatEditor->setCurrentIndex(repeatEditor->findText(index.model()->data(index, Qt::EditRole).toString())); + else { + QSpinBox* expireEditor = qobject_cast(editor); + if (expireEditor) + expireEditor->setValue(index.model()->data(index, Qt::EditRole).toInt()); + else { + QCheckBox* enablePlayEditor = qobject_cast(editor); + if (enablePlayEditor) + enablePlayEditor->setChecked(index.model()->data(index, Qt::EditRole).toBool()); + } + } + } } void NotifyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { - QLineEdit *edit = qobject_cast(editor); - if(edit) { - model->setData(index, edit->text()); - } else { - QComboBox * repeatEditor = qobject_cast(editor); - if(repeatEditor) { - model->setData(index, repeatEditor->currentText()); - } else { - QSpinBox * expireEditor = qobject_cast(editor); - if(expireEditor) { - model->setData(index, expireEditor->value(), Qt::EditRole); - } else { - QCheckBox* enablePlayEditor = qobject_cast(editor); - if (enablePlayEditor) { - model->setData(index, enablePlayEditor->isChecked(), Qt::EditRole); - } - } - } - } + QLineEdit *edit = qobject_cast(editor); + if (edit) { + model->setData(index, edit->text()); + } else { + QComboBox * repeatEditor = qobject_cast(editor); + if (repeatEditor) { + model->setData(index, repeatEditor->currentText()); + } else { + QSpinBox * expireEditor = qobject_cast(editor); + if (expireEditor) { + model->setData(index, expireEditor->value(), Qt::EditRole); + } else { + QCheckBox* enablePlayEditor = qobject_cast(editor); + if (enablePlayEditor) { + model->setData(index, enablePlayEditor->isChecked(), Qt::EditRole); + } + } + } + } } -void NotifyItemDelegate::selectRow(const QString & text) +void NotifyItemDelegate::selectRow(const QString& text) { - QComboBox* combo = qobject_cast(sender()); - QTableWidget* table = new QTableWidget; - table = (QTableWidget*)(combo->parent()); + QComboBox* combo = qobject_cast(sender()); + QTableWidget* table = new QTableWidget; + table = (QTableWidget*)(combo->parent()); - qDebug() << table->columnCount(); - qDebug() << table->rowCount(); - qDebug() << table->currentRow(); + qNotifyDebug() << table->columnCount(); + qNotifyDebug() << table->rowCount(); + qNotifyDebug() << table->currentRow(); } -QSize NotifyItemDelegate::sizeHint(const QStyleOptionViewItem & option, - const QModelIndex & index) const +QSize NotifyItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { - QSize s = QItemDelegate::sizeHint(option, index); - s.setHeight(10); - return s; + QSize s = QItemDelegate::sizeHint(option, index); + s.setHeight(10); + return s; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp new file mode 100644 index 000000000..616b2ada5 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp @@ -0,0 +1,42 @@ +/** + ****************************************************************************** + * + * @file notifylogging.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Uses to logging only inside notify plugin, + * can be convinient turned on/off + * @see The GNU Public License (GPL) Version 3 + * @defgroup notifyplugin + * @{ + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "notifylogging.h" + +#ifdef DEBUG_NOTIFIES +QDebug qNotifyDebug() +#endif +#ifndef DEBUG_NOTIFIES +QNoDebug qNotifyDebug() +#endif +{ +#ifdef DEBUG_NOTIFIES + return qDebug(); +#endif + return QNoDebug(); +} diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.h b/ground/openpilotgcs/src/plugins/notify/notifylogging.h new file mode 100644 index 000000000..bf02b86df --- /dev/null +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.h @@ -0,0 +1,42 @@ +/** + ****************************************************************************** + * + * @file notifylogging.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Uses to logging only inside notify plugin, + * can be convinient turned on/off + * @see The GNU Public License (GPL) Version 3 + * @defgroup notifyplugin + * @{ + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NOTIFYLOGGING_H +#define NOTIFYLOGGING_H + +#include "QDebug.h" + +#ifdef DEBUG_NOTIFIES +QDebug qNotifyDebug(); +#endif +#ifndef DEBUG_NOTIFIES +QNoDebug qNotifyDebug(); +#endif + + +#endif // NOTIFYLOGGING_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index c959925b4..9eef49dec 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -28,6 +28,7 @@ #include "notifyplugin.h" #include "notificationitem.h" #include "notifypluginoptionspage.h" +#include "notifylogging.h" #include #include #include @@ -43,18 +44,6 @@ static const QString VERSION = "1.0.0"; //#define DEBUG_NOTIFIES -#ifdef DEBUG_NOTIFIES -QDebug qNotifyDebug() -#endif -#ifndef DEBUG_NOTIFIES -QNoDebug qNotifyDebug() -#endif -{ -#ifdef DEBUG_NOTIFIES - return qDebug(); -#endif - return QNoDebug(); -} SoundNotifyPlugin::SoundNotifyPlugin() { @@ -84,15 +73,15 @@ bool SoundNotifyPlugin::initialize(const QStringList& args, QString *errMsg) void SoundNotifyPlugin::extensionsInitialized() { - Core::ICore::instance()->readSettings(this); - if ( !configured ){ - readConfig_0_0_0(); - } + Core::ICore::instance()->readSettings(this); + if ( !configured ){ + readConfig_0_0_0(); + } - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); - removedNotifies.clear(); - connectNotifications(); + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); + removedNotifies.clear(); + connectNotifications(); } void SoundNotifyPlugin::saveConfig( QSettings* settings, UAVConfigInfo *configInfo){ @@ -147,39 +136,39 @@ void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo *configIn void SoundNotifyPlugin::readConfig_0_0_0(){ - settings = Core::ICore::instance()->settings(); - settings->beginGroup(QLatin1String("NotifyPlugin")); + settings = Core::ICore::instance()->settings(); + settings->beginGroup(QLatin1String("NotifyPlugin")); - settings->beginReadArray("Current"); - settings->setArrayIndex(0); - currentNotification.restoreState(settings); - settings->endArray(); + settings->beginReadArray("Current"); + settings->setArrayIndex(0); + currentNotification.restoreState(settings); + settings->endArray(); - // read list of notifications from settings - int size = settings->beginReadArray("listNotifies"); - for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); - NotificationItem* notification = new NotificationItem; - notification->restoreState(settings); - lstNotifications.append(notification); - } - settings->endArray(); - setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); - settings->endGroup(); - - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); - removedNotifies.clear(); - connectNotifications(); - - configured = true; - } + // read list of notifications from settings + int size = settings->beginReadArray("listNotifies"); + for (int i = 0; i < size; ++i) { + settings->setArrayIndex(i); + NotificationItem* notification = new NotificationItem; + notification->restoreState(settings); + lstNotifications.append(notification); + } + settings->endArray(); + setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); + settings->endGroup(); + + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); + removedNotifies.clear(); + connectNotifications(); + + configured = true; +} void SoundNotifyPlugin::onTelemetryManagerAdded(QObject* obj) { - telMngr = qobject_cast(obj); - if(telMngr) - connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect())); + telMngr = qobject_cast(obj); + if (telMngr) + connect(telMngr, SIGNAL(disconnected()), this, SLOT(onAutopilotDisconnect())); } void SoundNotifyPlugin::shutdown() @@ -189,86 +178,76 @@ void SoundNotifyPlugin::shutdown() void SoundNotifyPlugin::onAutopilotDisconnect() { - connectNotifications(); + connectNotifications(); } /*! - clear any notify timers from previous flight; - reset will be perform on start of option page + clear any notify timers from previous flight; + reset will be perform on start of option page */ void SoundNotifyPlugin::resetNotification(void) { - //first, reject empty args and unknown fields. - foreach(NotificationItem* notify,lstNotifications) { - if(notify->timer) - { - disconnect(notify->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); - notify->timer->stop(); - delete notify->timer; - notify->timer = NULL; - } - if(notify->expireTimer) - { - disconnect(notify->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); - notify->expireTimer->stop(); - delete notify->expireTimer; - notify->expireTimer = NULL; - } - } + //first, reject empty args and unknown fields. + foreach(NotificationItem* ntf, lstNotifications) { + ntf->disposeTimer(); + disconnect(ntf->getTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); + ntf->disposeExpireTimer(); + disconnect(ntf->getExpireTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); + } } /*! - update list of notifies; - will be perform on OK or APPLY press of option page + update list of notifies; + will be perform on OK or APPLY press of option page */ void SoundNotifyPlugin::updateNotificationList(QList list) { - removedNotifies.clear(); - resetNotification(); - lstNotifications.clear(); - lstNotifications=list; - connectNotifications(); + removedNotifies.clear(); + resetNotification(); + lstNotifications.clear(); + lstNotifications=list; + connectNotifications(); - Core::ICore::instance()->saveSettings(this); + Core::ICore::instance()->saveSettings(this); } void SoundNotifyPlugin::connectNotifications() { - foreach(UAVDataObject* obj,lstNotifiedUAVObjects) { - if (obj != NULL) - disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(appendNotification(UAVObject*))); - } - if(phonon.mo != NULL) { - delete phonon.mo; - phonon.mo = NULL; - } + foreach(UAVDataObject* obj,lstNotifiedUAVObjects) { + if (obj != NULL) + disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(appendNotification(UAVObject*))); + } + if (phonon.mo != NULL) { + delete phonon.mo; + phonon.mo = NULL; + } - if(!enableSound) return; + if (!enableSound) return; - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); - lstNotifiedUAVObjects.clear(); - pendingNotifications.clear(); - lstNotifications.append(removedNotifies); - removedNotifies.clear(); + lstNotifiedUAVObjects.clear(); + pendingNotifications.clear(); + lstNotifications.append(removedNotifies); + removedNotifies.clear(); - //first, reject empty args and unknown fields. - foreach(NotificationItem* notify, lstNotifications) { - notify->firstStart=true; - notify->isNowPlaying=false; + //first, reject empty args and unknown fields. + foreach(NotificationItem* notify, lstNotifications) { + notify->firstStart=true; + notify->isNowPlaying=false; - UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); - if (obj != NULL ) { - if(!lstNotifiedUAVObjects.contains(obj)) { - lstNotifiedUAVObjects.append(obj); - connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); - } - } else - std::cout << "Error: Object is unknown (" << notify->getDataObject().toStdString() << ")." << std::endl; - } + UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); + if (obj != NULL ) { + if (!lstNotifiedUAVObjects.contains(obj)) { + lstNotifiedUAVObjects.append(obj); + connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + } + } else + std::cout << "Error: Object is unknown (" << notify->getDataObject().toStdString() << ")." << std::endl; + } - if(lstNotifications.isEmpty()) return; + if (lstNotifications.isEmpty()) return; // set notification message to current event phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory); phonon.mo->clearQueue(); @@ -284,80 +263,73 @@ void SoundNotifyPlugin::connectNotifications() void SoundNotifyPlugin::appendNotification(UAVObject *object) { - disconnect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + disconnect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); - foreach(NotificationItem* notification, lstNotifications) { - if(object->getName()!=notification->getDataObject()) - continue; + foreach(NotificationItem* ntf, lstNotifications) { + if (object->getName() != ntf->getDataObject()) + continue; - if(nowPlayingConfiguration == notification) - continue; + if (nowPlayingConfiguration == ntf) + continue; - if(notification->getRepeatFlag()!= "Repeat Instantly" && - notification->getRepeatFlag()!= "Repeat Once" && !notification->firstStart) - continue; + if (ntf->getRepeatFlag()!= "Repeat Instantly" && + ntf->getRepeatFlag()!= "Repeat Once" && !ntf->firstStart) + continue; - checkNotificationRule(notification,object); - } - connect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + checkNotificationRule(ntf,object); + } + connect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); } void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) { - bool condition=false; - double threshold; - QString direction; - QString fieldName; - threshold = notification->getSpinBoxValue(); - direction = notification->getValue(); - fieldName = notification->getObjectField(); - UAVObjectField* field = object->getField(fieldName); - if (field->getName()!="") { - double value = field->getDouble(); + bool condition=false; + double threshold; + QString direction; + QString fieldName; + threshold = notification->getSpinBoxValue(); + direction = notification->getValue(); + fieldName = notification->getObjectField(); + UAVObjectField* field = object->getField(fieldName); + if (field->getName()!="") { + double value = field->getDouble(); - switch(direction[0].toAscii()) - { - case 'E': - if(value==threshold) - condition = true; - break; - case 'G': - if(value>threshold) - condition = true; - break; - case 'L': - if(valuethreshold) + condition = true; + break; + case 'L': + if (valuetimer) - if(notification->timer->isActive()) - notification->timer->stop(); -#ifdef DEBUG_NOTIFIES - qDebug() << "add to pending list - " << notification->parseNotifyMessage(); -#endif - // if audio is busy, start expiration timer - //ms = (notification->getExpiredTimeout()[in sec])*1000 - //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); - pendingNotifications.append(notification); - if(!notification->expireTimer) - { - notification->expireTimer = new QTimer(notification); - connect(notification->expireTimer, SIGNAL(timeout()), this, SLOT(expireTimerHandler())); - } - notification->expireTimer->start(notification->getExpireTimeout()*1000); - } - } - } + if (condition) + { + if (!playNotification(notification)) + { + if (!pendingNotifications.contains(notification)) + { + notification->stopTimer(); + + qNotifyDebug() << "add to pending list - " << notification->parseNotifyMessage(); + // if audio is busy, start expiration timer + //ms = (notification->getExpiredTimeout()[in sec])*1000 + //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); + pendingNotifications.append(notification); + notification->startExpireTimer(); + connect(notification->getExpireTimer(), SIGNAL(timeout()), this, SLOT(expireTimerHandler())); + } + } + } } bool SoundNotifyPlugin::playNotification(NotificationItem* notification) @@ -366,132 +338,112 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) if (phonon.mo == NULL) return false; - if(!notification->getEnableFlag()) return true; + if (!notification->getEnableFlag()) return true; -#ifdef DEBUG_NOTIFIES - qDebug() << "Phonon State: " << phonon.mo->state(); -#endif - if((phonon.mo->state()==Phonon::PausedState) - || (phonon.mo->state()==Phonon::StoppedState) - || phonon.firstPlay) - { - // don't fire expire timer - nowPlayingConfiguration = notification; - if(notification->expireTimer) - notification->expireTimer->stop(); + qNotifyDebug() << "Phonon State: " << phonon.mo->state(); + if ((phonon.mo->state()==Phonon::PausedState) + || (phonon.mo->state()==Phonon::StoppedState) + || phonon.firstPlay) + { + // don't fire expire timer + nowPlayingConfiguration = notification; + notification->stopExpireTimer(); - if(notification->getRepeatFlag()=="Repeat Once") - { - removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); - } - else { - if(notification->getRepeatFlag()!="Repeat Instantly") - { - QRegExp rxlen("(\\d+)"); - QString value; - int timer_value; - int pos = rxlen.indexIn(notification->getRepeatFlag()); - if (pos > -1) { - value = rxlen.cap(1); // "189" - timer_value = (value.toInt()+8)*1000; //ms*1000 + average duration of meassage - } + if (notification->getRepeatFlag()=="Repeat Once") { + removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); + } else { + if (notification->getRepeatFlag()!="Repeat Instantly") + { + QRegExp rxlen("(\\d+)"); + QString value; + int timer_value; + int pos = rxlen.indexIn(notification->getRepeatFlag()); + if (pos > -1) { + value = rxlen.cap(1); // "189" + timer_value = (value.toInt()+8)*1000; //ms*1000 + average duration of meassage + } - if(!notification->timer) - { - notification->timer = new QTimer(notification); - notification->timer->setInterval(timer_value); - connect(notification->timer, SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); - } - if(!notification->timer->isActive()) - notification->timer->start(); - } - } - notification->firstStart=false; - phonon.mo->clear(); - QString str = notification->parseNotifyMessage(); - qNotifyDebug() << "play notification - " << str; + notification->startTimer(timer_value); + connect(notification->getTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); + } + } + notification->firstStart=false; + phonon.mo->clear(); + QString str = notification->parseNotifyMessage(); + qNotifyDebug() << "play notification - " << str; + foreach (QString item, notification->getMessageSequence()) { + Phonon::MediaSource *ms = new Phonon::MediaSource(item); + ms->setAutoDelete(true); + phonon.mo->enqueue(*ms); + } + phonon.mo->play(); + phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before + // the state is not "Loading" anymore. + } + else + return false; // if audio is busy - foreach(QString item, notification->getMessageSequence()) { - Phonon::MediaSource *ms = new Phonon::MediaSource(item); - ms->setAutoDelete(true); - phonon.mo->enqueue(*ms); - } - phonon.mo->play(); - phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before - // the state is not "Loading" anymore. - } - else - return false; // if audio is busy - - return true; + return true; } void SoundNotifyPlugin::repeatTimerHandler() { NotificationItem* notification = static_cast(sender()->parent()); -#ifdef DEBUG_NOTIFIES - qDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); -#endif - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + + qNotifyDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); + + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); UAVObject* object = objManager->getObject(notification->getDataObject()); - if(object) + if (object) checkNotificationRule(notification,object); } void SoundNotifyPlugin::expireTimerHandler() { - // fire expire timer - NotificationItem* notification = static_cast(sender()->parent()); - notification->expireTimer->stop(); + // fire expire timer + NotificationItem* notification = static_cast(sender()->parent()); + notification->stopExpireTimer(); - if(!pendingNotifications.isEmpty()) - { -#ifdef DEBUG_NOTIFIES - qDebug() << "expireTimerHandler - " << notification->parseNotifyMessage(); -#endif - pendingNotifications.removeOne(notification); - } + if (!pendingNotifications.isEmpty()) { + qNotifyDebug() << "expireTimerHandler - " << notification->parseNotifyMessage(); + pendingNotifications.removeOne(notification); + } } void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldstate) { Q_UNUSED(oldstate) -#ifdef DEBUG_NOTIFIES - qDebug() << "File length (ms): " << phonon.mo->totalTime(); - qDebug() << "New State: " << newstate; -#endif + qNotifyDebug() << "File length (ms): " << phonon.mo->totalTime(); + qNotifyDebug() << "New State: " << newstate; #ifndef Q_OS_WIN - // This is a hack to force Linux to wait until the end of the - // wav file before moving to the next in the queue. - // I wish I did not have to go through a #define, but I did not - // manage to make this work on both platforms any other way! - if (phonon.mo->totalTime()>0) - phonon.mo->setTransitionTime(phonon.mo->totalTime()); + // This is a hack to force Linux to wait until the end of the + // wav file before moving to the next in the queue. + // I wish I did not have to go through a #define, but I did not + // manage to make this work on both platforms any other way! + if (phonon.mo->totalTime()>0) + phonon.mo->setTransitionTime(phonon.mo->totalTime()); #endif - if((newstate == Phonon::PausedState) || - (newstate == Phonon::StoppedState)) - { - nowPlayingConfiguration=NULL; - if(!pendingNotifications.isEmpty()) - { - NotificationItem* notification = pendingNotifications.takeFirst(); -#ifdef DEBUG_NOTIFIES - qDebug() << "play audioFree - " << notification->parseNotifyMessage(); -#endif - playNotification(notification); - } - } else if (newstate == Phonon::ErrorState) - { - if(phonon.mo->errorType()==0) { - qDebug() << "Phonon::ErrorState: ErrorType = " << phonon.mo->errorType(); - phonon.mo->clearQueue(); - } - } -// if(newstate == Phonon::BufferingState) -// qDebug() << "Phonon::BufferingState!!!"; + if ((newstate == Phonon::PausedState) || + (newstate == Phonon::StoppedState)) + { + nowPlayingConfiguration=NULL; + if (!pendingNotifications.isEmpty()) + { + NotificationItem* notification = pendingNotifications.takeFirst(); + qNotifyDebug() << "play audioFree - " << notification->parseNotifyMessage(); + playNotification(notification); + } + } else { + if (newstate == Phonon::ErrorState) { + if (phonon.mo->errorType()==0) { + qDebug() << "Phonon::ErrorState: ErrorType = " << phonon.mo->errorType(); + phonon.mo->clearQueue(); + } + } + } } Q_EXPORT_PLUGIN(SoundNotifyPlugin) diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h index c1e0ce620..1d9475469 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h @@ -49,7 +49,6 @@ typedef struct { } PhononObject, *pPhononObject; - class SoundNotifyPlugin : public Core::IConfigurablePlugin { Q_OBJECT diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index cee9a4027..caad0efff 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -64,68 +64,67 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) //main widget QWidget *optionsPageWidget = new QWidget; //main layout - options_page->setupUi(optionsPageWidget); + options_page->setupUi(optionsPageWidget); - delegateItems.clear(); - listSoundFiles.clear(); + delegateItems.clear(); + listSoundFiles.clear(); - delegateItems << "Repeat Once" - << "Repeat Instantly" - << "Repeat 10 seconds" - << "Repeat 30 seconds" - << "Repeat 1 minute"; + delegateItems << "Repeat Once" + << "Repeat Instantly" + << "Repeat 10 seconds" + << "Repeat 30 seconds" + << "Repeat 1 minute"; - options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); - options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); + options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); + options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); - // Fills the combo boxes for the UAVObjects - QList< QList > objList = objManager.getDataObjects(); - foreach (QList list, objList) { - foreach (UAVDataObject* obj, list) { - options_page->UAVObject->addItem(obj->getName()); - } - } + // Fills the combo boxes for the UAVObjects + QList< QList > objList = objManager.getDataObjects(); + foreach (QList list, objList) { + foreach (UAVDataObject* obj, list) { + options_page->UAVObject->addItem(obj->getName()); + } + } - connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); - connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); + connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); + connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); - connect(this, SIGNAL(updateNotifications(QList)), - owner, SLOT(updateNotificationList(QList))); - connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); + connect(this, SIGNAL(updateNotifications(QList)), + owner, SLOT(updateNotificationList(QList))); + //connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); - //emit resetNotification(); - privListNotifications.clear(); + privListNotifications.clear(); - for (int i = 0; i < owner->getListNotifications().size(); ++i) { - NotificationItem* notification = new NotificationItem(); - owner->getListNotifications().at(i)->copyTo(notification); - privListNotifications.append(notification); - } + for (int i = 0; i < owner->getListNotifications().size(); ++i) { + NotificationItem* notification = new NotificationItem(); + owner->getListNotifications().at(i)->copyTo(notification); + privListNotifications.append(notification); + } - updateConfigView(owner->getCurrentNotification()); + updateConfigView(owner->getCurrentNotification()); - initButtons(); - initRulesTableModel(); - initRulesTableView(); - initPhononPlayer(); + initButtons(); + initRulesTableModel(); + initRulesTableView(); + initPhononPlayer(); - return optionsPageWidget; + return optionsPageWidget; } void NotifyPluginOptionsPage::initButtons() { - options_page->chkEnableSound->setChecked(owner->getEnableSound()); - connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); + options_page->chkEnableSound->setChecked(owner->getEnableSound()); + connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - options_page->buttonModify->setEnabled(false); - options_page->buttonDelete->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); - connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); - connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); - connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); + options_page->buttonModify->setEnabled(false); + options_page->buttonDelete->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); + connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); + connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); + connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); } void NotifyPluginOptionsPage::initPhononPlayer() @@ -150,32 +149,32 @@ void NotifyPluginOptionsPage::initRulesTableModel() void NotifyPluginOptionsPage::initRulesTableView() { - options_page->notifyRulesView->setModel(notifyRulesModel.data()); - options_page->notifyRulesView->resizeRowsToContents(); - options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); - options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); + options_page->notifyRulesView->setModel(notifyRulesModel.data()); + options_page->notifyRulesView->resizeRowsToContents(); + options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); + options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); - options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); - options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); - options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); - options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); - options_page->notifyRulesView->setDragEnabled(true); - options_page->notifyRulesView->setAcceptDrops(true); - options_page->notifyRulesView->setDropIndicatorShown(true); + options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); + options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); + options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); + options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); + options_page->notifyRulesView->setDragEnabled(true); + options_page->notifyRulesView->setAcceptDrops(true); + options_page->notifyRulesView->setDropIndicatorShown(true); } void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setSound1(options_page->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); - notification->setSayOrder(options_page->SayOrder->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setSound1(options_page->Sound1->currentText()); + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); + notification->setSayOrder(options_page->SayOrder->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); } @@ -185,19 +184,19 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio */ void NotifyPluginOptionsPage::apply() { - getOptionsPageValues(owner->getCurrentNotification()); - owner->setEnableSound(options_page->chkEnableSound->isChecked()); - emit updateNotifications(privListNotifications); + getOptionsPageValues(owner->getCurrentNotification()); + owner->setEnableSound(options_page->chkEnableSound->isChecked()); + emit updateNotifications(privListNotifications); } void NotifyPluginOptionsPage::finish() { - disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - if (notifySound) { - notifySound->stop(); - notifySound->clear(); - } + disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + if (notifySound) { + notifySound->stop(); + notifySound->clear(); + } } ////////////////////////////////////////////////////////////////////////////// @@ -205,247 +204,247 @@ void NotifyPluginOptionsPage::finish() // combo box ////////////////////////////////////////////////////////////////////////////// void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { - options_page->UAVObjectField->clear(); - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager* objManager = pm->getObject(); + options_page->UAVObjectField->clear(); + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager* objManager = pm->getObject(); UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); QList fieldList = obj->getFields(); foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); + options_page->UAVObjectField->addItem(field->getName()); } } // locate collection folder on disk void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) { - QDir dirPath(path); - listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - options_page->SoundCollectionList->clear(); - options_page->SoundCollectionList->addItems(listDirCollections); + QDir dirPath(path); + listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + options_page->SoundCollectionList->clear(); + options_page->SoundCollectionList->addItems(listDirCollections); } void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) { - options_page->SoundCollectionList->setCurrentIndex(index); + options_page->SoundCollectionList->setCurrentIndex(index); currentCollectionPath = options_page->SoundDirectoryPathChooser->path() + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); - QDir dirPath(currentCollectionPath); - QStringList filters; - filters << "*.mp3" << "*.wav"; - dirPath.setNameFilters(filters); - listSoundFiles = dirPath.entryList(filters); - listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); - options_page->Sound1->clear(); - options_page->Sound2->clear(); - options_page->Sound3->clear(); - options_page->Sound1->addItems(listSoundFiles); - options_page->Sound2->addItem(""); - options_page->Sound2->addItems(listSoundFiles); - options_page->Sound3->addItem(""); - options_page->Sound3->addItems(listSoundFiles); + QDir dirPath(currentCollectionPath); + QStringList filters; + filters << "*.mp3" << "*.wav"; + dirPath.setNameFilters(filters); + listSoundFiles = dirPath.entryList(filters); + listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); + options_page->Sound1->clear(); + options_page->Sound2->clear(); + options_page->Sound3->clear(); + options_page->Sound1->addItems(listSoundFiles); + options_page->Sound2->addItem(""); + options_page->Sound2->addItems(listSoundFiles); + options_page->Sound3->addItem(""); + options_page->Sound3->addItems(listSoundFiles); } void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) { - //Q_ASSERT(Phonon::ErrorState != newstate); + //Q_ASSERT(Phonon::ErrorState != newstate); - if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { - options_page->buttonPlayNotification->setText("Play"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); - } else { - if (newstate == Phonon::PlayingState) { - options_page->buttonPlayNotification->setText("Stop"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); - } - } + if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { + options_page->buttonPlayNotification->setText("Play"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); + } else { + if (newstate == Phonon::PlayingState) { + options_page->buttonPlayNotification->setText("Stop"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + } + } } void NotifyPluginOptionsPage::onFinishedPlaying() { - notifySound->clear(); + notifySound->clear(); } void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() { - NotificationItem* notification = NULL; + NotificationItem* notification = NULL; - if (-1 == notifyRulesSelection->currentIndex().row()) - return; - notifySound->clearQueue(); - notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); - notification->parseNotifyMessage(); - QStringList sequence = notification->getMessageSequence(); - Q_ASSERT(!!sequence.size()); - foreach(QString item, sequence) - notifySound->enqueue(Phonon::MediaSource(item)); + if (-1 == notifyRulesSelection->currentIndex().row()) + return; + notifySound->clearQueue(); + notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); + notification->parseNotifyMessage(); + QStringList sequence = notification->getMessageSequence(); + Q_ASSERT(!!sequence.size()); + foreach(QString item, sequence) + notifySound->enqueue(Phonon::MediaSource(item)); - notifySound->play(); + notifySound->play(); } void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) { - bool state1 = 1^state; + bool state1 = 1^state; - QList listOutputs = notifySound->outputPaths(); - Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); - audioOutput->setMuted(state1); + QList listOutputs = notifySound->outputPaths(); + Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); + audioOutput->setMuted(state1); } void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { - QString path = notification->getSoundCollectionPath(); - if (path == "") { - //QDir dir = QDir::currentPath(); - //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; - path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); - } + QString path = notification->getSoundCollectionPath(); + if (path == "") { + //QDir dir = QDir::currentPath(); + //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; + path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); + } - options_page->SoundDirectoryPathChooser->setPath(path); + options_page->SoundDirectoryPathChooser->setPath(path); - if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); - } else { - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - } + if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); + } else { + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + } - if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ - options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); - } + if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ + options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); + } - // Now load the object field values: - options_page->UAVObjectField->clear(); - QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); - if (obj != NULL ) { - QList fieldList = obj->getFields(); - foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); - } - } + // Now load the object field values: + options_page->UAVObjectField->clear(); + QString uavDataObject = notification->getDataObject(); + UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); + if (obj != NULL ) { + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } + } - if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { - options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); - } + if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { + options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); + } - if (-1 != options_page->Sound1->findText(notification->getSound1())) { - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); - } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + if (-1 != options_page->Sound1->findText(notification->getSound1())) { + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); - // don't show item if it wasn't find in stored location - //options_page->Sound1->setCurrentIndex(-1); - } + // don't show item if it wasn't find in stored location + //options_page->Sound1->setCurrentIndex(-1); + } - if (-1 != options_page->Sound2->findText(notification->getSound2())) { - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); - } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + if (-1 != options_page->Sound2->findText(notification->getSound2())) { + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); - // don't show item if it wasn't find in stored location - //options_page->Sound2->setCurrentIndex(-1); - } + // don't show item if it wasn't find in stored location + //options_page->Sound2->setCurrentIndex(-1); + } - if (-1 != options_page->Sound3->findText(notification->getSound3())) { - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); - } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); - } + if (-1 != options_page->Sound3->findText(notification->getSound3())) { + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + } - if (-1 != options_page->Value->findText(notification->getValue())) { - options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); - } + if (-1 != options_page->Value->findText(notification->getValue())) { + options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); + } - if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { - options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); - } + if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { + options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); + } - options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); + options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); } void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) { - bool select = false; - notifySound->stop(); - if (selected.indexes().size()) { - select = true; - updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); - } + bool select = false; + notifySound->stop(); + if (selected.indexes().size()) { + select = true; + updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); + } - options_page->buttonModify->setEnabled(select); - options_page->buttonDelete->setEnabled(select); - options_page->buttonPlayNotification->setEnabled(select); + options_page->buttonModify->setEnabled(select); + options_page->buttonDelete->setEnabled(select); + options_page->buttonPlayNotification->setEnabled(select); } void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() { - NotificationItem* notification = new NotificationItem; + NotificationItem* notification = new NotificationItem; - if (options_page->SoundDirectoryPathChooser->path()=="") { - QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); - textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); - options_page->SoundDirectoryPathChooser->setPalette(textPalette); - options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); - return; - } + if (options_page->SoundDirectoryPathChooser->path()=="") { + QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); + textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); + options_page->SoundDirectoryPathChooser->setPalette(textPalette); + options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); + return; + } - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); - if (options_page->Sound1->currentText().size() > 0) - notification->setSound1(options_page->Sound1->currentText()); + if (options_page->Sound1->currentText().size() > 0) + notification->setSound1(options_page->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); - if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) - || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { - return; - } else { - notification->setSayOrder(options_page->SayOrder->currentText()); - } - privListNotifications.append(notification); - emit entryAdded(privListNotifications.size() - 1); - notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) + || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { + return; + } else { + notification->setSayOrder(options_page->SayOrder->currentText()); + } + privListNotifications.append(notification); + emit entryAdded(privListNotifications.size() - 1); + notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() { - notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); - if (!notifyRulesModel->rowCount() - && (notifyRulesSelection->currentIndex().row() > 0 - && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) - { - options_page->buttonDelete->setEnabled(false); - options_page->buttonModify->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - } + notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); + if (!notifyRulesModel->rowCount() + && (notifyRulesSelection->currentIndex().row() > 0 + && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) + { + options_page->buttonDelete->setEnabled(false); + options_page->buttonModify->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + } } void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() { - NotificationItem* notification = new NotificationItem; - getOptionsPageValues(notification); - notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); - privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); - entryUpdated(notifyRulesSelection->currentIndex().row()); + NotificationItem* notification = new NotificationItem; + getOptionsPageValues(notification); + notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); + privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); + entryUpdated(notifyRulesSelection->currentIndex().row()); } diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig new file mode 100644 index 000000000..b91317c9f --- /dev/null +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig @@ -0,0 +1,465 @@ +/** + ****************************************************************************** + * + * @file notifypluginoptionspage.cpp + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Notify Plugin options page + * @see The GNU Public License (GPL) Version 3 + * @defgroup notifyplugin + * @{ + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "notifypluginoptionspage.h" +#include +#include "notificationitem.h" +#include "ui_notifypluginoptionspage.h" +#include "extensionsystem/pluginmanager.h" +#include "utils/pathutils.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "notifyplugin.h" +#include "notifyitemdelegate.h" +#include "notifytablemodel.h" + +NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) + : IOptionsPage(parent) + , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) + , owner(qobject_cast(parent)) + , currentCollectionPath("") + , privListNotifications((qobject_cast(parent))->getListNotifications()) +{ +} + +NotifyPluginOptionsPage::~NotifyPluginOptionsPage() +{ +} + +//creates options page widget (uses the UI file) +QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) +{ + options_page.reset(new Ui::NotifyPluginOptionsPage()); + //main widget + QWidget *optionsPageWidget = new QWidget; + //main layout + options_page->setupUi(optionsPageWidget); + + delegateItems.clear(); + listSoundFiles.clear(); + + delegateItems << "Repeat Once" + << "Repeat Instantly" + << "Repeat 10 seconds" + << "Repeat 30 seconds" + << "Repeat 1 minute"; + + options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); + options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); + + // Fills the combo boxes for the UAVObjects + QList< QList > objList = objManager.getDataObjects(); + foreach (QList list, objList) { + foreach (UAVDataObject* obj, list) { + options_page->UAVObject->addItem(obj->getName()); + } + } + + connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); + connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); + connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + + connect(this, SIGNAL(updateNotifications(QList)), + owner, SLOT(updateNotificationList(QList))); + connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); + + //emit resetNotification(); + + privListNotifications.clear(); + + for (int i = 0; i < owner->getListNotifications().size(); ++i) { + NotificationItem* notification = new NotificationItem(); + owner->getListNotifications().at(i)->copyTo(notification); + privListNotifications.append(notification); + } + + updateConfigView(owner->getCurrentNotification()); + + initButtons(); + initRulesTableModel(); + initRulesTableView(); + initPhononPlayer(); + + return optionsPageWidget; +} + +void NotifyPluginOptionsPage::initButtons() +{ + options_page->chkEnableSound->setChecked(owner->getEnableSound()); + connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); + + options_page->buttonModify->setEnabled(false); + options_page->buttonDelete->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); + connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); + connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); + connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); +} + +void NotifyPluginOptionsPage::initPhononPlayer() +{ + notifySound = Phonon::createPlayer(Phonon::NotificationCategory); + connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); +} + +void NotifyPluginOptionsPage::initRulesTableModel() +{ + notifyRulesModel.reset(new NotifyTableModel(&privListNotifications)); + notifyRulesSelection = new QItemSelectionModel(notifyRulesModel.data()); + connect(notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), + this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); + connect(this, SIGNAL(entryUpdated(int)), + notifyRulesModel.data(), SLOT(entryUpdated(int))); + connect(this, SIGNAL(entryAdded(int)), + notifyRulesModel.data(), SLOT(entryAdded(int))); +} + +void NotifyPluginOptionsPage::initRulesTableView() +{ + options_page->notifyRulesView->setModel(notifyRulesModel.data()); + options_page->notifyRulesView->resizeRowsToContents(); + options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); + options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); + + options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); + options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); + options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); + options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); + options_page->notifyRulesView->setDragEnabled(true); + options_page->notifyRulesView->setAcceptDrops(true); + options_page->notifyRulesView->setDropIndicatorShown(true); +} + +void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) +{ + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setSound1(options_page->Sound1->currentText()); + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); + notification->setSayOrder(options_page->SayOrder->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + +} + +/*! +* Called when the user presses apply or OK. +* Saves the current values +*/ +void NotifyPluginOptionsPage::apply() +{ + getOptionsPageValues(owner->getCurrentNotification()); + owner->setEnableSound(options_page->chkEnableSound->isChecked()); + emit updateNotifications(privListNotifications); +} + +void NotifyPluginOptionsPage::finish() +{ + disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + if (notifySound) { + notifySound->stop(); + notifySound->clear(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Fills in the combo box when value is changed in the +// combo box +////////////////////////////////////////////////////////////////////////////// +void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { + options_page->UAVObjectField->clear(); + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager* objManager = pm->getObject(); + UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } +} + +// locate collection folder on disk +void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) +{ + QDir dirPath(path); + listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + options_page->SoundCollectionList->clear(); + options_page->SoundCollectionList->addItems(listDirCollections); +} + + +void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) +{ + options_page->SoundCollectionList->setCurrentIndex(index); + + currentCollectionPath = options_page->SoundDirectoryPathChooser->path() + + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); + + QDir dirPath(currentCollectionPath); + QStringList filters; + filters << "*.mp3" << "*.wav"; + dirPath.setNameFilters(filters); + listSoundFiles = dirPath.entryList(filters); + listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); + + options_page->Sound1->clear(); + options_page->Sound2->clear(); + options_page->Sound3->clear(); + options_page->Sound1->addItems(listSoundFiles); + options_page->Sound2->addItem(""); + options_page->Sound2->addItems(listSoundFiles); + options_page->Sound3->addItem(""); + options_page->Sound3->addItems(listSoundFiles); + +} + +void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) +{ + //Q_ASSERT(Phonon::ErrorState != newstate); + + if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { + options_page->buttonPlayNotification->setText("Play"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); + } else { + if (newstate == Phonon::PlayingState) { + options_page->buttonPlayNotification->setText("Stop"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + } + } +} + +void NotifyPluginOptionsPage::onFinishedPlaying() +{ + notifySound->clear(); +} + +void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() +{ + NotificationItem* notification = NULL; + + if (-1 == notifyRulesSelection->currentIndex().row()) + return; + notifySound->clearQueue(); + notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); + notification->parseNotifyMessage(); + QStringList sequence = notification->getMessageSequence(); + Q_ASSERT(!!sequence.size()); + foreach(QString item, sequence) + notifySound->enqueue(Phonon::MediaSource(item)); + + notifySound->play(); +} + +void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) +{ + bool state1 = 1^state; + + QList listOutputs = notifySound->outputPaths(); + Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); + audioOutput->setMuted(state1); +} + +void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) +{ + QString path = notification->getSoundCollectionPath(); + if (path == "") { + //QDir dir = QDir::currentPath(); + //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; + path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); + } + + options_page->SoundDirectoryPathChooser->setPath(path); + + if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); + } else { + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + } + + if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ + options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); + } + +<<<<<<< Updated upstream + // Now load the object field values: + options_page->UAVObjectField->clear(); + QString uavDataObject = notification->getDataObject(); + UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); + if (obj != NULL ) { + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } + } +======= + // Now load the object field values: + options_page->UAVObjectField->clear(); + QString uavDataObject = notification->getDataObject(); + UAVDataObject* obj = dynamic_cast( objManager->getObject(uavDataObject/*objList.at(0).at(0)->getName()*/) ); + if (obj != NULL ) { + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } + } +>>>>>>> Stashed changes + + if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { + options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); + } + + if (-1 != options_page->Sound1->findText(notification->getSound1())) { + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + + // don't show item if it wasn't find in stored location + //options_page->Sound1->setCurrentIndex(-1); + } + + if (-1 != options_page->Sound2->findText(notification->getSound2())) { + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + + // don't show item if it wasn't find in stored location + //options_page->Sound2->setCurrentIndex(-1); + } + + if (-1 != options_page->Sound3->findText(notification->getSound3())) { + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + } else { + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + } + + if (-1 != options_page->Value->findText(notification->getValue())) { + options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); + } + + if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { + options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); + } + + options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); +} + +void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) +{ + bool select = false; + notifySound->stop(); + if (selected.indexes().size()) { + select = true; + updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); + } + + options_page->buttonModify->setEnabled(select); + options_page->buttonDelete->setEnabled(select); + options_page->buttonPlayNotification->setEnabled(select); +} + + +void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() +{ + NotificationItem* notification = new NotificationItem; + + if (options_page->SoundDirectoryPathChooser->path()=="") { + QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); + textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); + options_page->SoundDirectoryPathChooser->setPalette(textPalette); + options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); + return; + } + + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + + if (options_page->Sound1->currentText().size() > 0) + notification->setSound1(options_page->Sound1->currentText()); + + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); + + if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) + || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { + return; + } else { + notification->setSayOrder(options_page->SayOrder->currentText()); + } + privListNotifications.append(notification); + emit entryAdded(privListNotifications.size() - 1); + notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +} + + +void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() +{ + notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); + if (!notifyRulesModel->rowCount() + && (notifyRulesSelection->currentIndex().row() > 0 + && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) + { + options_page->buttonDelete->setEnabled(false); + options_page->buttonModify->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + } + +} + +void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() +{ + NotificationItem* notification = new NotificationItem; + getOptionsPageValues(notification); + notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); + privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); + entryUpdated(notifyRulesSelection->currentIndex().row()); + +} + diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 521cf9874..acb9f18e7 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -100,7 +100,7 @@ private: signals: void updateNotifications(QList list); - void resetNotification(void); + //void resetNotification(void); void entryUpdated(int index); void entryAdded(int position); diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index f3c89b5b7..7c564a6df 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -31,82 +31,82 @@ NotifyTableModel::NotifyTableModel(QList* parentList, QObject* parent) : QAbstractTableModel(parent) { - _headerStrings << "Name" << "Repeats" << "Lifetime,sec" << "Enable"; - _list.reset(parentList); + _headerStrings << "Name" << "Repeats" << "Lifetime,sec" << "Enable"; + _list.reset(parentList); } bool NotifyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { - if (index.isValid() && role == Qt::EditRole) { - if(eREPEAT_VALUE == index.column()) - _list->at(index.row())->setRepeatFlag(value.toString()); - else { - if(eEXPIRE_TIME == index.column()) - _list->at(index.row())->setExpireTimeout(value.toInt()); - else { - if(eENABLE_NOTIFICATION == index.column()) - _list->at(index.row())->setEnableFlag(value.toBool()); - } - } - emit dataChanged(index, index); - return true; - } - return false; + if (index.isValid() && role == Qt::EditRole) { + if(eREPEAT_VALUE == index.column()) + _list->at(index.row())->setRepeatFlag(value.toString()); + else { + if(eEXPIRE_TIME == index.column()) + _list->at(index.row())->setExpireTimeout(value.toInt()); + else { + if(eENABLE_NOTIFICATION == index.column()) + _list->at(index.row())->setEnableFlag(value.toBool()); + } + } + emit dataChanged(index, index); + return true; + } + return false; } QVariant NotifyTableModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) { - qWarning() << "NotifyTableModel::data - index.isValid()"; - return QVariant(); - } + if (!index.isValid()) { + qWarning() << "NotifyTableModel::data - index.isValid()"; + return QVariant(); + } - if (index.row() >= _list->size()) - return QVariant(); + if (index.row() >= _list->size()) + return QVariant(); - if (role == Qt::DisplayRole || role == Qt::EditRole) - { - switch(index.column()) - { - case eMESSAGE_NAME: - return _list->at(index.row())->parseNotifyMessage(); + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + switch(index.column()) + { + case eMESSAGE_NAME: + return _list->at(index.row())->parseNotifyMessage(); - case eREPEAT_VALUE: - return _list->at(index.row())->getRepeatFlag(); + case eREPEAT_VALUE: + return _list->at(index.row())->getRepeatFlag(); - case eEXPIRE_TIME: - return _list->at(index.row())->getExpireTimeout(); + case eEXPIRE_TIME: + return _list->at(index.row())->getExpireTimeout(); - case eENABLE_NOTIFICATION: - return _list->at(index.row())->getEnableFlag(); + case eENABLE_NOTIFICATION: + return _list->at(index.row())->getEnableFlag(); - default: - return QVariant(); - } - } - else - { - if (Qt::SizeHintRole == role){ - return QVariant(10); - } - } - return QVariant(); + default: + return QVariant(); + } + } + else + { + if (Qt::SizeHintRole == role){ + return QVariant(10); + } + } + return QVariant(); } QVariant NotifyTableModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) - return QVariant(); + if (role != Qt::DisplayRole) + return QVariant(); - if (orientation == Qt::Horizontal) - return _headerStrings.at(section); - else - if(orientation == Qt::Vertical) - return QString("%1").arg(section); + if (orientation == Qt::Horizontal) + return _headerStrings.at(section); + else + if(orientation == Qt::Vertical) + return QString("%1").arg(section); - return QVariant(); + return QVariant(); } bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex& index) @@ -132,11 +132,11 @@ bool NotifyTableModel::removeRows(int position, int rows, const QModelIndex& ind void NotifyTableModel::entryUpdated(int offset) { - QModelIndex idx = index(offset, 0); - emit dataChanged(idx, idx); + QModelIndex idx = index(offset, 0); + emit dataChanged(idx, idx); } void NotifyTableModel::entryAdded(int position) { - insertRows(position, 1,QModelIndex()); + insertRows(position, 1,QModelIndex()); } From 1665ae8299645c94d7cb6d7081b624e8dafd65b0 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Mon, 19 Sep 2011 00:26:49 +0300 Subject: [PATCH 05/72] +reordering add some changes; --- .../internals/projections/lks94projection.h | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h diff --git a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h b/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h deleted file mode 100644 index efbe9c394..000000000 --- a/ground/openpilotgcs/src/libs/opmapcontrol/src/internals/projections/lks94projection.h +++ /dev/null @@ -1,72 +0,0 @@ -/** -****************************************************************************** -* -* @file lks94projection.h -* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. -* @brief -* @see The GNU Public License (GPL) Version 3 -* @defgroup OPMapWidget -* @{ -* -*****************************************************************************/ -/* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, but -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -* for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -#ifndef LKS94PROJECTION_H -#define LKS94PROJECTION_H -#include -#include "cmath" -#include "D:\!Work\OpenPilot\OpenPilot\ground\openpilotgcs\src\libs\opmapcontrol\src\internals\pureprojection.h" - - -namespace projections { -class LKS94Projection:public internals::PureProjection -{ -public: - LKS94Projection(); - double GetTileMatrixResolution(int const& zoom); - virtual QString Type(){return "LKS94Projection";} - virtual Size TileSize() const; - virtual double Axis() const; - virtual double Flattening() const; - virtual core::Point FromLatLngToPixel(double lat, double lng, int const& zoom); - virtual internals::PointLatLng FromPixelToLatLng(int const& x, int const& y, int const& zoom); - virtual double GetGroundResolution(int const& zoom, double const& latitude); - virtual Size GetTileMatrixMinXY(int const& zoom); - virtual Size GetTileMatrixMaxXY(int const& zoom); - -private: - const double MinLatitude; - const double MaxLatitude; - const double MinLongitude; - const double MaxLongitude; - const double orignX; - const double orignY; - Size tileSize; - QVector DTM10(const QVector & lonlat); - QVector MTD10(QVector & pnt); - QVector DTM00(QVector & lonlat); - QVector DTM01(QVector & lonlat); - QVector MTD01(QVector & pnt); - QVector MTD11(QVector & p); - double Clip(double const& n, double const& minValue, double const& maxValue); -}; - -} -#endif // LKS94PROJECTION_H - - - - From 1af42e1b32d9d95845f62aa724e4fc0248f4bb7b Mon Sep 17 00:00:00 2001 From: Nickolay Date: Mon, 19 Sep 2011 00:30:57 +0300 Subject: [PATCH 06/72] + notify table reordering some changes --- .../src/plugins/notify/NotificationItem.h | 30 ++- .../src/plugins/notify/notificationitem.cpp | 50 ++++- .../src/plugins/notify/notifyitemdelegate.cpp | 10 +- .../src/plugins/notify/notifyitemdelegate.h | 4 +- .../src/plugins/notify/notifylogging.cpp | 13 +- .../src/plugins/notify/notifylogging.h | 8 +- .../src/plugins/notify/notifyplugin.cpp | 88 ++++----- .../notify/notifypluginoptionspage.cpp | 83 ++++----- .../plugins/notify/notifypluginoptionspage.h | 19 +- .../src/plugins/notify/notifytablemodel.cpp | 175 ++++++++++++++++-- .../src/plugins/notify/notifytablemodel.h | 23 ++- 11 files changed, 350 insertions(+), 153 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index ad7250060..da40d2afb 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -78,21 +78,22 @@ public: QStringList getMessageSequence() const { return _messageSequence; } void setMessageSequence(QStringList sequence) { _messageSequence = sequence; } - QString getRepeatFlag() const { return _repeatString; } - void setRepeatFlag(QString value) { _repeatString = value; } + QString retryString() const { return _repeatString; } + void setRetryString(QString value) { _repeatString = value; } - bool getRepeatTimeout() const { return _repeatTimeout; } - void setRepeatTimeout(bool value) { _repeatTimeout = value; } + int lifetime() const { return _expireTimeout; } + void setLifetime(int value) { _expireTimeout = value; } - int getExpireTimeout() const { return _expireTimeout; } - void setExpireTimeout(int value) { _expireTimeout = value; } - - bool getEnableFlag() const { return _enableFlag; } - void setEnableFlag(bool value) { _enableFlag = value; } + bool mute() const { return _mute; } + void setMute(bool value) { _mute = value; } void saveState(QSettings* settings) const; void restoreState(QSettings* settings); + + void seriaize(QDataStream& stream); + void deseriaize(QDataStream& stream); + QString parseNotifyMessage(); QTimer* getTimer() const { return _timer; } @@ -120,8 +121,6 @@ private: //! according to its priority QTimer* _expireTimer; - - QStringList _messageSequence; //! path to folder with sound files @@ -149,20 +148,15 @@ private: double _spinBoxValue; - QString _repeatString; - - //! time when next notification must be fired - bool _repeatTimeout; - //! how often or what periodicaly notification should be played - int _repeatTimerValue; + QString _repeatString; //! time after event occured till notification became invalid //! and will be removed from list int _expireTimeout; //! enables/disables playing of current notification - bool _enableFlag; + bool _mute; }; Q_DECLARE_METATYPE(NotificationItem*) diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 69f085620..889b84261 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -47,8 +47,8 @@ NotificationItem::NotificationItem(QObject *parent) , _sayOrder("Never") , _spinBoxValue(0) , _repeatString("Repeat Instantly") - , _repeatTimeout(true) , _expireTimeout(15) + , _mute(false) { _timer = NULL; @@ -71,8 +71,9 @@ void NotificationItem::copyTo(NotificationItem* that) const that->_sayOrder = _sayOrder; that->_spinBoxValue = _spinBoxValue; that->_repeatString = _repeatString; - that->_repeatTimeout = _repeatTimeout; that->_expireTimeout = _expireTimeout; + that->_mute = _mute; + } @@ -88,8 +89,10 @@ void NotificationItem::saveState(QSettings* settings) const settings->setValue(QLatin1String("Sound2"), getSound2()); settings->setValue(QLatin1String("Sound3"), getSound3()); settings->setValue(QLatin1String("SayOrder"), getSayOrder()); - settings->setValue(QLatin1String("Repeat"), getRepeatFlag()); - settings->setValue(QLatin1String("ExpireTimeout"), getExpireTimeout()); + settings->setValue(QLatin1String("Repeat"), retryString()); + settings->setValue(QLatin1String("ExpireTimeout"), lifetime()); + settings->setValue(QLatin1String("Mute"), mute()); + } void NotificationItem::restoreState(QSettings* settings) @@ -105,10 +108,45 @@ void NotificationItem::restoreState(QSettings* settings) setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); setSpinBoxValue(settings->value(QLatin1String("ValueSpinBox"), tr("")).toDouble()); - setRepeatFlag(settings->value(QLatin1String("Repeat"), tr("")).toString()); - setExpireTimeout(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); + setRetryString(settings->value(QLatin1String("Repeat"), tr("")).toString()); + setLifetime(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); + setMute(settings->value(QLatin1String("Mute"), tr("")).toInt()); + } +void NotificationItem::seriaize(QDataStream& stream) +{ + stream << this->_soundCollectionPath; + stream << this->_currentLanguage; + stream << this->_dataObject; + stream << this->_objectField; + stream << this->_dataValue; + stream << this->_sound1; + stream << this->_sound2; + stream << this->_sound3; + stream << this->_sayOrder; + stream << this->_spinBoxValue; + stream << this->_repeatString; + stream << this->_expireTimeout; + stream << this->_mute; +} + +void NotificationItem::deseriaize(QDataStream& stream) +{ + stream >> this->_soundCollectionPath; + stream >> this->_currentLanguage; + stream >> this->_dataObject; + stream >> this->_objectField; + stream >> this->_dataValue; + stream >> this->_sound1; + stream >> this->_sound2; + stream >> this->_sound3; + stream >> this->_sayOrder; + stream >> this->_spinBoxValue; + stream >> this->_repeatString; + stream >> this->_expireTimeout; + stream >> this->_mute; +} void NotificationItem::startTimer(int value) { if (!_timer) { diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp index f5f243e43..d418f0d26 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp @@ -30,11 +30,15 @@ #include "notifytablemodel.h" #include "notifylogging.h" -NotifyItemDelegate::NotifyItemDelegate(QStringList items, QObject* parent) +NotifyItemDelegate::NotifyItemDelegate(QObject* parent) : QItemDelegate(parent) , _parent(parent) - , _items(items) { + _titles << "Repeat Once" + << "Repeat Instantly" + << "Repeat 10 seconds" + << "Repeat 30 seconds" + << "Repeat 1 minute"; } @@ -44,7 +48,7 @@ QWidget *NotifyItemDelegate::createEditor(QWidget* parent, const QStyleOptionVie if (eREPEAT_VALUE == index.column()) { QComboBox* editor = new QComboBox(parent); editor->clear(); - editor->addItems(_items); + editor->addItems(_titles); return editor; } else { if (eEXPIRE_TIME == index.column()) { diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h index 01fa0794d..494e61c17 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h @@ -37,7 +37,7 @@ class NotifyItemDelegate : public QItemDelegate Q_OBJECT public: - NotifyItemDelegate(QStringList items, QObject *parent = 0); + NotifyItemDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; @@ -51,7 +51,7 @@ private slots: private: QObject* _parent; - QStringList _items; + QStringList _titles; }; diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp index 616b2ada5..0a29cc6e6 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp @@ -28,15 +28,16 @@ #include "notifylogging.h" -#ifdef DEBUG_NOTIFIES +#ifdef DEBUG_NOTIFIES_ENABLE QDebug qNotifyDebug() -#endif -#ifndef DEBUG_NOTIFIES -QNoDebug qNotifyDebug() -#endif { -#ifdef DEBUG_NOTIFIES return qDebug(); +} #endif + +#ifndef DEBUG_NOTIFIES_ENABLE +QNoDebug qNotifyDebug() +{ return QNoDebug(); } +#endif diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.h b/ground/openpilotgcs/src/plugins/notify/notifylogging.h index bf02b86df..ea7ea331c 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifylogging.h +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.h @@ -31,12 +31,16 @@ #include "QDebug.h" -#ifdef DEBUG_NOTIFIES +#define DEBUG_NOTIFIES_ENABLE + +#ifdef DEBUG_NOTIFIES_ENABLE QDebug qNotifyDebug(); #endif -#ifndef DEBUG_NOTIFIES + +#ifndef DEBUG_NOTIFIES_ENABLE QNoDebug qNotifyDebug(); #endif +#define qNotifyDebug_if(test) if(test) qNotifyDebug() #endif // NOTIFYLOGGING_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 9eef49dec..e7878c3da 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -272,8 +272,8 @@ void SoundNotifyPlugin::appendNotification(UAVObject *object) if (nowPlayingConfiguration == ntf) continue; - if (ntf->getRepeatFlag()!= "Repeat Instantly" && - ntf->getRepeatFlag()!= "Repeat Once" && !ntf->firstStart) + if (ntf->retryString() != "Repeat Instantly" && + ntf->retryString() != "Repeat Once" && !ntf->firstStart) continue; checkNotificationRule(ntf,object); @@ -288,46 +288,47 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA double threshold; QString direction; QString fieldName; + threshold = notification->getSpinBoxValue(); direction = notification->getValue(); fieldName = notification->getObjectField(); UAVObjectField* field = object->getField(fieldName); - if (field->getName()!="") { - double value = field->getDouble(); - switch(direction[0].toAscii()) - { - case 'E': - if (value==threshold) - condition = true; - break; - case 'G': - if (value>threshold) - condition = true; - break; - case 'L': - if (valuegetName() == "") + return; + + double value = field->getDouble(); + switch(direction[0].toAscii()) + { + case 'E': + condition = (value == threshold); + break; + + case 'G': + condition = (value > threshold); + break; + + case 'L': + condition = (value < threshold); + break; } - if (condition) - { - if (!playNotification(notification)) - { - if (!pendingNotifications.contains(notification)) - { - notification->stopTimer(); + if (!condition) + return; - qNotifyDebug() << "add to pending list - " << notification->parseNotifyMessage(); - // if audio is busy, start expiration timer - //ms = (notification->getExpiredTimeout()[in sec])*1000 - //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); - pendingNotifications.append(notification); - notification->startExpireTimer(); - connect(notification->getExpireTimer(), SIGNAL(timeout()), this, SLOT(expireTimerHandler())); - } + if (!playNotification(notification)) + { + if (!pendingNotifications.contains(notification)) + { + notification->stopTimer(); + + qNotifyDebug() << "add to pending list - " << notification->parseNotifyMessage(); + // if audio is busy, start expiration timer + //ms = (notification->getExpiredTimeout()[in sec])*1000 + //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); + pendingNotifications.append(notification); + notification->startExpireTimer(); + connect(notification->getExpireTimer(), SIGNAL(timeout()), this, SLOT(expireTimerHandler())); } } } @@ -338,26 +339,26 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) if (phonon.mo == NULL) return false; - if (!notification->getEnableFlag()) return true; + if (!notification->mute()) + return true; qNotifyDebug() << "Phonon State: " << phonon.mo->state(); if ((phonon.mo->state()==Phonon::PausedState) - || (phonon.mo->state()==Phonon::StoppedState) - || phonon.firstPlay) + || (phonon.mo->state()==Phonon::StoppedState) + || phonon.firstPlay) { // don't fire expire timer nowPlayingConfiguration = notification; notification->stopExpireTimer(); - if (notification->getRepeatFlag()=="Repeat Once") { + if (notification->retryString() == "Repeat Once") { removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); } else { - if (notification->getRepeatFlag()!="Repeat Instantly") - { + if (notification->retryString() != "Repeat Instantly") { QRegExp rxlen("(\\d+)"); QString value; int timer_value; - int pos = rxlen.indexIn(notification->getRepeatFlag()); + int pos = rxlen.indexIn(notification->retryString()); if (pos > -1) { value = rxlen.cap(1); // "189" timer_value = (value.toInt()+8)*1000; //ms*1000 + average duration of meassage @@ -379,10 +380,9 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) phonon.mo->play(); phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before // the state is not "Loading" anymore. - } - else + } else { return false; // if audio is busy - + } return true; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index caad0efff..a1122f078 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -43,13 +43,13 @@ #include "notifyplugin.h" #include "notifyitemdelegate.h" #include "notifytablemodel.h" +#include "notifylogging.h" NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) : IOptionsPage(parent) , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) , owner(qobject_cast(parent)) , currentCollectionPath("") - , privListNotifications((qobject_cast(parent))->getListNotifications()) { } @@ -66,15 +66,8 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) //main layout options_page->setupUi(optionsPageWidget); - delegateItems.clear(); listSoundFiles.clear(); - delegateItems << "Repeat Once" - << "Repeat Instantly" - << "Repeat 10 seconds" - << "Repeat 30 seconds" - << "Repeat 1 minute"; - options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); @@ -95,19 +88,13 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) //connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); - privListNotifications.clear(); - - for (int i = 0; i < owner->getListNotifications().size(); ++i) { - NotificationItem* notification = new NotificationItem(); - owner->getListNotifications().at(i)->copyTo(notification); - privListNotifications.append(notification); - } +// privListNotifications = ((qobject_cast(parent))->getListNotifications()); + privListNotifications = owner->getListNotifications(); updateConfigView(owner->getCurrentNotification()); + initRulesTable(); initButtons(); - initRulesTableModel(); - initRulesTableView(); initPhononPlayer(); return optionsPageWidget; @@ -129,31 +116,32 @@ void NotifyPluginOptionsPage::initButtons() void NotifyPluginOptionsPage::initPhononPlayer() { - notifySound = Phonon::createPlayer(Phonon::NotificationCategory); - connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); + connect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); + connect(notifySound.data(), SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); } -void NotifyPluginOptionsPage::initRulesTableModel() +void NotifyPluginOptionsPage::initRulesTable() { - notifyRulesModel.reset(new NotifyTableModel(&privListNotifications)); - notifyRulesSelection = new QItemSelectionModel(notifyRulesModel.data()); - connect(notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), + qNotifyDebug_if(_notifyRulesModel.isNull()) << "_notifyRulesModel.isNull())"; + qNotifyDebug_if(!_notifyRulesSelection) << "_notifyRulesSelection.isNull())"; + //QItemSelectionModel* selection = _notifyRulesSelection.take(); + _notifyRulesModel.reset(new NotifyTableModel(privListNotifications)); + _notifyRulesSelection = new QItemSelectionModel(_notifyRulesModel.data()); + + connect(_notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); connect(this, SIGNAL(entryUpdated(int)), - notifyRulesModel.data(), SLOT(entryUpdated(int))); + _notifyRulesModel.data(), SLOT(entryUpdated(int))); connect(this, SIGNAL(entryAdded(int)), - notifyRulesModel.data(), SLOT(entryAdded(int))); -} + _notifyRulesModel.data(), SLOT(entryAdded(int))); + + options_page->notifyRulesView->setModel(_notifyRulesModel.data()); + options_page->notifyRulesView->setSelectionModel(_notifyRulesSelection); + options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(this)); -void NotifyPluginOptionsPage::initRulesTableView() -{ - options_page->notifyRulesView->setModel(notifyRulesModel.data()); options_page->notifyRulesView->resizeRowsToContents(); - options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); - options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); - options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); @@ -161,6 +149,9 @@ void NotifyPluginOptionsPage::initRulesTableView() options_page->notifyRulesView->setDragEnabled(true); options_page->notifyRulesView->setAcceptDrops(true); options_page->notifyRulesView->setDropIndicatorShown(true); + options_page->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); + + } void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) @@ -175,7 +166,6 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio notification->setSayOrder(options_page->SayOrder->currentText()); notification->setValue(options_page->Value->currentText()); notification->setSpinBoxValue(options_page->ValueSpinBox->value()); - } /*! @@ -191,7 +181,7 @@ void NotifyPluginOptionsPage::apply() void NotifyPluginOptionsPage::finish() { - disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + disconnect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(changeButtonText(Phonon::State,Phonon::State))); if (notifySound) { notifySound->stop(); @@ -272,10 +262,10 @@ void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() { NotificationItem* notification = NULL; - if (-1 == notifyRulesSelection->currentIndex().row()) + if (-1 == _notifyRulesSelection->currentIndex().row()) return; notifySound->clearQueue(); - notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); + notification = privListNotifications.at(_notifyRulesSelection->currentIndex().row()); notification->parseNotifyMessage(); QStringList sequence = notification->getMessageSequence(); Q_ASSERT(!!sequence.size()); @@ -419,17 +409,17 @@ if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder-> } privListNotifications.append(notification); emit entryAdded(privListNotifications.size() - 1); - notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), + _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() { - notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); - if (!notifyRulesModel->rowCount() - && (notifyRulesSelection->currentIndex().row() > 0 - && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) + _notifyRulesModel->removeRow(_notifyRulesSelection->currentIndex().row()); + if (!_notifyRulesModel->rowCount() + && (_notifyRulesSelection->currentIndex().row() > 0 + && _notifyRulesSelection->currentIndex().row() < _notifyRulesModel->rowCount()) ) { options_page->buttonDelete->setEnabled(false); options_page->buttonModify->setEnabled(false); @@ -442,9 +432,12 @@ void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() { NotificationItem* notification = new NotificationItem; getOptionsPageValues(notification); - notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); - privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); - entryUpdated(notifyRulesSelection->currentIndex().row()); + notification->setRetryString(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryString()); + notification->setLifetime(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->lifetime()); + notification->setMute(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->mute()); + + privListNotifications.replace(_notifyRulesSelection->currentIndex().row(),notification); + entryUpdated(_notifyRulesSelection->currentIndex().row()); } diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index acb9f18e7..9e49e89ec 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -42,13 +42,15 @@ #include #include #include -#include "ui_notifypluginoptionspage.h" //#include "notifytablemodel.h" class NotifyTableModel; class NotificationItem; class SoundNotifyPlugin; +namespace Ui { + class NotifyPluginOptionsPage; +}; using namespace Core; @@ -74,11 +76,11 @@ public: void getOptionsPageValues(NotificationItem* notification); private: - //Q_DISABLE_COPY(NotifyPluginOptionsPage) + Q_DISABLE_COPY(NotifyPluginOptionsPage) + void initButtons(); void initPhononPlayer(); - void initRulesTableModel(); - void initRulesTableView(); + void initRulesTable(); private: UAVObjectManager& objManager; @@ -86,14 +88,13 @@ private: QStringList listDirCollections; QStringList listSoundFiles; QString currentCollectionPath; - int sizeNotifyList; Phonon::MediaObject *sound1; Phonon::MediaObject *sound2; - Phonon::MediaObject *notifySound; + QScopedPointer notifySound; Phonon::AudioOutput *audioOutput; - QStringList delegateItems; - QScopedPointer notifyRulesModel; - QItemSelectionModel *notifyRulesSelection; + + QScopedPointer _notifyRulesModel; + QItemSelectionModel* _notifyRulesSelection; QList privListNotifications; QScopedPointer options_page; diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index 7c564a6df..0c2337437 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -26,28 +26,41 @@ */ #include "notifytablemodel.h" +#include "notifylogging.h" #include +#include -NotifyTableModel::NotifyTableModel(QList* parentList, QObject* parent) +static int _dragStartRow = -1; +static int _dragNumRows = -1; +const char* mime_type_notify_table = "openpilot/notify_plugin_table"; + +NotifyTableModel::NotifyTableModel(QList& parentList, QObject* parent) : QAbstractTableModel(parent) + , _list(parentList) { - _headerStrings << "Name" << "Repeats" << "Lifetime,sec" << "Enable"; - _list.reset(parentList); + _headerStrings << "Name" << "Repeats" << "Lifetime,sec" << "Mute"; + connect(this, SIGNAL(dragRows(int, int)), this, SLOT(dropRows(int, int))); } bool NotifyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (index.isValid() && role == Qt::DisplayRole) { + if(eMESSAGE_NAME == index.column()) { + emit dataChanged(index, index); + return true; + } + } if (index.isValid() && role == Qt::EditRole) { if(eREPEAT_VALUE == index.column()) - _list->at(index.row())->setRepeatFlag(value.toString()); + _list.at(index.row())->setRetryString(value.toString()); else { if(eEXPIRE_TIME == index.column()) - _list->at(index.row())->setExpireTimeout(value.toInt()); + _list.at(index.row())->setLifetime(value.toInt()); else { if(eENABLE_NOTIFICATION == index.column()) - _list->at(index.row())->setEnableFlag(value.toBool()); + _list.at(index.row())->setMute(value.toBool()); } } emit dataChanged(index, index); @@ -63,7 +76,7 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const return QVariant(); } - if (index.row() >= _list->size()) + if (index.row() >= _list.size()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) @@ -71,16 +84,16 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const switch(index.column()) { case eMESSAGE_NAME: - return _list->at(index.row())->parseNotifyMessage(); + return _list.at(index.row())->parseNotifyMessage(); case eREPEAT_VALUE: - return _list->at(index.row())->getRepeatFlag(); + return _list.at(index.row())->retryString(); case eEXPIRE_TIME: - return _list->at(index.row())->getExpireTimeout(); + return _list.at(index.row())->lifetime(); case eENABLE_NOTIFICATION: - return _list->at(index.row())->getEnableFlag(); + return _list.at(index.row())->mute(); default: return QVariant(); @@ -112,7 +125,16 @@ QVariant NotifyTableModel::headerData(int section, Qt::Orientation orientation, bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex& index) { Q_UNUSED(index); - beginInsertRows(QModelIndex(), position, position+rows-1); + + if((-1 == position) || (-1 == rows) ) + return false; + + beginInsertRows(QModelIndex(), position, position + rows - 1); + + for (int row = 0; row < rows; ++row) { + _list.insert(position, new NotificationItem()); + } + endInsertRows(); return true; } @@ -120,10 +142,14 @@ bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex& ind bool NotifyTableModel::removeRows(int position, int rows, const QModelIndex& index) { Q_UNUSED(index); - beginRemoveRows(QModelIndex(), position, position+rows-1); - for (int row=0; row < rows; ++row) { - _list->removeAt(position); + if((-1 == position) || (-1 == rows) ) + return false; + + beginRemoveRows(QModelIndex(), position, position + rows - 1); + + for (int row = 0; row < rows; ++row) { + _list.removeAt(position); } endRemoveRows(); @@ -140,3 +166,122 @@ void NotifyTableModel::entryAdded(int position) { insertRows(position, 1,QModelIndex()); } + + +bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, + int column, const QModelIndex& parent) +{ + if (action == Qt::IgnoreAction) + return true; + + if (!data->hasFormat(mime_type_notify_table)) + return false; + + int beginRow = -1; + + if (row != -1) + beginRow = row; + else { + if (parent.isValid()) + beginRow = parent.row(); + else + beginRow = rowCount(QModelIndex()); + } + + if(-1 == beginRow) + return false; + + QByteArray encodedData = data->data(mime_type_notify_table); + QDataStream stream(&encodedData, QIODevice::ReadOnly); + int rows = beginRow; + while(!stream.atEnd()) { + qint32 ptr; + stream >> ptr; + NotificationItem* item = reinterpret_cast(ptr); + int dragged = _list.indexOf(item); + if(-1 == dragged || rows >= _list.size() || dragged == rows) { + qNotifyDebug() << "no such item"; + return false; + } + removeRows(rows, 1, QModelIndex()); + insertRows(rows, 1, QModelIndex()); + _list.replace(dragged, item); + // _list.swap(dragged, rows); + ++rows; + }; + + QModelIndex idxTopLeft = index(beginRow, 0, QModelIndex()); + QModelIndex idxBotRight = index(beginRow, columnCount(QModelIndex()), QModelIndex()); + emit dataChanged(idxTopLeft, idxBotRight); + //QStringList newItems; + + //removeRows(_dragStartRow, _dragNumRows, QModelIndex()); + //insertRows(beginRow, rows, QModelIndex()); +// int rows = beginRow; +// while (!stream.atEnd()) { +// _list.at(index.row())->deserialize(stream); +// ++rows; +// } + +// while(rows) { +// int column = 0; +// foreach (const QString& text, newItems) { +// QModelIndex idx = index(beginRow, column, QModelIndex()); +// if(!column) +// setData(const_cast(idx), text, Qt::DisplayRole); +// else +// setData(const_cast(idx), text, Qt::EditRole); +// ++column; +// } +// ++beginRow; +// --rows; +// } + return true; +} + +QMimeData* NotifyTableModel::mimeData(const QModelIndexList& indexes) const +{ + QMimeData* mimeData = new QMimeData(); + QByteArray encodedData; + + QDataStream stream(&encodedData, QIODevice::WriteOnly); + int rows = 0; + foreach (const QModelIndex& index, indexes) { + if(!index.column()) { + qint32 item = reinterpret_cast(_list.at(index.row())); + stream << item; + } + ++rows; + } + +// int numRows = 0; +// foreach (const QModelIndex& index, indexes) { +// if (index.isValid() && index.column()) { +// _list.at(index.row())->serialize(stream); +//// if(!index.column()) { +//// numRows++; +//// QString name = data(index, Qt::DisplayRole).toString(); +//// stream << name; +//// } else { +//// QString text = data(index, Qt::EditRole).toString(); +//// stream << text; +//// } +// } +// } + + mimeData->setData(mime_type_notify_table, encodedData); + + //emit dragRows(indexes.at(0).row(), rows); + dropRows(indexes.at(0).row(), rows); + //_dragStartRow = indexes.at(0).row(); + //_dragNumRows = 1/*numRows*/; + + return mimeData; +} + +void NotifyTableModel::dropRows(int position, int count) const +{ + for (int row = 0; row < count; ++row) { + _list.removeAt(position); + } +} diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index affae25da..f58cc0599 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -43,11 +43,11 @@ class NotifyTableModel : public QAbstractTableModel public: - NotifyTableModel(QList* parentList, QObject* parent = 0); + NotifyTableModel(QList& parentList, QObject* parent = 0); int rowCount(const QModelIndex& parent = QModelIndex()) const { - return _list->count(); + return _list.count(); } int columnCount(const QModelIndex &/*parent*/) const @@ -68,17 +68,34 @@ public: return Qt::MoveAction; } + QStringList mimeTypes() const + { + QStringList types; + types << "application/vnd.text.list"; + return types; + } + + bool dropMimeData( const QMimeData * data, Qt::DropAction action, int row, + int column, const QModelIndex& parent); + QMimeData* mimeData(const QModelIndexList &indexes) const; + + bool setData(const QModelIndex &index, const QVariant &value, int role); QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; bool insertRows(int position, int rows, const QModelIndex &index); bool removeRows(int position, int rows, const QModelIndex &index); +signals: + void dragRows(int position, int count); + private slots: void entryUpdated(int offset); void entryAdded(int position); + void dropRows(int position, int count) const; + private: - QScopedPointer > _list; + mutable QList& _list; QStringList _headerStrings; }; From 82ec3199d73f0d743d117fc028243dfd038b2ae5 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Thu, 29 Sep 2011 20:26:46 +0300 Subject: [PATCH 07/72] +dynamic field UI; --- .../src/plugins/notify/NotificationItem.h | 30 +- .../src/plugins/notify/notificationitem.cpp | 259 +++--- .../src/plugins/notify/notifyplugin.cpp | 9 +- .../notify/notifypluginoptionspage.cpp | 406 ++++++--- .../notify/notifypluginoptionspage.cpp.orig | 443 +++++----- .../plugins/notify/notifypluginoptionspage.h | 59 +- .../plugins/notify/notifypluginoptionspage.ui | 787 +++++++----------- .../src/plugins/notify/notifytablemodel.cpp | 8 +- .../src/plugins/notify/notifytablemodel.h | 3 +- 9 files changed, 1094 insertions(+), 910 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index da40d2afb..20de7a4f8 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -40,11 +40,15 @@ using namespace Core; QString getSound##number() const { return _sound##number; } \ void setSound##number(QString text) { _sound##number = text; } \ +class UAVDataObject; +class UAVObjectField; class NotificationItem : public QObject { Q_OBJECT public: + enum { eDefaultTimeout = 15 }; // in sec + explicit NotificationItem(QObject *parent = 0); void copyTo(NotificationItem*) const; @@ -53,15 +57,17 @@ public: DECLARE_SOUND(2) DECLARE_SOUND(3) - QString getValue() const { return _dataValue; } - void setValue(QString text) { _dataValue = text; } + QString range() const { return _rangeLimit; } + void setRange(QString text) { _rangeLimit = text; } QString getSayOrder() const { return _sayOrder; } void setSayOrder(QString text) { _sayOrder = text; } - double getSpinBoxValue() const { return _spinBoxValue; } - void setSpinBoxValue(double value) { _spinBoxValue = value; } + double singleValue() const { return _singleValue; } + void setSingleValue(double value) { _singleValue = value; } + double valueRange2() const { return _valueRange2; } + void setValueRange2(double value) { _valueRange2 = value; } QString getDataObject() const { return _dataObject; } void setDataObject(QString text) { _dataObject = text; } @@ -91,6 +97,9 @@ public: void restoreState(QSettings* settings); + UAVDataObject* getUAVObject(void); + UAVObjectField* getUAVObjectField(void); + void seriaize(QDataStream& stream); void deseriaize(QDataStream& stream); @@ -111,7 +120,7 @@ public: bool firstStart; private: - void checkSoundFilesExisting(); + void checkSoundFilesExisting(bool& missed1, bool& missed2, bool& missed3); private: QTimer* _timer; @@ -135,8 +144,8 @@ private: //! one field value change can be assigned to one notification QString _objectField; - //! poled UAV field value - QString _dataValue; + //! fire condition for UAV field value (lower, greater, in range) + QString _rangeLimit; //! possible sounds(at least one required to play notification) QString _sound1; @@ -146,7 +155,12 @@ private: //! order in what sounds 1-3 will be played QString _sayOrder; - double _spinBoxValue; + //! one-side range, value maybe lower or greater + double _singleValue; + + //! both-side range, value should be inside the range + //double _valueRange1; + double _valueRange2; //! how often or what periodicaly notification should be played QString _repeatString; diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 889b84261..d6c803b68 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -25,11 +25,19 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "notificationitem.h" -#include "notifylogging.h" +//Qt headers #include #include + +// GCS headers +#include "extensionsystem/pluginmanager.h" #include "utils/pathutils.h" +#include "uavobjectmanager.h" +#include "uavobject.h" + +// Notify plugin headers +#include "notificationitem.h" +#include "notifylogging.h" NotificationItem::NotificationItem(QObject *parent) @@ -40,14 +48,15 @@ NotificationItem::NotificationItem(QObject *parent) , _currentLanguage("default") , _dataObject("") , _objectField("") - , _dataValue("Equal to") + , _rangeLimit("Equal to") , _sound1("") , _sound2("") , _sound3("") , _sayOrder("Never") - , _spinBoxValue(0) + , _singleValue(0) + , _valueRange2(0) , _repeatString("Repeat Instantly") - , _expireTimeout(15) + , _expireTimeout(eDefaultTimeout) , _mute(false) { @@ -64,12 +73,13 @@ void NotificationItem::copyTo(NotificationItem* that) const that->_soundCollectionPath = _soundCollectionPath; that->_dataObject = _dataObject; that->_objectField = _objectField; - that->_dataValue = _dataValue; + that->_rangeLimit = _rangeLimit; that->_sound1 = _sound1; that->_sound2 = _sound2; that->_sound3 = _sound3; that->_sayOrder = _sayOrder; - that->_spinBoxValue = _spinBoxValue; + that->_singleValue = _singleValue; + that->_valueRange2 = _valueRange2; that->_repeatString = _repeatString; that->_expireTimeout = _expireTimeout; that->_mute = _mute; @@ -83,8 +93,9 @@ void NotificationItem::saveState(QSettings* settings) const settings->setValue(QLatin1String("CurrentLanguage"), getCurrentLanguage()); settings->setValue(QLatin1String("ObjectField"), getObjectField()); settings->setValue(QLatin1String("DataObject"), getDataObject()); - settings->setValue(QLatin1String("Value"), getValue()); - settings->setValue(QLatin1String("ValueSpinBox"), getSpinBoxValue()); + settings->setValue(QLatin1String("RangeLimit"), range()); + settings->setValue(QLatin1String("Value1"), singleValue()); + settings->setValue(QLatin1String("Value2"), valueRange2()); settings->setValue(QLatin1String("Sound1"), getSound1()); settings->setValue(QLatin1String("Sound2"), getSound2()); settings->setValue(QLatin1String("Sound3"), getSound3()); @@ -102,12 +113,13 @@ void NotificationItem::restoreState(QSettings* settings) setCurrentLanguage(settings->value(QLatin1String("CurrentLanguage"), tr("")).toString()); setDataObject(settings->value(QLatin1String("DataObject"), tr("")).toString()); setObjectField(settings->value(QLatin1String("ObjectField"), tr("")).toString()); - setValue(settings->value(QLatin1String("Value"), tr("")).toString()); + setRange(settings->value(QLatin1String("RangeLimit"), tr("")).toString()); setSound1(settings->value(QLatin1String("Sound1"), tr("")).toString()); setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); - setSpinBoxValue(settings->value(QLatin1String("ValueSpinBox"), tr("")).toDouble()); + setSingleValue(settings->value(QLatin1String("Value1"), tr("")).toDouble()); + setValueRange2(settings->value(QLatin1String("Value2"), tr("")).toDouble()); setRetryString(settings->value(QLatin1String("Repeat"), tr("")).toString()); setLifetime(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); setMute(settings->value(QLatin1String("Mute"), tr("")).toInt()); @@ -120,12 +132,13 @@ void NotificationItem::seriaize(QDataStream& stream) stream << this->_currentLanguage; stream << this->_dataObject; stream << this->_objectField; - stream << this->_dataValue; + stream << this->_rangeLimit; stream << this->_sound1; stream << this->_sound2; stream << this->_sound3; stream << this->_sayOrder; - stream << this->_spinBoxValue; + stream << this->_singleValue; + stream << this->_valueRange2; stream << this->_repeatString; stream << this->_expireTimeout; stream << this->_mute; @@ -137,12 +150,13 @@ void NotificationItem::deseriaize(QDataStream& stream) stream >> this->_currentLanguage; stream >> this->_dataObject; stream >> this->_objectField; - stream >> this->_dataValue; + stream >> this->_rangeLimit; stream >> this->_sound1; stream >> this->_sound2; stream >> this->_sound3; stream >> this->_sayOrder; - stream >> this->_spinBoxValue; + stream >> this->_singleValue; + stream >> this->_valueRange2; stream >> this->_repeatString; stream >> this->_expireTimeout; stream >> this->_mute; @@ -195,145 +209,192 @@ void NotificationItem::disposeExpireTimer() { } } +#define missed "missed sound" +#define CHECK_ADD_SOUND(n) ((!_missedSound##n) ? getSound##n() : (missed#n)) +#define CHECK_REPLACE_SOUND(n) ((!_missedSound##n) ? str.replace(missed#n, getSound##n()) : (missed#n)) + QString NotificationItem::parseNotifyMessage() { // tips: // check of *.wav files exist needed for playing phonon queues; // if phonon player don't find next file in queue, it buzz - QString str,str1; - str1= getSayOrder(); - str = QString("%L1 ").arg(getSpinBoxValue()); - int position = 0xFF; + QString str; + QString value; + QString sayOrder = getSayOrder(); + UAVObjectField* field = getUAVObjectField(); + if (UAVObjectField::ENUM == field->getType()) { + Q_ASSERT(singleValue() < field->getOptions().size()); + value = QString("%L1").arg(field->getOptions().at(singleValue())); + } else { + value = QString("%L1").arg(singleValue()); + } + + int position = -1; // default don't play value wav file + // generate queue of sound files to play _messageSequence.clear(); - checkSoundFilesExisting(); + bool _missedSound1 = false; + bool _missedSound2 = false; + bool _missedSound3 = false; + + checkSoundFilesExisting(_missedSound1, _missedSound2, _missedSound3); + str = CHECK_ADD_SOUND(1)+" "+CHECK_ADD_SOUND(2)+" "+CHECK_ADD_SOUND(3); if(!_messageSequence.size()) { qNotifyDebug() << "no any files in message queue"; } - switch(str1.at(0).toAscii()) + sayOrder = sayOrder.trimmed(); + switch(sayOrder.at(0).toUpper().toAscii()) { - case 'N'://NEVER: - str = getSound1()+" "+getSound2()+" "+getSound3(); - position = 0xFF; - break; - - case 'B'://BEFORE: - str = QString("%L1 ").arg(getSpinBoxValue())+getSound1()+" "+getSound2()+" "+getSound3(); - position = 0; - break; + case 'B'://BEFORE: + CHECK_REPLACE_SOUND(1); + CHECK_REPLACE_SOUND(2); + CHECK_REPLACE_SOUND(3); + str.prepend(value + " "); + position = 0; + break; case 'A'://AFTER: - switch(str1.at(6).toAscii()) + switch(sayOrder.at(6).toLower().toAscii()) { case 'f': - str = getSound1()+QString(" %L1 ").arg(getSpinBoxValue())+getSound2()+" "+getSound3(); + str = CHECK_ADD_SOUND(1)+" "+value+" "+CHECK_ADD_SOUND(2)+" "+CHECK_ADD_SOUND(3); position = 1; break; + case 's': - str = getSound1()+" "+getSound2()+QString(" %L1").arg(getSpinBoxValue())+" "+getSound3(); + str = CHECK_ADD_SOUND(1)+" "+CHECK_ADD_SOUND(2)+" "+value+" "+CHECK_ADD_SOUND(3); position = 2; break; + case 't': - str = getSound1()+" "+getSound2()+" "+getSound3()+QString(" %L1").arg(getSpinBoxValue()); + CHECK_REPLACE_SOUND(1); + CHECK_REPLACE_SOUND(2); + CHECK_REPLACE_SOUND(3); + str.append(" "+value); position = 3; break; } break; + + default: + CHECK_REPLACE_SOUND(1); + CHECK_REPLACE_SOUND(2); + CHECK_REPLACE_SOUND(3); + break; } - if(position != 0xFF) - { - QStringList numberParts = QString("%1").arg(getSpinBoxValue()).trimmed().split("."); - QStringList numberFiles; + if(-1 == position) { + qNotifyDebug() << "NotificationItem::parseNotifyMessage() | value position undefined"; + return str; + } - if((numberParts.at(0).size()==1) || (numberParts.at(0).toInt()<20)) - { - //if(numberParts.at(0)!="0") - numberFiles.append(numberParts.at(0)); - } else { - int i=0; - if(numberParts.at(0).right(2).toInt()<20 && numberParts.at(0).right(2).toInt()!=0) { - if(numberParts.at(0).right(2).toInt()<10) - numberFiles.append(numberParts.at(0).right(1)); - else - numberFiles.append(numberParts.at(0).right(2)); - i=2; - } - for(;igetType()) return str; - if(1 < numberParts.size()) { - numberFiles.append("point"); - if((numberParts.at(1).size()==1)) - numberFiles.append(numberParts.at(1)); - else { - if(numberParts.at(1).left(1)=="0") - numberFiles.append(numberParts.at(1).left(1)); - else - numberFiles.append(numberParts.at(1).left(1)+'0'); - numberFiles.append(numberParts.at(1).right(1)); - } + QStringList numberParts = value.trimmed().split("."); + QStringList digitWavs; + + if ( (numberParts.at(0).size() == 1) || (numberParts.at(0).toInt() < 20) ) { + // [1] check, is this number < 20, these numbers played by one wav file + digitWavs.append(numberParts.at(0)); + } else { + int i=0; + // [2] store two lowest digits of number + int num = numberParts.at(0).right(2).toInt(); + if (num < 20 && num != 0) { + // store eighter number in range [0...10) or in range [10...20) + digitWavs.append(numberParts.at(0).right(1 + num/11)); + i=2; + } + // [3] prepend 100 and 1000 digits of number + for (;i number < 1 + digitWavs.append(numberParts.at(1)); + } else { + // append fractional part of number + QString left = numberParts.at(1).left(1); + (left == "0") ? digitWavs.append(left) : digitWavs.append(left + '0'); + digitWavs.append(numberParts.at(1).right(1)); + } + } + foreach(QString fileName, digitWavs) { + fileName+=".wav"; + QString filePath = QDir::toNativeSeparators(getSoundCollectionPath()+"/"+ getCurrentLanguage()+"/"+fileName); + if(QFile::exists(filePath)) + _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+ "/"+getCurrentLanguage()+"/"+fileName)); + else { + if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName))) + _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName)); + else { + _messageSequence.clear(); + break; // if no some of *.wav files, then don't play number! } + } } return str; } +UAVObjectField* NotificationItem::getUAVObjectField() { + return getUAVObject()->getField(getObjectField()); +} -void NotificationItem::checkSoundFilesExisting() { +UAVDataObject* NotificationItem::getUAVObject() { + return dynamic_cast((ExtensionSystem::PluginManager::instance()->getObject())->getObject(getDataObject())); +} + + +void NotificationItem::checkSoundFilesExisting(bool& missed1, bool& missed2, bool& missed3) +{ if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav")); - else + else { if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav")); + else + missed1 = true; + } - - if(!getSound2().size()) - { + if(getSound2().size()) { if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav")); - else + else { if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav")); + else + missed2 = true; + } } - if(!getSound3().size()) - { + if(getSound3().size()) { if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav")); - else + else { if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav"))) _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav")); + else + missed3 = true; + } } } diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index e7878c3da..fa55cfc42 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -289,8 +289,8 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA QString direction; QString fieldName; - threshold = notification->getSpinBoxValue(); - direction = notification->getValue(); + threshold = notification->singleValue(); + direction = notification->range(); fieldName = notification->getObjectField(); UAVObjectField* field = object->getField(fieldName); @@ -311,6 +311,11 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA case 'L': condition = (value < threshold); break; + + case 'R': + condition = (value > threshold) && (value < notification->valueRange2()); + break; + } if (!condition) diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index a1122f078..305e5e13e 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -39,30 +39,58 @@ #include #include #include +#include +#include #include "notifyplugin.h" #include "notifyitemdelegate.h" #include "notifytablemodel.h" #include "notifylogging.h" + +static const char* cStrBefore1st = "Before first"; +static const char* cStrBefore2nd = "Before second"; +static const char* cStrAfter2nd = "After second"; + +static const char* cStrEqualTo = "Equal to"; +static const char* cStrLargeThan = "Large than"; +static const char* cStrLowerThan = "Lower than"; +static const char* cStrInRange = "In range"; + + +//----------------------------------------------------------------------------- NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) : IOptionsPage(parent) , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) , owner(qobject_cast(parent)) , currentCollectionPath("") + , _valueRange(NULL) + , _sayOrder(NULL) + , _fieldValue(NULL) + , _fieldType(-1) + , _form(NULL) { } +//----------------------------------------------------------------------------- NotifyPluginOptionsPage::~NotifyPluginOptionsPage() { } //creates options page widget (uses the UI file) + +//----------------------------------------------------------------------------- QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) { options_page.reset(new Ui::NotifyPluginOptionsPage()); //main widget - QWidget *optionsPageWidget = new QWidget; + QWidget* optionsPageWidget = new QWidget; + //if(!_fieldValue.isNull()) + _fieldValue = NULL; + _valueRange = NULL; + _fieldType = -1; + //save ref to form, needed for binding dynamic fields in future + _form = optionsPageWidget; //main layout options_page->setupUi(optionsPageWidget); @@ -71,35 +99,161 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); - // Fills the combo boxes for the UAVObjects - QList< QList > objList = objManager.getDataObjects(); - foreach (QList list, objList) { - foreach (UAVDataObject* obj, list) { - options_page->UAVObject->addItem(obj->getName()); - } - } - connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + + connect(this, SIGNAL(updateNotifications(QList)), owner, SLOT(updateNotificationList(QList))); //connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); - -// privListNotifications = ((qobject_cast(parent))->getListNotifications()); privListNotifications = owner->getListNotifications(); - updateConfigView(owner->getCurrentNotification()); + // [1] + addDynamicValueLayout(); + _selectedNotification = owner->getCurrentNotification(); + // [2] + updateConfigView(_selectedNotification); initRulesTable(); initButtons(); initPhononPlayer(); +// _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(0, 0, QModelIndex()), +// QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + return optionsPageWidget; } +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::apply() +{ + getOptionsPageValues(owner->getCurrentNotification()); + owner->setEnableSound(options_page->chkEnableSound->isChecked()); + emit updateNotifications(privListNotifications); +} + +void NotifyPluginOptionsPage::finish() +{ + + disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); + + disconnect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + if (notifySound) { + notifySound->stop(); + notifySound->clear(); + } +} + +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::addDynamicValueLayout() +{ + NotificationItem* curr = owner->getCurrentNotification(); + Q_ASSERT(curr); + options_page->dynamicValueLayout->addWidget(new QLabel("Say order ", _form)); + + _sayOrder = new QComboBox(_form); + options_page->dynamicValueLayout->addWidget(_sayOrder); + QStringList sayOrderValues; + sayOrderValues << cStrBefore1st << cStrBefore2nd << cStrAfter2nd; + _sayOrder->addItems(sayOrderValues); + + options_page->dynamicValueLayout->addWidget(new QLabel("Value is ", _form)); + + UAVDataObject* obj = dynamic_cast(objManager.getObject(curr->getDataObject())); + UAVObjectField* field = obj->getField(curr->getObjectField()); + Q_ASSERT(obj); + Q_ASSERT(field); + _valueRange = new QComboBox(_form); + options_page->dynamicValueLayout->addWidget(_valueRange); + + addDynamicField(field); +} + +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::resetValueRange() +{ + _fieldValue = new QLineEdit(_form); + (static_cast(_fieldValue))->setInputMask("999.99 - 999.99;"); + (static_cast(_fieldValue))->setText("0000000000"); + (static_cast(_fieldValue))->setCursorPosition(0); +} + +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::on_rangeValue_indexChanged(QString rangeStr) +{ + Q_ASSERT(_fieldValue); + if(rangeStr == cStrInRange) { + Q_ASSERT(_fieldValue); + options_page->dynamicValueLayout->removeWidget(_fieldValue); + resetValueRange(); + options_page->dynamicValueLayout->addWidget(_fieldValue); + + // _fieldType = -1; + // addDynamicField(field); + } +} + +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) +{ + //qDebugNotify_if(!objField || !parent) << "null input params"; + Q_ASSERT(objField); + if(objField->getType() == _fieldType) { + if(QComboBox* fieldValue = dynamic_cast(_fieldValue)) { + fieldValue->clear(); + QStringList enumValues(objField->getOptions()); + fieldValue->addItems(enumValues); + } + return; + } + // check if dynamic fileld already settled, + // so if its exists remove it and install new field + if(_fieldValue) + options_page->dynamicValueLayout->removeWidget(_fieldValue); + + disconnect(_valueRange, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_rangeValue_indexChanged(QString))); + + _valueRange->clear(); + QStringList rangeValues; + if(UAVObjectField::ENUM == objField->getType()) { + rangeValues << cStrEqualTo << cStrInRange; + _valueRange->addItems(rangeValues); + } + else { + rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; + _valueRange->addItems(rangeValues); + connect(_valueRange, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_rangeValue_indexChanged(QString))); + } + + + _fieldType = objField->getType(); + switch(_fieldType) + { + case UAVObjectField::ENUM: + { + _fieldValue = new QComboBox(_form); + QStringList enumValues(objField->getOptions()); + (dynamic_cast(_fieldValue))->addItems(enumValues); + } + break; + + default: + if(_valueRange->currentText() == cStrInRange) { + resetValueRange(); + } else { + _fieldValue = new QSpinBox(_form); + } + break; + }; + options_page->dynamicValueLayout->addWidget(_fieldValue); +} + +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initButtons() { options_page->chkEnableSound->setChecked(owner->getEnableSound()); @@ -114,6 +268,7 @@ void NotifyPluginOptionsPage::initButtons() connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initPhononPlayer() { notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); @@ -122,6 +277,8 @@ void NotifyPluginOptionsPage::initPhononPlayer() connect(notifySound.data(), SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); } + +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initRulesTable() { qNotifyDebug_if(_notifyRulesModel.isNull()) << "_notifyRulesModel.isNull())"; @@ -134,8 +291,8 @@ void NotifyPluginOptionsPage::initRulesTable() this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); connect(this, SIGNAL(entryUpdated(int)), _notifyRulesModel.data(), SLOT(entryUpdated(int))); - connect(this, SIGNAL(entryAdded(int)), - _notifyRulesModel.data(), SLOT(entryAdded(int))); +// connect(this, SIGNAL(entryAdded(int)), +// _notifyRulesModel.data(), SLOT(entryAdded(int))); options_page->notifyRulesView->setModel(_notifyRulesModel.data()); options_page->notifyRulesView->setSelectionModel(_notifyRulesSelection); @@ -150,12 +307,12 @@ void NotifyPluginOptionsPage::initRulesTable() options_page->notifyRulesView->setAcceptDrops(true); options_page->notifyRulesView->setDropIndicatorShown(true); options_page->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); - - } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { + Q_ASSERT(notification); notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); notification->setDataObject(options_page->UAVObject->currentText()); @@ -163,48 +320,51 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio notification->setSound1(options_page->Sound1->currentText()); notification->setSound2(options_page->Sound2->currentText()); notification->setSound3(options_page->Sound3->currentText()); - notification->setSayOrder(options_page->SayOrder->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); -} - -/*! -* Called when the user presses apply or OK. -* Saves the current values -*/ -void NotifyPluginOptionsPage::apply() -{ - getOptionsPageValues(owner->getCurrentNotification()); - owner->setEnableSound(options_page->chkEnableSound->isChecked()); - emit updateNotifications(privListNotifications); -} - -void NotifyPluginOptionsPage::finish() -{ - disconnect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - if (notifySound) { - notifySound->stop(); - notifySound->clear(); + notification->setSayOrder(_sayOrder->currentText()); + notification->setRange(_valueRange->currentText()); + if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + notification->setSingleValue(spinValue->value()); + else { + if(QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) + notification->setSingleValue(comboBoxValue->currentIndex()); + else { + if(QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { + QString str = rangeValue->text(); + QStringList range = str.split('-'); + notification->setSingleValue(range.at(0).toDouble()); + notification->setValueRange2(range.at(1).toDouble()); + } + } } } + +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::onUAVField_indexChanged(QString field) { + _fieldType = -1; + UAVDataObject* obj = dynamic_cast( objManager.getObject(options_page->UAVObject->currentText())); + addDynamicField(obj->getField(field)); + +} + ////////////////////////////////////////////////////////////////////////////// // Fills in the combo box when value is changed in the // combo box ////////////////////////////////////////////////////////////////////////////// void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { - options_page->UAVObjectField->clear(); - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager* objManager = pm->getObject(); - UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); + _fieldType = -1; + UAVDataObject* obj = dynamic_cast( objManager.getObject(val) ); QList fieldList = obj->getFields(); + disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); + options_page->UAVObjectField->clear(); foreach (UAVObjectField* field, fieldList) { options_page->UAVObjectField->addItem(field->getName()); } + connect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); + addDynamicField(fieldList.at(0)); } -// locate collection folder on disk +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) { QDir dirPath(path); @@ -213,7 +373,7 @@ void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) options_page->SoundCollectionList->addItems(listDirCollections); } - +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) { options_page->SoundCollectionList->setCurrentIndex(index); @@ -238,6 +398,7 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) { //Q_ASSERT(Phonon::ErrorState != newstate); @@ -253,25 +414,29 @@ void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon:: } } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::onFinishedPlaying() { notifySound->clear(); } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() { NotificationItem* notification = NULL; if (-1 == _notifyRulesSelection->currentIndex().row()) - return; + return; notifySound->clearQueue(); notification = privListNotifications.at(_notifyRulesSelection->currentIndex().row()); notification->parseNotifyMessage(); QStringList sequence = notification->getMessageSequence(); Q_ASSERT(!!sequence.size()); - foreach(QString item, sequence) - notifySound->enqueue(Phonon::MediaSource(item)); - + qNotifyDebug() << "on_buttonTestSoundNotification_clicked"; + foreach(QString item, sequence) { + qNotifyDebug() << item; + notifySound->enqueue(Phonon::MediaSource(item)); + } notifySound->play(); } @@ -284,90 +449,132 @@ void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) audioOutput->setMuted(state1); } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { + Q_ASSERT(notification); + disconnect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_UAVObject_indexChanged(QString))); + disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), + this, SLOT(onUAVField_indexChanged(QString))); + QString path = notification->getSoundCollectionPath(); if (path == "") { - //QDir dir = QDir::currentPath(); - //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; - path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); + //QDir dir = QDir::currentPath(); + //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; + path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); } options_page->SoundDirectoryPathChooser->setPath(path); if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); } else { - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + } + + + // Fills the combo boxes for the UAVObjects + QList< QList > objList = objManager.getDataObjects(); + foreach (QList list, objList) { + foreach (UAVDataObject* obj, list) { + options_page->UAVObject->addItem(obj->getName()); + } } if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ - options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); + options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); } - // Now load the object field values: options_page->UAVObjectField->clear(); QString uavDataObject = notification->getDataObject(); UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); if (obj != NULL ) { - QList fieldList = obj->getFields(); - foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); - } + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } } if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { - options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); + options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); } if (-1 != options_page->Sound1->findText(notification->getSound1())) { - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); - - // don't show item if it wasn't find in stored location - //options_page->Sound1->setCurrentIndex(-1); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); } if (-1 != options_page->Sound2->findText(notification->getSound2())) { - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); - - // don't show item if it wasn't find in stored location - //options_page->Sound2->setCurrentIndex(-1); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); } if (-1 != options_page->Sound3->findText(notification->getSound3())) { - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); } - if (-1 != options_page->Value->findText(notification->getValue())) { - options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); + if (-1 != _valueRange->findText(notification->range())) { + _valueRange->setCurrentIndex(_valueRange->findText(notification->range())); } - if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { - options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); + if (-1 != _sayOrder->findText(notification->getSayOrder())) { + _sayOrder->setCurrentIndex(_sayOrder->findText(notification->getSayOrder())); } - options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); + setDynamicValueField(notification); + + connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_UAVObject_indexChanged(QString))); + connect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), + this, SLOT(onUAVField_indexChanged(QString))); + } +//----------------------------------------------------------------------------- +void NotifyPluginOptionsPage::setDynamicValueField(NotificationItem* notification) +{ + if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + spinValue->setValue(notification->singleValue()); + else { + if(QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) + comboBoxValue->setCurrentIndex(notification->singleValue()); + else { + if(QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { + resetValueRange(); + rangeValue->setText(QString("%1%2").arg(notification->singleValue()) + .arg(notification->valueRange2())); + } else { + qNotifyDebug() << "NotifyPluginOptionsPage::setDynamicValueField | unknown _fieldValue: " << _fieldValue; + } + + } + } +} + +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) { bool select = false; notifySound->stop(); if (selected.indexes().size()) { - select = true; - updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); + select = true; + _selectedNotification = privListNotifications.at(selected.indexes().at(0).row()); + updateConfigView(_selectedNotification); + UAVDataObject* obj = dynamic_cast( objManager.getObject(options_page->UAVObject->currentText())); + UAVObjectField* field = obj->getField(options_page->UAVObjectField->currentText()); + addDynamicField(field); + setDynamicValueField(_selectedNotification); } options_page->buttonModify->setEnabled(select); @@ -375,7 +582,7 @@ void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemS options_page->buttonPlayNotification->setEnabled(select); } - +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() { NotificationItem* notification = new NotificationItem; @@ -392,34 +599,36 @@ void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); notification->setDataObject(options_page->UAVObject->currentText()); notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + notification->setRange(_valueRange->currentText()); + + if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + notification->setSingleValue(spinValue->value()); if (options_page->Sound1->currentText().size() > 0) - notification->setSound1(options_page->Sound1->currentText()); + notification->setSound1(options_page->Sound1->currentText()); notification->setSound2(options_page->Sound2->currentText()); notification->setSound3(options_page->Sound3->currentText()); -if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) - || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { + if ( ((!options_page->Sound2->currentText().size()) && (_sayOrder->currentText()=="After second")) + || ((!options_page->Sound3->currentText().size()) && (_sayOrder->currentText()=="After third")) ) { return; } else { - notification->setSayOrder(options_page->SayOrder->currentText()); + notification->setSayOrder(_sayOrder->currentText()); } - privListNotifications.append(notification); - emit entryAdded(privListNotifications.size() - 1); + + _notifyRulesModel->entryAdded(notification); _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } - +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() { _notifyRulesModel->removeRow(_notifyRulesSelection->currentIndex().row()); if (!_notifyRulesModel->rowCount() && (_notifyRulesSelection->currentIndex().row() > 0 - && _notifyRulesSelection->currentIndex().row() < _notifyRulesModel->rowCount()) ) + && _notifyRulesSelection->currentIndex().row() < _notifyRulesModel->rowCount()) ) { options_page->buttonDelete->setEnabled(false); options_page->buttonModify->setEnabled(false); @@ -428,6 +637,7 @@ void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() } +//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() { NotificationItem* notification = new NotificationItem; diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig index b91317c9f..2ff775e31 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp.orig @@ -43,13 +43,13 @@ #include "notifyplugin.h" #include "notifyitemdelegate.h" #include "notifytablemodel.h" +#include "notifylogging.h" NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) : IOptionsPage(parent) , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) , owner(qobject_cast(parent)) , currentCollectionPath("") - , privListNotifications((qobject_cast(parent))->getListNotifications()) { } @@ -64,22 +64,53 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) //main widget QWidget *optionsPageWidget = new QWidget; //main layout + options_page->setupUi(optionsPageWidget); + + listSoundFiles.clear(); + + options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); + options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); + + // Fills the combo boxes for the UAVObjects + QList< QList > objList = objManager.getDataObjects(); + foreach (QList list, objList) { + foreach (UAVDataObject* obj, list) { + options_page->UAVObject->addItem(obj->getName()); + } + } + +<<<<<<< Updated upstream + connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); + connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); + connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); +======= + options_page = new Ui::NotifyPluginOptionsPage(); + //main widget + QWidget *optionsPageWidget = new QWidget; + //main layout options_page->setupUi(optionsPageWidget); delegateItems.clear(); listSoundFiles.clear(); + options_page->horizontalLayout_3->addWidget(new QPushButton("testtt")); delegateItems << "Repeat Once" << "Repeat Instantly" << "Repeat 10 seconds" << "Repeat 30 seconds" << "Repeat 1 minute"; + options_page->chkEnableSound->setChecked(owner->getEnableSound()); options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); + + + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + objManager = pm->getObject(); + // Fills the combo boxes for the UAVObjects - QList< QList > objList = objManager.getDataObjects(); + QList< QList > objList = objManager->getDataObjects(); foreach (QList list, objList) { foreach (UAVDataObject* obj, list) { options_page->UAVObject->addItem(obj->getName()); @@ -88,95 +119,122 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); + connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); + connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); +// connect(options_page->buttonTestSound1, SIGNAL(clicked()), this, SLOT(on_buttonTestSound1_clicked())); +// connect(options_page->buttonTestSound2, SIGNAL(clicked()), this, SLOT(on_buttonTestSound2_clicked())); + connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); + connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - connect(this, SIGNAL(updateNotifications(QList)), - owner, SLOT(updateNotificationList(QList))); + + connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); + connect(this, SIGNAL(updateNotifications(QList)), + owner, SLOT(updateNotificationList(QList))); connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); //emit resetNotification(); - privListNotifications.clear(); - for (int i = 0; i < owner->getListNotifications().size(); ++i) { - NotificationItem* notification = new NotificationItem(); - owner->getListNotifications().at(i)->copyTo(notification); - privListNotifications.append(notification); + privListNotifications.clear(); + + for (int i = 0; i < owner->getListNotifications().size(); ++i) { + NotifyPluginConfiguration* notification = new NotifyPluginConfiguration(); + owner->getListNotifications().at(i)->copyTo(notification); + privListNotifications.append(notification); } - updateConfigView(owner->getCurrentNotification()); + updateConfigView(owner->getCurrentNotification()); - initButtons(); - initRulesTableModel(); - initRulesTableView(); - initPhononPlayer(); + options_page->chkEnableSound->setChecked(owner->getEnableSound()); - return optionsPageWidget; + QStringList headerStrings; + headerStrings << "Name" << "Repeats" << "Lifetime,sec"; +>>>>>>> Stashed changes + + connect(this, SIGNAL(updateNotifications(QList)), + owner, SLOT(updateNotificationList(QList))); + //connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); + + +// privListNotifications = ((qobject_cast(parent))->getListNotifications()); + privListNotifications = owner->getListNotifications(); + + updateConfigView(owner->getCurrentNotification()); + + initRulesTable(); + initButtons(); + initPhononPlayer(); + + return optionsPageWidget; } void NotifyPluginOptionsPage::initButtons() { - options_page->chkEnableSound->setChecked(owner->getEnableSound()); - connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); + options_page->chkEnableSound->setChecked(owner->getEnableSound()); + connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); - options_page->buttonModify->setEnabled(false); - options_page->buttonDelete->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); - connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); - connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); - connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); + options_page->buttonModify->setEnabled(false); + options_page->buttonDelete->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); + connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); + connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); + connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); } void NotifyPluginOptionsPage::initPhononPlayer() { - notifySound = Phonon::createPlayer(Phonon::NotificationCategory); - connect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), + notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); + connect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - connect(notifySound, SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); + connect(notifySound.data(), SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); } -void NotifyPluginOptionsPage::initRulesTableModel() +void NotifyPluginOptionsPage::initRulesTable() { - notifyRulesModel.reset(new NotifyTableModel(&privListNotifications)); - notifyRulesSelection = new QItemSelectionModel(notifyRulesModel.data()); - connect(notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), + qNotifyDebug_if(_notifyRulesModel.isNull()) << "_notifyRulesModel.isNull())"; + qNotifyDebug_if(!_notifyRulesSelection) << "_notifyRulesSelection.isNull())"; + //QItemSelectionModel* selection = _notifyRulesSelection.take(); + _notifyRulesModel.reset(new NotifyTableModel(privListNotifications)); + _notifyRulesSelection = new QItemSelectionModel(_notifyRulesModel.data()); + + connect(_notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); connect(this, SIGNAL(entryUpdated(int)), - notifyRulesModel.data(), SLOT(entryUpdated(int))); + _notifyRulesModel.data(), SLOT(entryUpdated(int))); connect(this, SIGNAL(entryAdded(int)), - notifyRulesModel.data(), SLOT(entryAdded(int))); -} + _notifyRulesModel.data(), SLOT(entryAdded(int))); + + options_page->notifyRulesView->setModel(_notifyRulesModel.data()); + options_page->notifyRulesView->setSelectionModel(_notifyRulesSelection); + options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(this)); + + options_page->notifyRulesView->resizeRowsToContents(); + options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); + options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); + options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); + options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); + options_page->notifyRulesView->setDragEnabled(true); + options_page->notifyRulesView->setAcceptDrops(true); + options_page->notifyRulesView->setDropIndicatorShown(true); + options_page->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); -void NotifyPluginOptionsPage::initRulesTableView() -{ - options_page->notifyRulesView->setModel(notifyRulesModel.data()); - options_page->notifyRulesView->resizeRowsToContents(); - options_page->notifyRulesView->setSelectionModel(notifyRulesSelection); - options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(delegateItems,this)); - options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); - options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); - options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); - options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); - options_page->notifyRulesView->setDragEnabled(true); - options_page->notifyRulesView->setAcceptDrops(true); - options_page->notifyRulesView->setDropIndicatorShown(true); } void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setSound1(options_page->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); - notification->setSayOrder(options_page->SayOrder->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); - + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setSound1(options_page->Sound1->currentText()); + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); + notification->setSayOrder(options_page->SayOrder->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); } /*! @@ -185,19 +243,19 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio */ void NotifyPluginOptionsPage::apply() { - getOptionsPageValues(owner->getCurrentNotification()); - owner->setEnableSound(options_page->chkEnableSound->isChecked()); - emit updateNotifications(privListNotifications); + getOptionsPageValues(owner->getCurrentNotification()); + owner->setEnableSound(options_page->chkEnableSound->isChecked()); + emit updateNotifications(privListNotifications); } void NotifyPluginOptionsPage::finish() { - disconnect(notifySound,SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - if (notifySound) { - notifySound->stop(); - notifySound->clear(); - } + disconnect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(changeButtonText(Phonon::State,Phonon::State))); + if (notifySound) { + notifySound->stop(); + notifySound->clear(); + } } ////////////////////////////////////////////////////////////////////////////// @@ -205,23 +263,23 @@ void NotifyPluginOptionsPage::finish() // combo box ////////////////////////////////////////////////////////////////////////////// void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { - options_page->UAVObjectField->clear(); - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager* objManager = pm->getObject(); + options_page->UAVObjectField->clear(); + ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager* objManager = pm->getObject(); UAVDataObject* obj = dynamic_cast( objManager->getObject(val) ); QList fieldList = obj->getFields(); foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); + options_page->UAVObjectField->addItem(field->getName()); } } // locate collection folder on disk void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) { - QDir dirPath(path); - listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - options_page->SoundCollectionList->clear(); - options_page->SoundCollectionList->addItems(listDirCollections); + QDir dirPath(path); + listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + options_page->SoundCollectionList->clear(); + options_page->SoundCollectionList->addItems(listDirCollections); } @@ -230,7 +288,7 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) options_page->SoundCollectionList->setCurrentIndex(index); currentCollectionPath = options_page->SoundDirectoryPathChooser->path() - + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); + + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); QDir dirPath(currentCollectionPath); QStringList filters; @@ -238,7 +296,6 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) dirPath.setNameFilters(filters); listSoundFiles = dirPath.entryList(filters); listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); - options_page->Sound1->clear(); options_page->Sound2->clear(); options_page->Sound3->clear(); @@ -252,135 +309,122 @@ void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) { - //Q_ASSERT(Phonon::ErrorState != newstate); + //Q_ASSERT(Phonon::ErrorState != newstate); - if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { - options_page->buttonPlayNotification->setText("Play"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); - } else { - if (newstate == Phonon::PlayingState) { - options_page->buttonPlayNotification->setText("Stop"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); - } - } + if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { + options_page->buttonPlayNotification->setText("Play"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); + } else { + if (newstate == Phonon::PlayingState) { + options_page->buttonPlayNotification->setText("Stop"); + options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + } + } } void NotifyPluginOptionsPage::onFinishedPlaying() { - notifySound->clear(); + notifySound->clear(); } void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() { - NotificationItem* notification = NULL; + NotificationItem* notification = NULL; - if (-1 == notifyRulesSelection->currentIndex().row()) - return; - notifySound->clearQueue(); - notification = privListNotifications.at(notifyRulesSelection->currentIndex().row()); - notification->parseNotifyMessage(); - QStringList sequence = notification->getMessageSequence(); - Q_ASSERT(!!sequence.size()); - foreach(QString item, sequence) - notifySound->enqueue(Phonon::MediaSource(item)); + if (-1 == _notifyRulesSelection->currentIndex().row()) + return; + notifySound->clearQueue(); + notification = privListNotifications.at(_notifyRulesSelection->currentIndex().row()); + notification->parseNotifyMessage(); + QStringList sequence = notification->getMessageSequence(); + Q_ASSERT(!!sequence.size()); + foreach(QString item, sequence) + notifySound->enqueue(Phonon::MediaSource(item)); - notifySound->play(); + notifySound->play(); } void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) { - bool state1 = 1^state; + bool state1 = 1^state; - QList listOutputs = notifySound->outputPaths(); - Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); - audioOutput->setMuted(state1); + QList listOutputs = notifySound->outputPaths(); + Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); + audioOutput->setMuted(state1); } void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { QString path = notification->getSoundCollectionPath(); if (path == "") { - //QDir dir = QDir::currentPath(); - //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; - path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); + //QDir dir = QDir::currentPath(); + //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; + path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); } options_page->SoundDirectoryPathChooser->setPath(path); if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); } else { - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); } if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ - options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); + options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); } -<<<<<<< Updated upstream - // Now load the object field values: - options_page->UAVObjectField->clear(); - QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); - if (obj != NULL ) { - QList fieldList = obj->getFields(); - foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); - } - } -======= // Now load the object field values: options_page->UAVObjectField->clear(); QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast( objManager->getObject(uavDataObject/*objList.at(0).at(0)->getName()*/) ); + UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); if (obj != NULL ) { - QList fieldList = obj->getFields(); - foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); - } + QList fieldList = obj->getFields(); + foreach (UAVObjectField* field, fieldList) { + options_page->UAVObjectField->addItem(field->getName()); + } } ->>>>>>> Stashed changes if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { - options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); + options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); } if (-1 != options_page->Sound1->findText(notification->getSound1())) { - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); - // don't show item if it wasn't find in stored location - //options_page->Sound1->setCurrentIndex(-1); + // don't show item if it wasn't find in stored location + //options_page->Sound1->setCurrentIndex(-1); } if (-1 != options_page->Sound2->findText(notification->getSound2())) { - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); - // don't show item if it wasn't find in stored location - //options_page->Sound2->setCurrentIndex(-1); + // don't show item if it wasn't find in stored location + //options_page->Sound2->setCurrentIndex(-1); } if (-1 != options_page->Sound3->findText(notification->getSound3())) { - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); } else { - // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + // show item from default location + options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); } if (-1 != options_page->Value->findText(notification->getValue())) { - options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); + options_page->Value->setCurrentIndex(options_page->Value->findText(notification->getValue())); } if (-1 != options_page->SayOrder->findText(notification->getSayOrder())) { - options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); + options_page->SayOrder->setCurrentIndex(options_page->SayOrder->findText(notification->getSayOrder())); } options_page->ValueSpinBox->setValue(notification->getSpinBoxValue()); @@ -388,78 +432,81 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) { - bool select = false; - notifySound->stop(); - if (selected.indexes().size()) { - select = true; - updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); - } + bool select = false; + notifySound->stop(); + if (selected.indexes().size()) { + select = true; + updateConfigView(privListNotifications.at(selected.indexes().at(0).row())); + } - options_page->buttonModify->setEnabled(select); - options_page->buttonDelete->setEnabled(select); - options_page->buttonPlayNotification->setEnabled(select); + options_page->buttonModify->setEnabled(select); + options_page->buttonDelete->setEnabled(select); + options_page->buttonPlayNotification->setEnabled(select); } void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() { - NotificationItem* notification = new NotificationItem; + NotificationItem* notification = new NotificationItem; - if (options_page->SoundDirectoryPathChooser->path()=="") { - QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); - textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); - options_page->SoundDirectoryPathChooser->setPalette(textPalette); - options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); - return; - } + if (options_page->SoundDirectoryPathChooser->path()=="") { + QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); + textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); + options_page->SoundDirectoryPathChooser->setPalette(textPalette); + options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); + return; + } - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setValue(options_page->Value->currentText()); - notification->setSpinBoxValue(options_page->ValueSpinBox->value()); + notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); + notification->setDataObject(options_page->UAVObject->currentText()); + notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setValue(options_page->Value->currentText()); + notification->setSpinBoxValue(options_page->ValueSpinBox->value()); - if (options_page->Sound1->currentText().size() > 0) - notification->setSound1(options_page->Sound1->currentText()); + if (options_page->Sound1->currentText().size() > 0) + notification->setSound1(options_page->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); + notification->setSound2(options_page->Sound2->currentText()); + notification->setSound3(options_page->Sound3->currentText()); - if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) - || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { - return; - } else { - notification->setSayOrder(options_page->SayOrder->currentText()); - } - privListNotifications.append(notification); - emit entryAdded(privListNotifications.size() - 1); - notifyRulesSelection->setCurrentIndex(notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); +if ( ((!options_page->Sound2->currentText().size()) && (options_page->SayOrder->currentText()=="After second")) + || ((!options_page->Sound3->currentText().size()) && (options_page->SayOrder->currentText()=="After third")) ) { + return; + } else { + notification->setSayOrder(options_page->SayOrder->currentText()); + } + privListNotifications.append(notification); + emit entryAdded(privListNotifications.size() - 1); + _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() { - notifyRulesModel->removeRow(notifyRulesSelection->currentIndex().row()); - if (!notifyRulesModel->rowCount() - && (notifyRulesSelection->currentIndex().row() > 0 - && notifyRulesSelection->currentIndex().row() < notifyRulesModel->rowCount()) ) - { - options_page->buttonDelete->setEnabled(false); - options_page->buttonModify->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - } + _notifyRulesModel->removeRow(_notifyRulesSelection->currentIndex().row()); + if (!_notifyRulesModel->rowCount() + && (_notifyRulesSelection->currentIndex().row() > 0 + && _notifyRulesSelection->currentIndex().row() < _notifyRulesModel->rowCount()) ) + { + options_page->buttonDelete->setEnabled(false); + options_page->buttonModify->setEnabled(false); + options_page->buttonPlayNotification->setEnabled(false); + } } void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() { - NotificationItem* notification = new NotificationItem; - getOptionsPageValues(notification); - notification->setRepeatFlag(privListNotifications.at(notifyRulesSelection->currentIndex().row())->getRepeatFlag()); - privListNotifications.replace(notifyRulesSelection->currentIndex().row(),notification); - entryUpdated(notifyRulesSelection->currentIndex().row()); + NotificationItem* notification = new NotificationItem; + getOptionsPageValues(notification); + notification->setRetryString(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryString()); + notification->setLifetime(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->lifetime()); + notification->setMute(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->mute()); + + privListNotifications.replace(_notifyRulesSelection->currentIndex().row(),notification); + entryUpdated(_notifyRulesSelection->currentIndex().row()); } diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 9e49e89ec..f4a29ae41 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -42,7 +42,8 @@ #include #include #include -//#include "notifytablemodel.h" +#include +#include class NotifyTableModel; class NotificationItem; @@ -65,8 +66,6 @@ public: QString category() const { return QLatin1String("Notify Plugin");} QString trCategory() const { return tr("Notify Plugin");} - - QWidget *createPage(QWidget *parent); void apply(); void finish(); @@ -75,13 +74,39 @@ public: void updateConfigView(NotificationItem* notification); void getOptionsPageValues(NotificationItem* notification); +signals: + void updateNotifications(QList list); + //void resetNotification(void); + void entryUpdated(int index); + private: Q_DISABLE_COPY(NotifyPluginOptionsPage) + void resetValueRange(); + void setDynamicValueField(NotificationItem* notification); + void addDynamicField(UAVObjectField* objField); + void addDynamicValueLayout(); void initButtons(); void initPhononPlayer(); void initRulesTable(); +private slots: + void on_buttonTestSoundNotification_clicked(); + + void on_buttonAddNotification_clicked(); + void on_buttonDeleteNotification_clicked(); + void on_buttonModifyNotification_clicked(); + void on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ); + void on_soundLanguage_indexChanged(int index); + void on_buttonSoundFolder_clicked(const QString& path); + void on_UAVObject_indexChanged(QString val); + void onUAVField_indexChanged(QString val); + void changeButtonText(Phonon::State newstate, Phonon::State oldstate); + void on_chkEnableSound_toggled(bool state); + void on_rangeValue_indexChanged(QString); + + void onFinishedPlaying(void); + private: UAVObjectManager& objManager; SoundNotifyPlugin* owner; @@ -99,28 +124,12 @@ private: QScopedPointer options_page; -signals: - void updateNotifications(QList list); - //void resetNotification(void); - void entryUpdated(int index); - void entryAdded(int position); - - -private slots: - void on_buttonTestSoundNotification_clicked(); - - void on_buttonAddNotification_clicked(); - void on_buttonDeleteNotification_clicked(); - void on_buttonModifyNotification_clicked(); - void on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ); - void on_soundLanguage_indexChanged(int index); - void on_buttonSoundFolder_clicked(const QString& path); - void on_UAVObject_indexChanged(QString val); - void changeButtonText(Phonon::State newstate, Phonon::State oldstate); - void on_chkEnableSound_toggled(bool state); - - void onFinishedPlaying(void); - + QComboBox* _valueRange; + QComboBox* _sayOrder; + QWidget* _fieldValue; + int _fieldType; + QWidget* _form; + NotificationItem* _selectedNotification; }; #endif // NOTIFYPLUGINOPTIONSPAGE_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui index 4645bd14a..23d05c2a0 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui @@ -6,7 +6,7 @@ 0 0 - 589 + 570 453 @@ -19,531 +19,364 @@ Form - - - - 10 - 10 - 551 - 81 - + + + QLayout::SetMinimumSize - - Sound Collection - - - - - 10 - 20 - 531 - 51 - - - - - 6 + + + + QLayout::SetFixedSize - - - - Language + + + + + 0 + 0 + - - - - - - true + + Sound Collection - - - 75 - 23 - - - - - - - - - 147 - 0 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + + true + + + + 75 + 23 + + + + + 550 + 16777215 + + + + + + + + + 0 + 0 + + + + Language + + + + + + + + 147 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Select the sound collection</span></p></body></html> + + + + + + + + + + + + + + + + + DataObject + + + + + + + + 0 + 0 + + + + + + + + ObjectField + + + + + + + + 0 + 0 + - - - - - - 10 - 220 - 551 - 211 - - - - Sound Notifications - - - - - 10 - 180 - 531 - 26 - - - + + + + + Qt::Horizontal + + + + + + + + - + + + + 0 + 0 + + - Enable Sounds + Sound1: - - - Qt::Horizontal + + + + 0 + 0 + - + - 138 - 20 + 110 + 0 - - - - - - Play - - - - :/notify/images/play.png:/notify/images/play.png - - - - - - - Qt::Horizontal - - + - 40 - 20 + 16777215 + 16777215 - + - - - Qt::Horizontal + + + + 0 + 0 + - + + Sound2: + + + + + + + + 0 + 0 + + + - 40 - 20 + 110 + 0 - - - - - - Add - - - - :/notify/images/add.png:/notify/images/add.png + + + 16777215 + 16777215 + - - - Modify + + + + 0 + 0 + - - - :/notify/images/modify.png:/notify/images/modify.png + + Sound3: - - - Delete + + + + 0 + 0 + - - - :/utils/images/removesubmitfield.png:/utils/images/removesubmitfield.png + + + 110 + 0 + + + + + 16777215 + 16777215 + - - - - - 10 - 20 - 531 - 151 - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - 22 - - - 22 - - - - - - - 10 - 100 - 551 - 31 - - - - - - - DataObject - - - - - - - - 0 - 0 - - - - - - - - ObjectField - - - - - - - - 0 - 0 - - - - - - - - - - 7 - 130 - 551 - 20 - - - - Qt::Horizontal - - - - - - 10 - 180 - 551 - 31 - - - - - - - - 0 - 0 - - - - Sound1: - - - - - - - - 0 - 0 - - - - - 110 - 0 - - - - - 16777215 - 16777215 - - - - - - - - Sound2: - - - - - - - - 0 - 0 - - - - - 110 - 0 - - - - - 16777215 - 16777215 - - - - - - - - Sound3: - - - - - - - - 0 - 0 - - - - - 110 - 0 - - - - - 16777215 - 16777215 - - - - - - - - - - 10 - 150 - 551 - 31 - - - - - - - true - - - - 0 - 0 - - - - - 40 - 0 - - - - Value is - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 110 - 16777215 - - + + + + + + + + Sound Notifications + + - - Equal to - + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + 22 + + + 22 + + - - Greater than - + + + + + Enable Sounds + + + + + + + Qt::Horizontal + + + + 138 + 20 + + + + + + + + Play + + + + :/notify/images/play.png:/notify/images/play.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + :/notify/images/add.png:/notify/images/add.png + + + + + + + Modify + + + + :/notify/images/modify.png:/notify/images/modify.png + + + + + + + Delete + + + + :/utils/images/removesubmitfield.png:/utils/images/removesubmitfield.png + + + + - - - Less than - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 170 - 16777215 - - - - 2 - - - 9999.899999999999636 - - - 1.000000000000000 - - - - - - - - 0 - 0 - - - - Say Order - - - - - - - - 0 - 0 - - - - - 110 - 16777215 - - - - Select if the value of the object should be spoken and if so, either before the configured sound or after it. - - - - Never - - - - - Before first - - - - - After first - - - - - After second - - - - - After third - - - - - - + + + + diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index 0c2337437..138af106b 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -162,9 +162,13 @@ void NotifyTableModel::entryUpdated(int offset) emit dataChanged(idx, idx); } -void NotifyTableModel::entryAdded(int position) +void NotifyTableModel::entryAdded(NotificationItem* item) { - insertRows(position, 1,QModelIndex()); + insertRows(rowCount(), 1, QModelIndex()); + NotificationItem* tmp = _list.at(rowCount() - 1); + _list.replace(rowCount() - 1, item); + delete tmp; + entryUpdated(rowCount() - 1); } diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index f58cc0599..3168a848f 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -86,12 +86,13 @@ public: bool insertRows(int position, int rows, const QModelIndex &index); bool removeRows(int position, int rows, const QModelIndex &index); + void entryAdded(NotificationItem* item); + signals: void dragRows(int position, int count); private slots: void entryUpdated(int offset); - void entryAdded(int position); void dropRows(int position, int count) const; private: From 6a5589ef5101bef3d7e37a37aad32925adea66e4 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Tue, 4 Oct 2011 01:59:37 +0300 Subject: [PATCH 08/72] +multiple selection with D&D completed; +support of enum and range for value completed; --- .../src/plugins/notify/NotificationItem.h | 35 +- .../src/plugins/notify/notificationitem.cpp | 299 +++++----- .../src/plugins/notify/notifyitemdelegate.cpp | 15 +- .../src/plugins/notify/notifyitemdelegate.h | 24 +- .../src/plugins/notify/notifyplugin.cpp | 62 +- .../src/plugins/notify/notifyplugin.h | 88 +-- .../notify/notifypluginoptionspage.cpp | 539 +++++++++--------- .../plugins/notify/notifypluginoptionspage.h | 136 +++-- .../plugins/notify/notifypluginoptionspage.ui | 2 +- .../src/plugins/notify/notifytablemodel.cpp | 102 ++-- .../src/plugins/notify/notifytablemodel.h | 80 ++- 11 files changed, 699 insertions(+), 683 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index 20de7a4f8..1898f1a55 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -103,7 +103,31 @@ public: void seriaize(QDataStream& stream); void deseriaize(QDataStream& stream); - QString parseNotifyMessage(); + /** + * Convert notification item fields in single string, + * to show in table for example + * + * @return string which describe notification + */ + QString toString(); + + /** + * Generate list of sound files needed to play notification + * + * @return success - reference to non-empty _messageSequence; + * error - if one of sounds doesn't exist returns + * reference to empty _messageSequence; + */ + QStringList& toSoundList(); + + /** + * Returns sound caption name, needed to create string representation of notification. + * + * @return success - string == , if sound file exists + * error - string == [missind], if sound file doesn't exist + */ + QString getSoundCaption(QString fileName); + QTimer* getTimer() const { return _timer; } void startTimer(int value); @@ -119,10 +143,14 @@ public: bool isNowPlaying; bool firstStart; -private: - void checkSoundFilesExisting(bool& missed1, bool& missed2, bool& missed3); + static QStringList sayOrderValues; + static QStringList retryValues; private: + QString checkSoundExists(QString fileName); + +private: + QTimer* _timer; //! time from putting notification in queue till moment when notification became out-of-date @@ -130,6 +158,7 @@ private: //! according to its priority QTimer* _expireTimer; + //! list of wav files from which notification consists QStringList _messageSequence; //! path to folder with sound files diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index d6c803b68..1b0e634a6 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -40,10 +40,28 @@ #include "notifylogging.h" +static const QString cStrNever("Never"); +static const QString cStrBefore1st("Before first"); +static const QString cStrBefore2nd("Before second"); +static const QString cStrAfter2nd("After second"); + +static const QString cStrRetryOnce("Repeat Once"); +static const QString cStrRetryInstantly("Repeat Instantly"); +static const QString cStrRetry10sec("Repeat 10 seconds"); +static const QString cStrRetry30sec("Repeat 30 seconds"); +static const QString cStrRetry1min("Repeat 1 minute"); + + +QStringList NotificationItem::sayOrderValues; +QStringList NotificationItem::retryValues; + + NotificationItem::NotificationItem(QObject *parent) : QObject(parent) , isNowPlaying(0) , firstStart(true) + , _timer(NULL) + , _expireTimer(NULL) , _soundCollectionPath("") , _currentLanguage("default") , _dataObject("") @@ -52,16 +70,23 @@ NotificationItem::NotificationItem(QObject *parent) , _sound1("") , _sound2("") , _sound3("") - , _sayOrder("Never") + , _sayOrder(cStrNever) , _singleValue(0) , _valueRange2(0) - , _repeatString("Repeat Instantly") + , _repeatString(cStrRetryInstantly) , _expireTimeout(eDefaultTimeout) , _mute(false) - { - _timer = NULL; - _expireTimer = NULL; + NotificationItem::sayOrderValues.append(cStrBefore1st); + NotificationItem::sayOrderValues.append(cStrBefore2nd); + NotificationItem::sayOrderValues.append(cStrAfter2nd); + + NotificationItem::retryValues.append(cStrRetryOnce); + NotificationItem::retryValues.append(cStrRetryInstantly); + NotificationItem::retryValues.append(cStrRetry10sec); + NotificationItem::retryValues.append(cStrRetry30sec); + NotificationItem::retryValues.append(cStrRetry1min); + } void NotificationItem::copyTo(NotificationItem* that) const @@ -103,7 +128,6 @@ void NotificationItem::saveState(QSettings* settings) const settings->setValue(QLatin1String("Repeat"), retryString()); settings->setValue(QLatin1String("ExpireTimeout"), lifetime()); settings->setValue(QLatin1String("Mute"), mute()); - } void NotificationItem::restoreState(QSettings* settings) @@ -123,7 +147,6 @@ void NotificationItem::restoreState(QSettings* settings) setRetryString(settings->value(QLatin1String("Repeat"), tr("")).toString()); setLifetime(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); setMute(settings->value(QLatin1String("Mute"), tr("")).toInt()); - } void NotificationItem::seriaize(QDataStream& stream) @@ -162,7 +185,8 @@ void NotificationItem::deseriaize(QDataStream& stream) stream >> this->_mute; } -void NotificationItem::startTimer(int value) { +void NotificationItem::startTimer(int value) +{ if (!_timer) { _timer = new QTimer(this); _timer->setInterval(value); @@ -171,14 +195,16 @@ void NotificationItem::startTimer(int value) { _timer->start(); } -void NotificationItem::stopTimer() { +void NotificationItem::stopTimer() +{ if (_timer) { if (_timer->isActive()) _timer->stop(); } } -void NotificationItem::disposeTimer() { +void NotificationItem::disposeTimer() +{ if (_timer) { _timer->stop(); delete _timer; @@ -186,22 +212,24 @@ void NotificationItem::disposeTimer() { } } -void NotificationItem::startExpireTimer() { - if (!_expireTimer) - { +void NotificationItem::startExpireTimer() +{ + if (!_expireTimer) { _expireTimer = new QTimer(this); } _expireTimer->start(_expireTimeout * 1000); } -void NotificationItem::stopExpireTimer() { +void NotificationItem::stopExpireTimer() +{ if (_expireTimer) { if (_expireTimer) _expireTimer->stop(); } } -void NotificationItem::disposeExpireTimer() { +void NotificationItem::disposeExpireTimer() +{ if (_expireTimer) { _expireTimer->stop(); delete _expireTimer; @@ -209,91 +237,33 @@ void NotificationItem::disposeExpireTimer() { } } -#define missed "missed sound" -#define CHECK_ADD_SOUND(n) ((!_missedSound##n) ? getSound##n() : (missed#n)) -#define CHECK_REPLACE_SOUND(n) ((!_missedSound##n) ? str.replace(missed#n, getSound##n()) : (missed#n)) - -QString NotificationItem::parseNotifyMessage() +int getValuePosition(QString sayOrder) { - // tips: - // check of *.wav files exist needed for playing phonon queues; - // if phonon player don't find next file in queue, it buzz + return NotificationItem::sayOrderValues.indexOf(sayOrder); +} - QString str; - QString value; - QString sayOrder = getSayOrder(); - UAVObjectField* field = getUAVObjectField(); - if (UAVObjectField::ENUM == field->getType()) { - Q_ASSERT(singleValue() < field->getOptions().size()); - value = QString("%L1").arg(field->getOptions().at(singleValue())); - } else { - value = QString("%L1").arg(singleValue()); +QString NotificationItem::checkSoundExists(QString fileName) +{ + QString name(fileName + ".wav"); + QString filePath = QDir::toNativeSeparators(getSoundCollectionPath() + "/" + + getCurrentLanguage() + "/" + + name); + if(QFile::exists(filePath)) + return filePath; + else { + filePath = QDir::toNativeSeparators(getSoundCollectionPath() + + "/default/" + + name); + if(!QFile::exists(filePath)) + filePath.clear(); } + return filePath; +} - int position = -1; // default don't play value wav file - - // generate queue of sound files to play - _messageSequence.clear(); - - bool _missedSound1 = false; - bool _missedSound2 = false; - bool _missedSound3 = false; - - checkSoundFilesExisting(_missedSound1, _missedSound2, _missedSound3); - str = CHECK_ADD_SOUND(1)+" "+CHECK_ADD_SOUND(2)+" "+CHECK_ADD_SOUND(3); - - if(!_messageSequence.size()) { - qNotifyDebug() << "no any files in message queue"; - } - - sayOrder = sayOrder.trimmed(); - switch(sayOrder.at(0).toUpper().toAscii()) - { - case 'B'://BEFORE: - CHECK_REPLACE_SOUND(1); - CHECK_REPLACE_SOUND(2); - CHECK_REPLACE_SOUND(3); - str.prepend(value + " "); - position = 0; - break; - - case 'A'://AFTER: - switch(sayOrder.at(6).toLower().toAscii()) - { - case 'f': - str = CHECK_ADD_SOUND(1)+" "+value+" "+CHECK_ADD_SOUND(2)+" "+CHECK_ADD_SOUND(3); - position = 1; - break; - - case 's': - str = CHECK_ADD_SOUND(1)+" "+CHECK_ADD_SOUND(2)+" "+value+" "+CHECK_ADD_SOUND(3); - position = 2; - break; - - case 't': - CHECK_REPLACE_SOUND(1); - CHECK_REPLACE_SOUND(2); - CHECK_REPLACE_SOUND(3); - str.append(" "+value); - position = 3; - break; - } - break; - - default: - CHECK_REPLACE_SOUND(1); - CHECK_REPLACE_SOUND(2); - CHECK_REPLACE_SOUND(3); - break; - } - - if(-1 == position) { - qNotifyDebug() << "NotificationItem::parseNotifyMessage() | value position undefined"; - return str; - } - - if (UAVObjectField::ENUM == field->getType()) return str; - +QStringList valueToSoundList(QString value) +{ + // replace point chr if exists + value = value.replace(',', '.'); QStringList numberParts = value.trimmed().split("."); QStringList digitWavs; @@ -338,23 +308,100 @@ QString NotificationItem::parseNotifyMessage() digitWavs.append(numberParts.at(1).right(1)); } } - foreach(QString fileName, digitWavs) { - fileName+=".wav"; - QString filePath = QDir::toNativeSeparators(getSoundCollectionPath()+"/"+ getCurrentLanguage()+"/"+fileName); - if(QFile::exists(filePath)) - _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+ "/"+getCurrentLanguage()+"/"+fileName)); - else { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName))) - _messageSequence.insert(position++,QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+fileName)); - else { - _messageSequence.clear(); - break; // if no some of *.wav files, then don't play number! - } + return digitWavs; +} + +QString NotificationItem::toString() +{ + QString str; + QString value; + UAVObjectField* field = getUAVObjectField(); + if (UAVObjectField::ENUM == field->getType()) { + Q_ASSERT(singleValue() < field->getOptions().size()); + value = field->getOptions().at(singleValue()); + } else { + value = QString("%L1").arg(singleValue()); + } + + int pos = getValuePosition(getSayOrder().trimmed()); + QStringList lst; + lst.append(getSoundCaption(getSound1())); + lst.append(getSoundCaption(getSound2())); + lst.append(getSoundCaption(getSound3())); + QStringList valueSounds = valueToSoundList(value); + bool missed = false; + foreach(QString sound, valueSounds) { + if(checkSoundExists(sound).isEmpty()) { + missed = true; + break; } } + + // if not "Never" case + if(-1 != pos) { + if(missed) + lst.insert(pos, "[missed]" + value); + else + lst.insert(pos, value); + } + str = lst.join(" "); return str; } +QStringList& NotificationItem::toSoundList() +{ + // tips: + // check of *.wav files exist needed for playing phonon queues; + // if phonon player don't find next file in queue, it buzz + + QString value; + UAVObjectField* field = getUAVObjectField(); + if (UAVObjectField::ENUM == field->getType()) { + Q_ASSERT(singleValue() < field->getOptions().size()); + value = field->getOptions().at(singleValue()); + } else { + value = QString("%L1").arg(singleValue()); + } + + // generate queue of sound files to play + _messageSequence.clear(); + int pos = getValuePosition(getSayOrder().trimmed()); + QStringList lst; + if(!getSound1().isEmpty()) + lst.append(getSound1()); + if(!getSound2().isEmpty()) + lst.append(getSound2()); + if(!getSound3().isEmpty()) + lst.append(getSound3()); + + // if not "Never" case + if(-1 != pos) { + QStringList valueSounds = valueToSoundList(value); + foreach(QString sound, valueSounds) + lst.insert(pos++, sound); + } + + foreach(QString sound, lst) { + QString path = checkSoundExists(sound); + if (!path.isEmpty()) { + _messageSequence.append(path); + } else { + _messageSequence.clear(); + break; + } + } + return _messageSequence; +} + +QString NotificationItem::getSoundCaption(QString fileName) +{ + if(fileName.isEmpty()) return QString(); + if(checkSoundExists(fileName).isEmpty()) { + return QString("[missed]") + fileName; + } + return fileName; +} + UAVObjectField* NotificationItem::getUAVObjectField() { return getUAVObject()->getField(getObjectField()); } @@ -362,39 +409,3 @@ UAVObjectField* NotificationItem::getUAVObjectField() { UAVDataObject* NotificationItem::getUAVObject() { return dynamic_cast((ExtensionSystem::PluginManager::instance()->getObject())->getObject(getDataObject())); } - - -void NotificationItem::checkSoundFilesExisting(bool& missed1, bool& missed2, bool& missed3) -{ - - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound1()+".wav")); - else { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound1()+".wav")); - else - missed1 = true; - } - - if(getSound2().size()) { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/" + getCurrentLanguage()+"/"+getSound2()+".wav")); - else { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath() + "/default/"+getSound2()+".wav")); - else - missed2 = true; - } - } - - if(getSound3().size()) { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+ "/" + getCurrentLanguage()+"/"+getSound3()+".wav")); - else { - if(QFile::exists(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav"))) - _messageSequence.append(QDir::toNativeSeparators(getSoundCollectionPath()+"/default/"+getSound3()+".wav")); - else - missed3 = true; - } - } -} diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp index d418f0d26..da7177b35 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.cpp @@ -29,34 +29,29 @@ #include "notifyitemdelegate.h" #include "notifytablemodel.h" #include "notifylogging.h" +#include "notificationitem.h" NotifyItemDelegate::NotifyItemDelegate(QObject* parent) : QItemDelegate(parent) , _parent(parent) { - _titles << "Repeat Once" - << "Repeat Instantly" - << "Repeat 10 seconds" - << "Repeat 30 seconds" - << "Repeat 1 minute"; - } QWidget *NotifyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& /*none*/, const QModelIndex& index) const { - if (eREPEAT_VALUE == index.column()) { + if (eRepeatValue == index.column()) { QComboBox* editor = new QComboBox(parent); editor->clear(); - editor->addItems(_titles); + editor->addItems(NotificationItem::retryValues); return editor; } else { - if (eEXPIRE_TIME == index.column()) { + if (eExpireTimer == index.column()) { QSpinBox* editor = new QSpinBox(parent); connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); return editor; } else { - if (eENABLE_NOTIFICATION == index.column()) { + if (eTurnOn == index.column()) { QCheckBox* editor = new QCheckBox(parent); connect(editor, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); return editor; diff --git a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h index 494e61c17..ace6d4976 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyitemdelegate.h @@ -34,25 +34,23 @@ class NotifyItemDelegate : public QItemDelegate { - Q_OBJECT + Q_OBJECT public: - NotifyItemDelegate(QObject *parent = 0); - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, - const QModelIndex &index) const; - void setEditorData(QWidget *editor, const QModelIndex &index) const; - void setModelData(QWidget *editor, QAbstractItemModel *model, - const QModelIndex &index) const; - QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; + NotifyItemDelegate(QObject *parent = 0); + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &index) const; + void setEditorData(QWidget *editor, const QModelIndex &index) const; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const; + QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; private slots: - void selectRow(const QString & text); - void commitAndCloseEditor(); + void selectRow(const QString & text); + void commitAndCloseEditor(); private: - QObject* _parent; - QStringList _titles; - + QObject* _parent; }; #endif // NOTIFYITEMDELEGATE_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index fa55cfc42..88cb23621 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -49,7 +49,6 @@ SoundNotifyPlugin::SoundNotifyPlugin() { phonon.mo = NULL; configured = false; - // Do nothing } SoundNotifyPlugin::~SoundNotifyPlugin() @@ -57,7 +56,6 @@ SoundNotifyPlugin::~SoundNotifyPlugin() Core::ICore::instance()->saveSettings(this); if (phonon.mo != NULL) delete phonon.mo; - // Do nothing } bool SoundNotifyPlugin::initialize(const QStringList& args, QString *errMsg) @@ -99,8 +97,8 @@ void SoundNotifyPlugin::saveConfig( QSettings* settings, UAVConfigInfo *configIn settings->beginWriteArray("listNotifies"); for (int i = 0; i < lstNotifications.size(); i++) { - settings->setArrayIndex(i); - lstNotifications.at(i)->saveState(settings); + settings->setArrayIndex(i); + lstNotifications.at(i)->saveState(settings); } settings->endArray(); settings->setValue(QLatin1String("EnableSound"), enableSound); @@ -147,10 +145,10 @@ void SoundNotifyPlugin::readConfig_0_0_0(){ // read list of notifications from settings int size = settings->beginReadArray("listNotifies"); for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); - NotificationItem* notification = new NotificationItem; - notification->restoreState(settings); - lstNotifications.append(notification); + settings->setArrayIndex(i); + NotificationItem* notification = new NotificationItem; + notification->restoreState(settings); + lstNotifications.append(notification); } settings->endArray(); setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); @@ -237,14 +235,17 @@ void SoundNotifyPlugin::connectNotifications() notify->firstStart=true; notify->isNowPlaying=false; + if(notify->mute()) continue; + UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); if (obj != NULL ) { if (!lstNotifiedUAVObjects.contains(obj)) { - lstNotifiedUAVObjects.append(obj); - connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + lstNotifiedUAVObjects.append(obj); + connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); } - } else - std::cout << "Error: Object is unknown (" << notify->getDataObject().toStdString() << ")." << std::endl; + } else { + qNotifyDebug() << "Error: Object is unknown (" << notify->getDataObject() << ")."; + } } if (lstNotifications.isEmpty()) return; @@ -294,7 +295,7 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA fieldName = notification->getObjectField(); UAVObjectField* field = object->getField(fieldName); - if (field->getName() == "") + if (field->getName().isEmpty()) return; double value = field->getDouble(); @@ -321,13 +322,11 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA if (!condition) return; - if (!playNotification(notification)) - { - if (!pendingNotifications.contains(notification)) - { + if (!playNotification(notification)) { + if (!pendingNotifications.contains(notification)) { notification->stopTimer(); - qNotifyDebug() << "add to pending list - " << notification->parseNotifyMessage(); + qNotifyDebug() << "add to pending list - " << notification->toString(); // if audio is busy, start expiration timer //ms = (notification->getExpiredTimeout()[in sec])*1000 //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); @@ -344,8 +343,8 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) if (phonon.mo == NULL) return false; - if (!notification->mute()) - return true; + if (notification->mute()) + return false; qNotifyDebug() << "Phonon State: " << phonon.mo->state(); if ((phonon.mo->state()==Phonon::PausedState) @@ -375,9 +374,8 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) } notification->firstStart=false; phonon.mo->clear(); - QString str = notification->parseNotifyMessage(); - qNotifyDebug() << "play notification - " << str; - foreach (QString item, notification->getMessageSequence()) { + qNotifyDebug() << "play notification - " << notification->toString(); + foreach (QString item, notification->toSoundList()) { Phonon::MediaSource *ms = new Phonon::MediaSource(item); ms->setAutoDelete(true); phonon.mo->enqueue(*ms); @@ -393,15 +391,15 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) void SoundNotifyPlugin::repeatTimerHandler() { - NotificationItem* notification = static_cast(sender()->parent()); + NotificationItem* notification = static_cast(sender()->parent()); - qNotifyDebug() << "repeatTimerHandler - " << notification->parseNotifyMessage(); + qNotifyDebug() << "repeatTimerHandler - " << notification->toString(); - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); - UAVObject* object = objManager->getObject(notification->getDataObject()); - if (object) - checkNotificationRule(notification,object); + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + UAVObjectManager *objManager = pm->getObject(); + UAVObject* object = objManager->getObject(notification->getDataObject()); + if (object) + checkNotificationRule(notification,object); } void SoundNotifyPlugin::expireTimerHandler() @@ -411,7 +409,7 @@ void SoundNotifyPlugin::expireTimerHandler() notification->stopExpireTimer(); if (!pendingNotifications.isEmpty()) { - qNotifyDebug() << "expireTimerHandler - " << notification->parseNotifyMessage(); + qNotifyDebug() << "expireTimerHandler - " << notification->toString(); pendingNotifications.removeOne(notification); } } @@ -438,7 +436,7 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst if (!pendingNotifications.isEmpty()) { NotificationItem* notification = pendingNotifications.takeFirst(); - qNotifyDebug() << "play audioFree - " << notification->parseNotifyMessage(); + qNotifyDebug() << "play audioFree - " << notification->toString(); playNotification(notification); } } else { diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h index 1d9475469..0b7a31f3b 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h @@ -50,65 +50,65 @@ typedef struct { class SoundNotifyPlugin : public Core::IConfigurablePlugin -{ - Q_OBJECT -public: - SoundNotifyPlugin(); - ~SoundNotifyPlugin(); +{ + Q_OBJECT +public: + SoundNotifyPlugin(); + ~SoundNotifyPlugin(); - void extensionsInitialized(); - bool initialize(const QStringList & arguments, QString * errorString); - void readConfig( QSettings* qSettings, Core::UAVConfigInfo *configInfo); - void saveConfig( QSettings* qSettings, Core::UAVConfigInfo *configInfo); - void shutdown(); + void extensionsInitialized(); + bool initialize(const QStringList & arguments, QString * errorString); + void readConfig( QSettings* qSettings, Core::UAVConfigInfo *configInfo); + void saveConfig( QSettings* qSettings, Core::UAVConfigInfo *configInfo); + void shutdown(); - QList getListNotifications() { return lstNotifications; } - NotificationItem* getCurrentNotification(){ return ¤tNotification;} + QList getListNotifications() { return lstNotifications; } + NotificationItem* getCurrentNotification(){ return ¤tNotification;} - bool getEnableSound() const { return enableSound; } - void setEnableSound(bool value) {enableSound = value; } + bool getEnableSound() const { return enableSound; } + void setEnableSound(bool value) {enableSound = value; } private: - SoundNotifyPlugin(const SoundNotifyPlugin& rhs); - SoundNotifyPlugin& operator= (const SoundNotifyPlugin& rhs); + Q_DISABLE_COPY(SoundNotifyPlugin) - bool playNotification(NotificationItem* notification); - void checkNotificationRule(NotificationItem* notification, UAVObject* object); - void readConfig_0_0_0(); + bool playNotification(NotificationItem* notification); + void checkNotificationRule(NotificationItem* notification, UAVObject* object); + void readConfig_0_0_0(); private slots: - void onTelemetryManagerAdded(QObject* obj); - void onAutopilotDisconnect(); - void connectNotifications(); - void updateNotificationList(QList list); - void resetNotification(void); - void appendNotification(UAVObject *object); - void repeatTimerHandler(void); - void expireTimerHandler(void); - void stateChanged(Phonon::State newstate, Phonon::State oldstate); + + void onTelemetryManagerAdded(QObject* obj); + void onAutopilotDisconnect(); + void connectNotifications(); + void updateNotificationList(QList list); + void resetNotification(void); + void appendNotification(UAVObject *object); + void repeatTimerHandler(void); + void expireTimerHandler(void); + void stateChanged(Phonon::State newstate, Phonon::State oldstate); private: - bool configured; // just for migration,delete later - bool enableSound; - QList< QList* > lstMediaSource; - QStringList mediaSource; - QMultiMap mapMediaObjects; - QSettings* settings; + bool configured; // just for migration,delete later + bool enableSound; + QList< QList* > lstMediaSource; + QStringList mediaSource; + QMultiMap mapMediaObjects; + QSettings* settings; - QList lstNotifiedUAVObjects; - QList lstNotifications; - QList pendingNotifications; - QList removedNotifies; + QList lstNotifiedUAVObjects; + QList lstNotifications; + QList pendingNotifications; + QList removedNotifies; - NotificationItem currentNotification; - NotificationItem* nowPlayingConfiguration; + NotificationItem currentNotification; + NotificationItem* nowPlayingConfiguration; - QString m_field; - PhononObject phonon; - NotifyPluginOptionsPage *mop; - TelemetryManager* telMngr; + QString m_field; + PhononObject phonon; + NotifyPluginOptionsPage *mop; + TelemetryManager* telMngr; }; #endif // SOUNDNOTIFYPLUGIN_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 305e5e13e..fdf0f5cc9 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -47,72 +47,61 @@ #include "notifytablemodel.h" #include "notifylogging.h" - -static const char* cStrBefore1st = "Before first"; -static const char* cStrBefore2nd = "Before second"; -static const char* cStrAfter2nd = "After second"; - static const char* cStrEqualTo = "Equal to"; static const char* cStrLargeThan = "Large than"; static const char* cStrLowerThan = "Lower than"; static const char* cStrInRange = "In range"; -//----------------------------------------------------------------------------- -NotifyPluginOptionsPage::NotifyPluginOptionsPage(/*NotificationItem *config,*/ QObject *parent) +NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) : IOptionsPage(parent) - , objManager(*ExtensionSystem::PluginManager::instance()->getObject()) - , owner(qobject_cast(parent)) - , currentCollectionPath("") + , _objManager(*ExtensionSystem::PluginManager::instance()->getObject()) + , _owner(qobject_cast(parent)) + , _currentCollectionPath("") , _valueRange(NULL) , _sayOrder(NULL) , _fieldValue(NULL) , _fieldType(-1) , _form(NULL) -{ -} + , _selectedNotification(NULL) +{} -//----------------------------------------------------------------------------- NotifyPluginOptionsPage::~NotifyPluginOptionsPage() -{ -} +{} -//creates options page widget (uses the UI file) - -//----------------------------------------------------------------------------- QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) { - options_page.reset(new Ui::NotifyPluginOptionsPage()); + _optionsPage.reset(new Ui::NotifyPluginOptionsPage()); //main widget QWidget* optionsPageWidget = new QWidget; - //if(!_fieldValue.isNull()) _fieldValue = NULL; _valueRange = NULL; - _fieldType = -1; + resetFieldType(); //save ref to form, needed for binding dynamic fields in future _form = optionsPageWidget; //main layout - options_page->setupUi(optionsPageWidget); + _optionsPage->setupUi(optionsPageWidget); - listSoundFiles.clear(); - - options_page->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); - options_page->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); - - connect(options_page->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), this, SLOT(on_buttonSoundFolder_clicked(const QString&))); - connect(options_page->SoundCollectionList, SIGNAL(currentIndexChanged (int)), this, SLOT(on_soundLanguage_indexChanged(int))); + _listSoundFiles.clear(); + _optionsPage->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); + _optionsPage->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); + connect(_optionsPage->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), + this, SLOT(on_buttonSoundFolder_clicked(const QString&))); + connect(_optionsPage->SoundCollectionList, SIGNAL(currentIndexChanged (int)), + this, SLOT(on_soundLanguage_indexChanged(int))); connect(this, SIGNAL(updateNotifications(QList)), - owner, SLOT(updateNotificationList(QList))); + _owner, SLOT(updateNotificationList(QList))); //connect(this, SIGNAL(resetNotification()),owner, SLOT(resetNotification())); - privListNotifications = owner->getListNotifications(); + _privListNotifications = _owner->getListNotifications(); + // [1] + _selectedNotification = _owner->getCurrentNotification(); addDynamicValueLayout(); - _selectedNotification = owner->getCurrentNotification(); // [2] updateConfigView(_selectedNotification); @@ -120,117 +109,119 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) initButtons(); initPhononPlayer(); -// _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(0, 0, QModelIndex()), -// QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(0, 0, QModelIndex()), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); return optionsPageWidget; } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::apply() { - getOptionsPageValues(owner->getCurrentNotification()); - owner->setEnableSound(options_page->chkEnableSound->isChecked()); - emit updateNotifications(privListNotifications); + getOptionsPageValues(_owner->getCurrentNotification()); + _owner->setEnableSound(_optionsPage->chkEnableSound->isChecked()); + emit updateNotifications(_privListNotifications); } void NotifyPluginOptionsPage::finish() { + disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_UAVField_indexChanged(QString))); - disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); - - disconnect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - if (notifySound) { - notifySound->stop(); - notifySound->clear(); + disconnect(_notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(on_changeButtonText(Phonon::State,Phonon::State))); + if (_notifySound) { + _notifySound->stop(); + _notifySound->clear(); } } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::addDynamicValueLayout() { - NotificationItem* curr = owner->getCurrentNotification(); + NotificationItem* curr = _owner->getCurrentNotification(); Q_ASSERT(curr); - options_page->dynamicValueLayout->addWidget(new QLabel("Say order ", _form)); + _optionsPage->dynamicValueLayout->addWidget(new QLabel("Say order ", _form)); _sayOrder = new QComboBox(_form); - options_page->dynamicValueLayout->addWidget(_sayOrder); - QStringList sayOrderValues; - sayOrderValues << cStrBefore1st << cStrBefore2nd << cStrAfter2nd; - _sayOrder->addItems(sayOrderValues); + _optionsPage->dynamicValueLayout->addWidget(_sayOrder); + _sayOrder->addItems(NotificationItem::sayOrderValues); - options_page->dynamicValueLayout->addWidget(new QLabel("Value is ", _form)); + _optionsPage->dynamicValueLayout->addWidget(new QLabel("Value is ", _form)); - UAVDataObject* obj = dynamic_cast(objManager.getObject(curr->getDataObject())); + UAVDataObject* obj = dynamic_cast(_objManager.getObject(curr->getDataObject())); UAVObjectField* field = obj->getField(curr->getObjectField()); Q_ASSERT(obj); Q_ASSERT(field); _valueRange = new QComboBox(_form); - options_page->dynamicValueLayout->addWidget(_valueRange); + _optionsPage->dynamicValueLayout->addWidget(_valueRange); addDynamicField(field); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::resetValueRange() { - _fieldValue = new QLineEdit(_form); (static_cast(_fieldValue))->setInputMask("999.99 - 999.99;"); (static_cast(_fieldValue))->setText("0000000000"); (static_cast(_fieldValue))->setCursorPosition(0); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_rangeValue_indexChanged(QString rangeStr) { Q_ASSERT(_fieldValue); - if(rangeStr == cStrInRange) { - Q_ASSERT(_fieldValue); - options_page->dynamicValueLayout->removeWidget(_fieldValue); - resetValueRange(); - options_page->dynamicValueLayout->addWidget(_fieldValue); - - // _fieldType = -1; - // addDynamicField(field); - } + UAVObjectField* field = getObjectFieldFromPage(); + Q_ASSERT(!!field); + setDynamicValueWidget(field); + setDynamicValueField(_selectedNotification); +} + +void NotifyPluginOptionsPage::resetFieldType() +{ + _fieldType = -1; } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) { - //qDebugNotify_if(!objField || !parent) << "null input params"; + //qDebugNotify_ if (!objField || !parent) << "null input params"; Q_ASSERT(objField); - if(objField->getType() == _fieldType) { - if(QComboBox* fieldValue = dynamic_cast(_fieldValue)) { + if (objField->getType() == _fieldType) { + if (QComboBox* fieldValue = dynamic_cast(_fieldValue)) { fieldValue->clear(); QStringList enumValues(objField->getOptions()); fieldValue->addItems(enumValues); } return; } - // check if dynamic fileld already settled, - // so if its exists remove it and install new field - if(_fieldValue) - options_page->dynamicValueLayout->removeWidget(_fieldValue); disconnect(_valueRange, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_rangeValue_indexChanged(QString))); _valueRange->clear(); QStringList rangeValues; - if(UAVObjectField::ENUM == objField->getType()) { + if (UAVObjectField::ENUM == objField->getType()) { rangeValues << cStrEqualTo << cStrInRange; _valueRange->addItems(rangeValues); - } - else { + _valueRange->setCurrentIndex(rangeValues.indexOf(_selectedNotification->range())); + + } else { rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; _valueRange->addItems(rangeValues); connect(_valueRange, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_rangeValue_indexChanged(QString))); } + setDynamicValueWidget(objField); +} +void NotifyPluginOptionsPage::setDynamicValueWidget(UAVObjectField* objField) +{ + Q_ASSERT(_valueRange); + + // check if dynamic fileld already settled, + // so if its exists remove it and install new field + if (_fieldValue) { + _optionsPage->dynamicValueLayout->removeWidget(_fieldValue); + delete _fieldValue; + _fieldValue = NULL; + } _fieldType = objField->getType(); switch(_fieldType) { @@ -243,92 +234,90 @@ void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) break; default: - if(_valueRange->currentText() == cStrInRange) { + if (_valueRange->currentText() == cStrInRange) { + _fieldValue = new QLineEdit(_form); resetValueRange(); } else { _fieldValue = new QSpinBox(_form); } break; }; - options_page->dynamicValueLayout->addWidget(_fieldValue); + _optionsPage->dynamicValueLayout->addWidget(_fieldValue); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initButtons() { - options_page->chkEnableSound->setChecked(owner->getEnableSound()); - connect(options_page->chkEnableSound, SIGNAL(toggled(bool)), this, SLOT(on_chkEnableSound_toggled(bool))); + _optionsPage->chkEnableSound->setChecked(_owner->getEnableSound()); + connect(_optionsPage->chkEnableSound, SIGNAL(toggled(bool)), + this, SLOT(on_checkEnableSound_toggled(bool))); - options_page->buttonModify->setEnabled(false); - options_page->buttonDelete->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); - connect(options_page->buttonAdd, SIGNAL(pressed()), this, SLOT(on_buttonAddNotification_clicked())); - connect(options_page->buttonDelete, SIGNAL(pressed()), this, SLOT(on_buttonDeleteNotification_clicked())); - connect(options_page->buttonModify, SIGNAL(pressed()), this, SLOT(on_buttonModifyNotification_clicked())); - connect(options_page->buttonPlayNotification, SIGNAL(clicked()), this, SLOT(on_buttonTestSoundNotification_clicked())); + _optionsPage->buttonModify->setEnabled(false); + _optionsPage->buttonDelete->setEnabled(false); + _optionsPage->buttonPlayNotification->setEnabled(false); + connect(_optionsPage->buttonAdd, SIGNAL(pressed()), + this, SLOT(on_button_AddNotification_clicked())); + connect(_optionsPage->buttonDelete, SIGNAL(pressed()), + this, SLOT(on_button_DeleteNotification_clicked())); + connect(_optionsPage->buttonModify, SIGNAL(pressed()), + this, SLOT(on_button_ModifyNotification_clicked())); + connect(_optionsPage->buttonPlayNotification, SIGNAL(clicked()), + this, SLOT(on_button_TestSoundNotification_clicked())); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initPhononPlayer() { - notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); - connect(notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(changeButtonText(Phonon::State,Phonon::State))); - connect(notifySound.data(), SIGNAL(finished(void)), this, SLOT(onFinishedPlaying(void))); + _notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); + connect(_notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(on_changeButtonText(Phonon::State,Phonon::State))); + connect(_notifySound.data(), SIGNAL(finished(void)), this, SLOT(on_FinishedPlaying(void))); } - -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::initRulesTable() { qNotifyDebug_if(_notifyRulesModel.isNull()) << "_notifyRulesModel.isNull())"; qNotifyDebug_if(!_notifyRulesSelection) << "_notifyRulesSelection.isNull())"; - //QItemSelectionModel* selection = _notifyRulesSelection.take(); - _notifyRulesModel.reset(new NotifyTableModel(privListNotifications)); + _notifyRulesModel.reset(new NotifyTableModel(_privListNotifications)); _notifyRulesSelection = new QItemSelectionModel(_notifyRulesModel.data()); connect(_notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), - this, SLOT(on_tableNotification_changeSelection( const QItemSelection & , const QItemSelection & ))); + this, SLOT(on_table_changeSelection( const QItemSelection & , const QItemSelection & ))); connect(this, SIGNAL(entryUpdated(int)), - _notifyRulesModel.data(), SLOT(entryUpdated(int))); -// connect(this, SIGNAL(entryAdded(int)), -// _notifyRulesModel.data(), SLOT(entryAdded(int))); + _notifyRulesModel.data(), SLOT(entryUpdated(int))); - options_page->notifyRulesView->setModel(_notifyRulesModel.data()); - options_page->notifyRulesView->setSelectionModel(_notifyRulesSelection); - options_page->notifyRulesView->setItemDelegate(new NotifyItemDelegate(this)); + _optionsPage->notifyRulesView->setModel(_notifyRulesModel.data()); + _optionsPage->notifyRulesView->setSelectionModel(_notifyRulesSelection); + _optionsPage->notifyRulesView->setItemDelegate(new NotifyItemDelegate(this)); - options_page->notifyRulesView->resizeRowsToContents(); - options_page->notifyRulesView->setColumnWidth(eMESSAGE_NAME,200); - options_page->notifyRulesView->setColumnWidth(eREPEAT_VALUE,120); - options_page->notifyRulesView->setColumnWidth(eEXPIRE_TIME,100); - options_page->notifyRulesView->setColumnWidth(eENABLE_NOTIFICATION,60); - options_page->notifyRulesView->setDragEnabled(true); - options_page->notifyRulesView->setAcceptDrops(true); - options_page->notifyRulesView->setDropIndicatorShown(true); - options_page->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); + _optionsPage->notifyRulesView->resizeRowsToContents(); + _optionsPage->notifyRulesView->setColumnWidth(eMessageName,200); + _optionsPage->notifyRulesView->setColumnWidth(eRepeatValue,120); + _optionsPage->notifyRulesView->setColumnWidth(eExpireTimer,100); + _optionsPage->notifyRulesView->setColumnWidth(eTurnOn,60); + _optionsPage->notifyRulesView->setDragEnabled(true); + _optionsPage->notifyRulesView->setAcceptDrops(true); + _optionsPage->notifyRulesView->setDropIndicatorShown(true); + _optionsPage->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { Q_ASSERT(notification); - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); - notification->setSound1(options_page->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); + notification->setSoundCollectionPath(_optionsPage->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(_optionsPage->SoundCollectionList->currentText()); + notification->setDataObject(_optionsPage->UAVObject->currentText()); + notification->setObjectField(_optionsPage->UAVObjectField->currentText()); + notification->setSound1(_optionsPage->Sound1->currentText()); + notification->setSound2(_optionsPage->Sound2->currentText()); + notification->setSound3(_optionsPage->Sound3->currentText()); notification->setSayOrder(_sayOrder->currentText()); notification->setRange(_valueRange->currentText()); - if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) notification->setSingleValue(spinValue->value()); else { - if(QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) + if (QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) notification->setSingleValue(comboBoxValue->currentIndex()); else { - if(QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { + if (QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { QString str = rangeValue->text(); QStringList range = str.split('-'); notification->setSingleValue(range.at(0).toDouble()); @@ -338,190 +327,175 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio } } - -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::onUAVField_indexChanged(QString field) { - _fieldType = -1; - UAVDataObject* obj = dynamic_cast( objManager.getObject(options_page->UAVObject->currentText())); +void NotifyPluginOptionsPage::on_UAVField_indexChanged(QString field) +{ + resetFieldType(); + UAVDataObject* obj = dynamic_cast( _objManager.getObject(_optionsPage->UAVObject->currentText())); addDynamicField(obj->getField(field)); } -////////////////////////////////////////////////////////////////////////////// -// Fills in the combo box when value is changed in the -// combo box -////////////////////////////////////////////////////////////////////////////// -void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) { - _fieldType = -1; - UAVDataObject* obj = dynamic_cast( objManager.getObject(val) ); +void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) +{ + resetFieldType(); + UAVDataObject* obj = dynamic_cast( _objManager.getObject(val) ); QList fieldList = obj->getFields(); - disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); - options_page->UAVObjectField->clear(); + disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVField_indexChanged(QString))); + _optionsPage->UAVObjectField->clear(); foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); + _optionsPage->UAVObjectField->addItem(field->getName()); } - connect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(onUAVField_indexChanged(QString))); + connect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVField_indexChanged(QString))); addDynamicField(fieldList.at(0)); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) { QDir dirPath(path); - listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - options_page->SoundCollectionList->clear(); - options_page->SoundCollectionList->addItems(listDirCollections); + _listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + _optionsPage->SoundCollectionList->clear(); + _optionsPage->SoundCollectionList->addItems(_listDirCollections); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) { - options_page->SoundCollectionList->setCurrentIndex(index); + _optionsPage->SoundCollectionList->setCurrentIndex(index); + _currentCollectionPath = _optionsPage->SoundDirectoryPathChooser->path() + + QDir::toNativeSeparators("/" + _optionsPage->SoundCollectionList->currentText()); - currentCollectionPath = options_page->SoundDirectoryPathChooser->path() - + QDir::toNativeSeparators("/" + options_page->SoundCollectionList->currentText()); - - QDir dirPath(currentCollectionPath); + QDir dirPath(_currentCollectionPath); QStringList filters; filters << "*.mp3" << "*.wav"; dirPath.setNameFilters(filters); - listSoundFiles = dirPath.entryList(filters); - listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); - options_page->Sound1->clear(); - options_page->Sound2->clear(); - options_page->Sound3->clear(); - options_page->Sound1->addItems(listSoundFiles); - options_page->Sound2->addItem(""); - options_page->Sound2->addItems(listSoundFiles); - options_page->Sound3->addItem(""); - options_page->Sound3->addItems(listSoundFiles); - + _listSoundFiles = dirPath.entryList(filters); + _listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); + _optionsPage->Sound1->clear(); + _optionsPage->Sound2->clear(); + _optionsPage->Sound3->clear(); + _optionsPage->Sound1->addItems(_listSoundFiles); + _optionsPage->Sound2->addItem(""); + _optionsPage->Sound2->addItems(_listSoundFiles); + _optionsPage->Sound3->addItem(""); + _optionsPage->Sound3->addItems(_listSoundFiles); } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::changeButtonText(Phonon::State newstate, Phonon::State oldstate) +void NotifyPluginOptionsPage::on_changeButtonText(Phonon::State newstate, Phonon::State oldstate) { //Q_ASSERT(Phonon::ErrorState != newstate); if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { - options_page->buttonPlayNotification->setText("Play"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); + _optionsPage->buttonPlayNotification->setText("Play"); + _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); } else { if (newstate == Phonon::PlayingState) { - options_page->buttonPlayNotification->setText("Stop"); - options_page->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); + _optionsPage->buttonPlayNotification->setText("Stop"); + _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); } } } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::onFinishedPlaying() +void NotifyPluginOptionsPage::on_FinishedPlaying() { - notifySound->clear(); + _notifySound->clear(); } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::on_buttonTestSoundNotification_clicked() +void NotifyPluginOptionsPage::on_button_TestSoundNotification_clicked() { NotificationItem* notification = NULL; - - if (-1 == _notifyRulesSelection->currentIndex().row()) - return; - notifySound->clearQueue(); - notification = privListNotifications.at(_notifyRulesSelection->currentIndex().row()); - notification->parseNotifyMessage(); - QStringList sequence = notification->getMessageSequence(); - Q_ASSERT(!!sequence.size()); qNotifyDebug() << "on_buttonTestSoundNotification_clicked"; + Q_ASSERT(-1 != _notifyRulesSelection->currentIndex().row()); + _notifySound->clearQueue(); + notification = _privListNotifications.at(_notifyRulesSelection->currentIndex().row()); + QStringList sequence = notification->toSoundList(); + if (sequence.isEmpty()) { + qNotifyDebug() << "message sequense is empty!"; + return; + } foreach(QString item, sequence) { qNotifyDebug() << item; - notifySound->enqueue(Phonon::MediaSource(item)); + _notifySound->enqueue(Phonon::MediaSource(item)); } - notifySound->play(); + _notifySound->play(); } -void NotifyPluginOptionsPage::on_chkEnableSound_toggled(bool state) +void NotifyPluginOptionsPage::on_checkEnableSound_toggled(bool state) { bool state1 = 1^state; - QList listOutputs = notifySound->outputPaths(); + QList listOutputs = _notifySound->outputPaths(); Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); audioOutput->setMuted(state1); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { Q_ASSERT(notification); - disconnect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), + disconnect(_optionsPage->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); - disconnect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), - this, SLOT(onUAVField_indexChanged(QString))); + disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_UAVField_indexChanged(QString))); QString path = notification->getSoundCollectionPath(); - if (path == "") { - //QDir dir = QDir::currentPath(); - //path = QDir::currentPath().left(QDir::currentPath().indexOf("OpenPilot",0,Qt::CaseSensitive))+"../share/sounds"; + if (path.isEmpty()) { path = Utils::PathUtils().InsertDataPath("%%DATAPATH%%sounds"); } - options_page->SoundDirectoryPathChooser->setPath(path); + _optionsPage->SoundDirectoryPathChooser->setPath(path); - if (-1 != options_page->SoundCollectionList->findText(notification->getCurrentLanguage())){ - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText(notification->getCurrentLanguage())); + if (-1 != _optionsPage->SoundCollectionList->findText(notification->getCurrentLanguage())) { + _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText(notification->getCurrentLanguage())); } else { - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); + _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); } - // Fills the combo boxes for the UAVObjects - QList< QList > objList = objManager.getDataObjects(); + QList< QList > objList = _objManager.getDataObjects(); foreach (QList list, objList) { foreach (UAVDataObject* obj, list) { - options_page->UAVObject->addItem(obj->getName()); + _optionsPage->UAVObject->addItem(obj->getName()); } } - if (options_page->UAVObject->findText(notification->getDataObject())!=-1){ - options_page->UAVObject->setCurrentIndex(options_page->UAVObject->findText(notification->getDataObject())); + if (-1 != _optionsPage->UAVObject->findText(notification->getDataObject())) { + _optionsPage->UAVObject->setCurrentIndex(_optionsPage->UAVObject->findText(notification->getDataObject())); } - options_page->UAVObjectField->clear(); + _optionsPage->UAVObjectField->clear(); QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast(objManager.getObject(uavDataObject)); + UAVDataObject* obj = dynamic_cast(_objManager.getObject(uavDataObject)); if (obj != NULL ) { QList fieldList = obj->getFields(); foreach (UAVObjectField* field, fieldList) { - options_page->UAVObjectField->addItem(field->getName()); + _optionsPage->UAVObjectField->addItem(field->getName()); } } - if (-1 != options_page->UAVObjectField->findText(notification->getObjectField())) { - options_page->UAVObjectField->setCurrentIndex(options_page->UAVObjectField->findText(notification->getObjectField())); + if (-1 != _optionsPage->UAVObjectField->findText(notification->getObjectField())) { + _optionsPage->UAVObjectField->setCurrentIndex(_optionsPage->UAVObjectField->findText(notification->getObjectField())); } - if (-1 != options_page->Sound1->findText(notification->getSound1())) { - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + if (-1 != _optionsPage->Sound1->findText(notification->getSound1())) { + _optionsPage->Sound1->setCurrentIndex(_optionsPage->Sound1->findText(notification->getSound1())); } else { // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound1->setCurrentIndex(options_page->Sound1->findText(notification->getSound1())); + _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); + _optionsPage->Sound1->setCurrentIndex(_optionsPage->Sound1->findText(notification->getSound1())); } - if (-1 != options_page->Sound2->findText(notification->getSound2())) { - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + if (-1 != _optionsPage->Sound2->findText(notification->getSound2())) { + _optionsPage->Sound2->setCurrentIndex(_optionsPage->Sound2->findText(notification->getSound2())); } else { // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound2->setCurrentIndex(options_page->Sound2->findText(notification->getSound2())); + _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); + _optionsPage->Sound2->setCurrentIndex(_optionsPage->Sound2->findText(notification->getSound2())); } - if (-1 != options_page->Sound3->findText(notification->getSound3())) { - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + if (-1 != _optionsPage->Sound3->findText(notification->getSound3())) { + _optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3())); } else { // show item from default location - options_page->SoundCollectionList->setCurrentIndex(options_page->SoundCollectionList->findText("default")); - options_page->Sound3->setCurrentIndex(options_page->Sound3->findText(notification->getSound3())); + _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); + _optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3())); } if (-1 != _valueRange->findText(notification->range())) { @@ -534,120 +508,123 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) setDynamicValueField(notification); - connect(options_page->UAVObject, SIGNAL(currentIndexChanged(QString)), + connect(_optionsPage->UAVObject, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVObject_indexChanged(QString))); - connect(options_page->UAVObjectField, SIGNAL(currentIndexChanged(QString)), - this, SLOT(onUAVField_indexChanged(QString))); + connect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_UAVField_indexChanged(QString))); } -//----------------------------------------------------------------------------- void NotifyPluginOptionsPage::setDynamicValueField(NotificationItem* notification) { - if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) spinValue->setValue(notification->singleValue()); else { - if(QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) + if (QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) comboBoxValue->setCurrentIndex(notification->singleValue()); else { - if(QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { - resetValueRange(); - rangeValue->setText(QString("%1%2").arg(notification->singleValue()) - .arg(notification->valueRange2())); + if (QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { + //resetValueRange(); + QString str = QString("%1%2").arg(notification->singleValue(), 5, 'f', 2, '0') + .arg(notification->valueRange2(), 5, 'f', 2, '0'); + rangeValue->setText(str); } else { qNotifyDebug() << "NotifyPluginOptionsPage::setDynamicValueField | unknown _fieldValue: " << _fieldValue; } - } } } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) +UAVObjectField* NotifyPluginOptionsPage::getObjectFieldFromPage() { - bool select = false; - notifySound->stop(); - if (selected.indexes().size()) { - select = true; - _selectedNotification = privListNotifications.at(selected.indexes().at(0).row()); - updateConfigView(_selectedNotification); - UAVDataObject* obj = dynamic_cast( objManager.getObject(options_page->UAVObject->currentText())); - UAVObjectField* field = obj->getField(options_page->UAVObjectField->currentText()); - addDynamicField(field); - setDynamicValueField(_selectedNotification); - } - - options_page->buttonModify->setEnabled(select); - options_page->buttonDelete->setEnabled(select); - options_page->buttonPlayNotification->setEnabled(select); + UAVDataObject* obj = dynamic_cast( _objManager.getObject(_optionsPage->UAVObject->currentText())); + return obj->getField(_optionsPage->UAVObjectField->currentText()); } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::on_buttonAddNotification_clicked() + +UAVObjectField* NotifyPluginOptionsPage::getObjectFieldFromSelected() +{ + UAVDataObject* obj = dynamic_cast(_objManager.getObject(_selectedNotification->getDataObject())); + return obj->getField(_selectedNotification->getObjectField()); +} + +void NotifyPluginOptionsPage::on_table_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) +{ + bool select = false; + _notifySound->stop(); + if (selected.indexes().size()) { + select = true; + _selectedNotification = _privListNotifications.at(selected.indexes().at(0).row()); + UAVObjectField* field = getObjectFieldFromSelected(); + addDynamicField(field); + updateConfigView(_selectedNotification); + } + + _optionsPage->buttonModify->setEnabled(select); + _optionsPage->buttonDelete->setEnabled(select); + _optionsPage->buttonPlayNotification->setEnabled(select); +} + +void NotifyPluginOptionsPage::on_button_AddNotification_clicked() { NotificationItem* notification = new NotificationItem; - if (options_page->SoundDirectoryPathChooser->path()=="") { - QPalette textPalette=options_page->SoundDirectoryPathChooser->palette(); - textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); - options_page->SoundDirectoryPathChooser->setPalette(textPalette); - options_page->SoundDirectoryPathChooser->setPath("please select sound collection folder"); - return; + if (_optionsPage->SoundDirectoryPathChooser->path().isEmpty()) { + QPalette textPalette=_optionsPage->SoundDirectoryPathChooser->palette(); + textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); + _optionsPage->SoundDirectoryPathChooser->setPalette(textPalette); + _optionsPage->SoundDirectoryPathChooser->setPath("please select sound collection folder"); + return; } - notification->setSoundCollectionPath(options_page->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(options_page->SoundCollectionList->currentText()); - notification->setDataObject(options_page->UAVObject->currentText()); - notification->setObjectField(options_page->UAVObjectField->currentText()); + notification->setSoundCollectionPath(_optionsPage->SoundDirectoryPathChooser->path()); + notification->setCurrentLanguage(_optionsPage->SoundCollectionList->currentText()); + notification->setDataObject(_optionsPage->UAVObject->currentText()); + notification->setObjectField(_optionsPage->UAVObjectField->currentText()); notification->setRange(_valueRange->currentText()); - if(QSpinBox* spinValue = dynamic_cast(_fieldValue)) + if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) notification->setSingleValue(spinValue->value()); - if (options_page->Sound1->currentText().size() > 0) - notification->setSound1(options_page->Sound1->currentText()); + if (_optionsPage->Sound1->currentText().size() > 0) + notification->setSound1(_optionsPage->Sound1->currentText()); - notification->setSound2(options_page->Sound2->currentText()); - notification->setSound3(options_page->Sound3->currentText()); + notification->setSound2(_optionsPage->Sound2->currentText()); + notification->setSound3(_optionsPage->Sound3->currentText()); - if ( ((!options_page->Sound2->currentText().size()) && (_sayOrder->currentText()=="After second")) - || ((!options_page->Sound3->currentText().size()) && (_sayOrder->currentText()=="After third")) ) { + if ( ((!_optionsPage->Sound2->currentText().size()) && (_sayOrder->currentText()=="After second")) + || ((!_optionsPage->Sound3->currentText().size()) && (_sayOrder->currentText()=="After third")) ) { return; } else { notification->setSayOrder(_sayOrder->currentText()); } _notifyRulesModel->entryAdded(notification); - _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(privListNotifications.size()-1,0,QModelIndex()), + _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(_privListNotifications.size()-1,0,QModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::on_buttonDeleteNotification_clicked() +void NotifyPluginOptionsPage::on_button_DeleteNotification_clicked() { _notifyRulesModel->removeRow(_notifyRulesSelection->currentIndex().row()); if (!_notifyRulesModel->rowCount() && (_notifyRulesSelection->currentIndex().row() > 0 && _notifyRulesSelection->currentIndex().row() < _notifyRulesModel->rowCount()) ) { - options_page->buttonDelete->setEnabled(false); - options_page->buttonModify->setEnabled(false); - options_page->buttonPlayNotification->setEnabled(false); + _optionsPage->buttonDelete->setEnabled(false); + _optionsPage->buttonModify->setEnabled(false); + _optionsPage->buttonPlayNotification->setEnabled(false); } - } -//----------------------------------------------------------------------------- -void NotifyPluginOptionsPage::on_buttonModifyNotification_clicked() +void NotifyPluginOptionsPage::on_button_ModifyNotification_clicked() { NotificationItem* notification = new NotificationItem; getOptionsPageValues(notification); - notification->setRetryString(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryString()); - notification->setLifetime(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->lifetime()); - notification->setMute(privListNotifications.at(_notifyRulesSelection->currentIndex().row())->mute()); + notification->setRetryString(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryString()); + notification->setLifetime(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->lifetime()); + notification->setMute(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->mute()); - privListNotifications.replace(_notifyRulesSelection->currentIndex().row(),notification); + _privListNotifications.replace(_notifyRulesSelection->currentIndex().row(),notification); entryUpdated(_notifyRulesSelection->currentIndex().row()); - } - diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index f4a29ae41..3f36f3f4d 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -57,78 +57,130 @@ using namespace Core; class NotifyPluginOptionsPage : public IOptionsPage { - Q_OBJECT + Q_OBJECT + public: - explicit NotifyPluginOptionsPage(/*NotificationItem *config, */QObject *parent = 0); - ~NotifyPluginOptionsPage(); - QString id() const { return QLatin1String("settings"); } - QString trName() const { return tr("settings"); } - QString category() const { return QLatin1String("Notify Plugin");} - QString trCategory() const { return tr("Notify Plugin");} + + explicit NotifyPluginOptionsPage(QObject *parent = 0); + ~NotifyPluginOptionsPage(); + QString id() const { return QLatin1String("settings"); } + QString trName() const { return tr("settings"); } + QString category() const { return QLatin1String("Notify Plugin");} + QString trCategory() const { return tr("Notify Plugin");} QWidget *createPage(QWidget *parent); void apply(); - void finish(); - void restoreFromSettings(); + void finish(); + void restoreFromSettings(); - void updateConfigView(NotificationItem* notification); - void getOptionsPageValues(NotificationItem* notification); + void updateConfigView(NotificationItem* notification); + void getOptionsPageValues(NotificationItem* notification); + UAVObjectField* getObjectFieldFromPage(); + UAVObjectField* getObjectFieldFromSelected(); signals: void updateNotifications(QList list); - //void resetNotification(void); void entryUpdated(int index); +private slots: + void on_button_TestSoundNotification_clicked(); + void on_button_AddNotification_clicked(); + void on_button_DeleteNotification_clicked(); + void on_button_ModifyNotification_clicked(); + + /** + * We can use continuous selection, to select simultaneously + * multiple rows to move them(using drag & drop) inside table ranges. + */ + void on_table_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ); + + void on_soundLanguage_indexChanged(int index); + void on_buttonSoundFolder_clicked(const QString& path); + void on_UAVObject_indexChanged(QString val); + void on_UAVField_indexChanged(QString val); + void on_changeButtonText(Phonon::State newstate, Phonon::State oldstate); + void on_checkEnableSound_toggled(bool state); + + /** + * Important when we change to or from "In range" value + * For enums UI layout stayed the same, but for numeric values + * we need to change UI to show edit line, + * to have possibility assign range limits for value. + */ + void on_rangeValue_indexChanged(QString); + + void on_FinishedPlaying(void); + + private: Q_DISABLE_COPY(NotifyPluginOptionsPage) void resetValueRange(); + void resetFieldType(); + void setDynamicValueField(NotificationItem* notification); void addDynamicField(UAVObjectField* objField); void addDynamicValueLayout(); + void setDynamicValueWidget(UAVObjectField* objField); + void initButtons(); void initPhononPlayer(); void initRulesTable(); -private slots: - void on_buttonTestSoundNotification_clicked(); - - void on_buttonAddNotification_clicked(); - void on_buttonDeleteNotification_clicked(); - void on_buttonModifyNotification_clicked(); - void on_tableNotification_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ); - void on_soundLanguage_indexChanged(int index); - void on_buttonSoundFolder_clicked(const QString& path); - void on_UAVObject_indexChanged(QString val); - void onUAVField_indexChanged(QString val); - void changeButtonText(Phonon::State newstate, Phonon::State oldstate); - void on_chkEnableSound_toggled(bool state); - void on_rangeValue_indexChanged(QString); - - void onFinishedPlaying(void); - private: - UAVObjectManager& objManager; - SoundNotifyPlugin* owner; - QStringList listDirCollections; - QStringList listSoundFiles; - QString currentCollectionPath; - Phonon::MediaObject *sound1; - Phonon::MediaObject *sound2; - QScopedPointer notifySound; - Phonon::AudioOutput *audioOutput; - QScopedPointer _notifyRulesModel; - QItemSelectionModel* _notifyRulesSelection; - QList privListNotifications; + UAVObjectManager& _objManager; + SoundNotifyPlugin* _owner; + QStringList _listDirCollections; + QStringList _listSoundFiles; + QString _currentCollectionPath; + Phonon::MediaObject* _sound1; + Phonon::MediaObject* _sound2; + QScopedPointer _notifySound; + Phonon::AudioOutput* _audioOutput; - QScopedPointer options_page; + QScopedPointer _notifyRulesModel; + QItemSelectionModel* _notifyRulesSelection; + /** + * Local copy of notification list, which owned by notify plugin. + * Notification list readed once on application loaded, during + * notify plugin startup, then on open options page. + * This copy is simple assignment, but due to implicitly sharing + * we don't have additional cost for that, copy will created + * only after modification of private notify list. + */ + QList _privListNotifications; + + QScopedPointer _optionsPage; + + //! widget to convinient selection of condition for field value (equal, lower, greater) QComboBox* _valueRange; + + //! widget to convinient selection of order in which sounds will be played QComboBox* _sayOrder; + + //! widget to represent edit widget for UAVObjectfield, + //! can be spinbox - for numerics, combobox - enums, or + //! lineedit - for range limits QWidget* _fieldValue; + + //! type of UAVObjectField - numeric or ENUM + //! this variable needs to correctly set dynamic UI elemen _fieldValue + //! NOTE: ocassionaly it should be invalidated (= -1) to reset _fieldValue int _fieldType; + + //! actualy reference to optionsPageWidget, + //! we MUST hold it beyond the scope of createPage func + //! to have possibility change dynamic parts of options page layout in future QWidget* _form; + + //! needs to correctly update UI during transitions from "In Range" to other + //! _valueRange entries and back direction as well + QString _prevRangeValue; + + //! Currently selected notification, all controls filled accroding to it. + //! On options page startup, always points to first row. NotificationItem* _selectedNotification; }; diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui index 23d05c2a0..94560ff1a 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.ui @@ -266,7 +266,7 @@ p, li { white-space: pre-wrap; } - QAbstractItemView::SingleSelection + QAbstractItemView::ContiguousSelection QAbstractItemView::SelectRows diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index 138af106b..b1fd1c737 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -30,8 +30,6 @@ #include #include -static int _dragStartRow = -1; -static int _dragNumRows = -1; const char* mime_type_notify_table = "openpilot/notify_plugin_table"; NotifyTableModel::NotifyTableModel(QList& parentList, QObject* parent) @@ -47,19 +45,19 @@ bool NotifyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::DisplayRole) { - if(eMESSAGE_NAME == index.column()) { + if(eMessageName == index.column()) { emit dataChanged(index, index); return true; } } if (index.isValid() && role == Qt::EditRole) { - if(eREPEAT_VALUE == index.column()) + if(eRepeatValue == index.column()) _list.at(index.row())->setRetryString(value.toString()); else { - if(eEXPIRE_TIME == index.column()) + if(eExpireTimer == index.column()) _list.at(index.row())->setLifetime(value.toInt()); else { - if(eENABLE_NOTIFICATION == index.column()) + if(eTurnOn == index.column()) _list.at(index.row())->setMute(value.toBool()); } } @@ -83,16 +81,16 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const { switch(index.column()) { - case eMESSAGE_NAME: - return _list.at(index.row())->parseNotifyMessage(); + case eMessageName: + return _list.at(index.row())->toString(); - case eREPEAT_VALUE: + case eRepeatValue: return _list.at(index.row())->retryString(); - case eEXPIRE_TIME: + case eExpireTimer: return _list.at(index.row())->lifetime(); - case eENABLE_NOTIFICATION: + case eTurnOn: return _list.at(index.row())->mute(); default: @@ -126,13 +124,13 @@ bool NotifyTableModel::insertRows(int position, int rows, const QModelIndex& ind { Q_UNUSED(index); - if((-1 == position) || (-1 == rows) ) + if (-1 == position || -1 == rows) return false; beginInsertRows(QModelIndex(), position, position + rows - 1); - for (int row = 0; row < rows; ++row) { - _list.insert(position, new NotificationItem()); + for (int i = 0; i < rows; ++i) { + _list.insert(position + i, new NotificationItem()); } endInsertRows(); @@ -171,6 +169,17 @@ void NotifyTableModel::entryAdded(NotificationItem* item) entryUpdated(rowCount() - 1); } +Qt::DropActions NotifyTableModel::supportedDropActions() const +{ + return Qt::MoveAction; +} + +QStringList NotifyTableModel::mimeTypes() const +{ + QStringList types; + types << mime_type_notify_table; + return types; +} bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex& parent) @@ -198,48 +207,31 @@ bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction acti QByteArray encodedData = data->data(mime_type_notify_table); QDataStream stream(&encodedData, QIODevice::ReadOnly); int rows = beginRow; + // read next item from input MIME and drop into the table line by line while(!stream.atEnd()) { qint32 ptr; stream >> ptr; NotificationItem* item = reinterpret_cast(ptr); int dragged = _list.indexOf(item); + // we can drag item from top rows to bottom (DOWN_DIRECTION), + // or from bottom rows to top rows (UP_DIRECTION) + enum { UP_DIRECTION, DOWN_DIRECTION }; + int direction = (dragged < rows) ? DOWN_DIRECTION : (dragged += 1, UP_DIRECTION); + Q_ASSERT(insertRows(rows + direction, 1, QModelIndex())); if(-1 == dragged || rows >= _list.size() || dragged == rows) { qNotifyDebug() << "no such item"; + return false; } - removeRows(rows, 1, QModelIndex()); - insertRows(rows, 1, QModelIndex()); - _list.replace(dragged, item); - // _list.swap(dragged, rows); - ++rows; + _list.replace(rows + direction, item); + Q_ASSERT(removeRows(dragged, 1, QModelIndex())); + if(direction == UP_DIRECTION) + ++rows; }; QModelIndex idxTopLeft = index(beginRow, 0, QModelIndex()); QModelIndex idxBotRight = index(beginRow, columnCount(QModelIndex()), QModelIndex()); emit dataChanged(idxTopLeft, idxBotRight); - //QStringList newItems; - - //removeRows(_dragStartRow, _dragNumRows, QModelIndex()); - //insertRows(beginRow, rows, QModelIndex()); -// int rows = beginRow; -// while (!stream.atEnd()) { -// _list.at(index.row())->deserialize(stream); -// ++rows; -// } - -// while(rows) { -// int column = 0; -// foreach (const QString& text, newItems) { -// QModelIndex idx = index(beginRow, column, QModelIndex()); -// if(!column) -// setData(const_cast(idx), text, Qt::DisplayRole); -// else -// setData(const_cast(idx), text, Qt::EditRole); -// ++column; -// } -// ++beginRow; -// --rows; -// } return true; } @@ -251,35 +243,13 @@ QMimeData* NotifyTableModel::mimeData(const QModelIndexList& indexes) const QDataStream stream(&encodedData, QIODevice::WriteOnly); int rows = 0; foreach (const QModelIndex& index, indexes) { - if(!index.column()) { + if (!index.column()) { qint32 item = reinterpret_cast(_list.at(index.row())); stream << item; + ++rows; } - ++rows; } - -// int numRows = 0; -// foreach (const QModelIndex& index, indexes) { -// if (index.isValid() && index.column()) { -// _list.at(index.row())->serialize(stream); -//// if(!index.column()) { -//// numRows++; -//// QString name = data(index, Qt::DisplayRole).toString(); -//// stream << name; -//// } else { -//// QString text = data(index, Qt::EditRole).toString(); -//// stream << text; -//// } -// } -// } - mimeData->setData(mime_type_notify_table, encodedData); - - //emit dragRows(indexes.at(0).row(), rows); - dropRows(indexes.at(0).row(), rows); - //_dragStartRow = indexes.at(0).row(); - //_dragNumRows = 1/*numRows*/; - return mimeData; } diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index 3168a848f..28eb8cc68 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -33,72 +33,58 @@ #include #include "notificationitem.h" -enum ColumnNames { eMESSAGE_NAME, eREPEAT_VALUE, eEXPIRE_TIME, eENABLE_NOTIFICATION }; +enum ColumnNames { eMessageName, eRepeatValue, eExpireTimer, eTurnOn }; class NotifyTableModel : public QAbstractTableModel { - Q_OBJECT + Q_OBJECT - enum {eColumnCount = 4 }; + enum {eColumnCount = 4 }; public: - NotifyTableModel(QList& parentList, QObject* parent = 0); - - int rowCount(const QModelIndex& parent = QModelIndex()) const - { - return _list.count(); - } - - int columnCount(const QModelIndex &/*parent*/) const - { - return eColumnCount; - } - - Qt::ItemFlags flags(const QModelIndex &index) const - { - if (!index.isValid()) - return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; - - return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; - } - - Qt::DropActions supportedDropActions() const + NotifyTableModel(QList& parentList, QObject* parent = 0); + int rowCount(const QModelIndex& parent = QModelIndex()) const { - return Qt::MoveAction; + return _list.count(); } - QStringList mimeTypes() const - { - QStringList types; - types << "application/vnd.text.list"; - return types; - } + int columnCount(const QModelIndex &/*parent*/) const + { + return eColumnCount; + } - bool dropMimeData( const QMimeData * data, Qt::DropAction action, int row, - int column, const QModelIndex& parent); - QMimeData* mimeData(const QModelIndexList &indexes) const; + Qt::ItemFlags flags(const QModelIndex &index) const + { + if (!index.isValid()) + return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; + + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + } + QStringList mimeTypes() const; + Qt::DropActions supportedDropActions() const; + bool dropMimeData( const QMimeData * data, Qt::DropAction action, int row, + int column, const QModelIndex& parent); + QMimeData* mimeData(const QModelIndexList &indexes) const; - bool setData(const QModelIndex &index, const QVariant &value, int role); - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - bool insertRows(int position, int rows, const QModelIndex &index); - bool removeRows(int position, int rows, const QModelIndex &index); - - void entryAdded(NotificationItem* item); + bool setData(const QModelIndex &index, const QVariant &value, int role); + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + bool insertRows(int position, int rows, const QModelIndex &index); + bool removeRows(int position, int rows, const QModelIndex &index); + void entryAdded(NotificationItem* item); signals: - void dragRows(int position, int count); + void dragRows(int position, int count); private slots: - void entryUpdated(int offset); - void dropRows(int position, int count) const; + void entryUpdated(int offset); + void dropRows(int position, int count) const; private: - mutable QList& _list; - QStringList _headerStrings; + mutable QList& _list; + QStringList _headerStrings; }; - #endif // NOTIFYTABLEMODEL_H From 20757c2efd40484c107d6b5d892c51721a32da80 Mon Sep 17 00:00:00 2001 From: Nickolay Date: Wed, 12 Oct 2011 08:36:05 +0300 Subject: [PATCH 09/72] +complete all features; +testing in progress; --- .../src/plugins/notify/NotificationItem.h | 11 +- .../src/plugins/notify/notificationitem.cpp | 55 +- .../src/plugins/notify/notifylogging.cpp | 2 +- .../src/plugins/notify/notifyplugin.cpp | 440 ++++++------ .../src/plugins/notify/notifyplugin.h | 22 +- .../notify/notifypluginoptionspage.cpp | 627 +++++++++--------- .../plugins/notify/notifypluginoptionspage.h | 99 ++- .../src/plugins/notify/notifytablemodel.cpp | 27 +- 8 files changed, 687 insertions(+), 596 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index 1898f1a55..d4929a1e5 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -63,8 +63,8 @@ public: QString getSayOrder() const { return _sayOrder; } void setSayOrder(QString text) { _sayOrder = text; } - double singleValue() const { return _singleValue; } - void setSingleValue(double value) { _singleValue = value; } + QVariant singleValue() const { return _singleValue; } + void setSingleValue(QVariant value) { _singleValue = value; } double valueRange2() const { return _valueRange2; } void setValueRange2(double value) { _valueRange2 = value; } @@ -131,6 +131,7 @@ public: QTimer* getTimer() const { return _timer; } void startTimer(int value); + void restartTimer(); void stopTimer(); void disposeTimer(); @@ -141,7 +142,7 @@ public: void disposeExpireTimer(); bool isNowPlaying; - bool firstStart; + bool _isPlayed; static QStringList sayOrderValues; static QStringList retryValues; @@ -184,8 +185,8 @@ private: //! order in what sounds 1-3 will be played QString _sayOrder; - //! one-side range, value maybe lower or greater - double _singleValue; + //! one-side range, value(numeric or ENUM type) maybe lower, greater or in range + QVariant _singleValue; //! both-side range, value should be inside the range //double _valueRange1; diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 1b0e634a6..ec86aabcd 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -59,7 +59,7 @@ QStringList NotificationItem::retryValues; NotificationItem::NotificationItem(QObject *parent) : QObject(parent) , isNowPlaying(0) - , firstStart(true) + , _isPlayed(false) , _timer(NULL) , _expireTimer(NULL) , _soundCollectionPath("") @@ -77,10 +77,12 @@ NotificationItem::NotificationItem(QObject *parent) , _expireTimeout(eDefaultTimeout) , _mute(false) { + NotificationItem::sayOrderValues.clear(); NotificationItem::sayOrderValues.append(cStrBefore1st); NotificationItem::sayOrderValues.append(cStrBefore2nd); NotificationItem::sayOrderValues.append(cStrAfter2nd); + NotificationItem::retryValues.clear(); NotificationItem::retryValues.append(cStrRetryOnce); NotificationItem::retryValues.append(cStrRetryInstantly); NotificationItem::retryValues.append(cStrRetry10sec); @@ -92,7 +94,7 @@ NotificationItem::NotificationItem(QObject *parent) void NotificationItem::copyTo(NotificationItem* that) const { that->isNowPlaying = isNowPlaying; - that->firstStart = firstStart; + that->_isPlayed = _isPlayed; that->_soundCollectionPath = _soundCollectionPath; that->_currentLanguage = _currentLanguage; that->_soundCollectionPath = _soundCollectionPath; @@ -142,7 +144,8 @@ void NotificationItem::restoreState(QSettings* settings) setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); - setSingleValue(settings->value(QLatin1String("Value1"), tr("")).toDouble()); + QVariant value = settings->value(QLatin1String("Value1"), tr("")); + setSingleValue(value); setValueRange2(settings->value(QLatin1String("Value2"), tr("")).toDouble()); setRetryString(settings->value(QLatin1String("Repeat"), tr("")).toString()); setLifetime(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); @@ -185,16 +188,26 @@ void NotificationItem::deseriaize(QDataStream& stream) stream >> this->_mute; } -void NotificationItem::startTimer(int value) +void NotificationItem::startTimer(int msec) { if (!_timer) { _timer = new QTimer(this); - _timer->setInterval(value); + _timer->setInterval(msec); } if (!_timer->isActive()) _timer->start(); } + +void NotificationItem::restartTimer() +{ + if (!_timer) { + if (!_timer->isActive()) + _timer->start(); + } +} + + void NotificationItem::stopTimer() { if (_timer) { @@ -311,17 +324,26 @@ QStringList valueToSoundList(QString value) return digitWavs; } +QString stringFromValue(QVariant value, UAVObjectField* field) +{ + Q_ASSERT(field); + Q_ASSERT(!value.isNull()); + QString str; + if (UAVObjectField::ENUM == field->getType()) { + if(!field->getOptions().contains(value.toString())) + return QString(); + str = value.toString(); + } else { + str = QString("%L1").arg(value.toDouble()); + } + return str; +} + QString NotificationItem::toString() { QString str; - QString value; UAVObjectField* field = getUAVObjectField(); - if (UAVObjectField::ENUM == field->getType()) { - Q_ASSERT(singleValue() < field->getOptions().size()); - value = field->getOptions().at(singleValue()); - } else { - value = QString("%L1").arg(singleValue()); - } + QString value = stringFromValue(singleValue(), field); int pos = getValuePosition(getSayOrder().trimmed()); QStringList lst; @@ -353,15 +375,8 @@ QStringList& NotificationItem::toSoundList() // tips: // check of *.wav files exist needed for playing phonon queues; // if phonon player don't find next file in queue, it buzz - - QString value; UAVObjectField* field = getUAVObjectField(); - if (UAVObjectField::ENUM == field->getType()) { - Q_ASSERT(singleValue() < field->getOptions().size()); - value = field->getOptions().at(singleValue()); - } else { - value = QString("%L1").arg(singleValue()); - } + QString value = stringFromValue(singleValue(), field); // generate queue of sound files to play _messageSequence.clear(); diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp index 0a29cc6e6..3cb11d111 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.cpp @@ -31,7 +31,7 @@ #ifdef DEBUG_NOTIFIES_ENABLE QDebug qNotifyDebug() { - return qDebug(); + return qDebug() << "[NOTIFY_PLG]"; } #endif diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 88cb23621..5ac05776a 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -48,7 +48,6 @@ static const QString VERSION = "1.0.0"; SoundNotifyPlugin::SoundNotifyPlugin() { phonon.mo = NULL; - configured = false; } SoundNotifyPlugin::~SoundNotifyPlugin() @@ -72,13 +71,10 @@ bool SoundNotifyPlugin::initialize(const QStringList& args, QString *errMsg) void SoundNotifyPlugin::extensionsInitialized() { Core::ICore::instance()->readSettings(this); - if ( !configured ){ - readConfig_0_0_0(); - } ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); - removedNotifies.clear(); + _toRemoveNotifications.clear(); connectNotifications(); } @@ -96,46 +92,19 @@ void SoundNotifyPlugin::saveConfig( QSettings* settings, UAVConfigInfo *configIn settings->endGroup(); settings->beginWriteArray("listNotifies"); - for (int i = 0; i < lstNotifications.size(); i++) { + for (int i = 0; i < _notificationList.size(); i++) { settings->setArrayIndex(i); - lstNotifications.at(i)->saveState(settings); + _notificationList.at(i)->saveState(settings); } settings->endArray(); settings->setValue(QLatin1String("EnableSound"), enableSound); } -void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo *configInfo){ - - if ( configInfo->version() == UAVConfigVersion() ){ - // Just for migration to the new format. - configured = false; - return; - } - - settings->beginReadArray("Current"); - settings->setArrayIndex(0); - currentNotification.restoreState(settings); - settings->endArray(); - - // read list of notifications from settings - int size = settings->beginReadArray("listNotifies"); - for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); - NotificationItem* notification = new NotificationItem; - notification->restoreState(settings); - lstNotifications.append(notification); - } - settings->endArray(); - setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); - - configured = true; -} - -void SoundNotifyPlugin::readConfig_0_0_0(){ - - settings = Core::ICore::instance()->settings(); - settings->beginGroup(QLatin1String("NotifyPlugin")); +void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo *configInfo) +{ + // Just for migration to the new format. + //Q_ASSERT(configInfo->version() == UAVConfigVersion()); settings->beginReadArray("Current"); settings->setArrayIndex(0); @@ -148,18 +117,10 @@ void SoundNotifyPlugin::readConfig_0_0_0(){ settings->setArrayIndex(i); NotificationItem* notification = new NotificationItem; notification->restoreState(settings); - lstNotifications.append(notification); + _notificationList.append(notification); } settings->endArray(); setEnableSound(settings->value(QLatin1String("EnableSound"),0).toBool()); - settings->endGroup(); - - ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance(); - connect(pm, SIGNAL(objectAdded(QObject*)), this, SLOT(onTelemetryManagerAdded(QObject*))); - removedNotifies.clear(); - connectNotifications(); - - configured = true; } void SoundNotifyPlugin::onTelemetryManagerAdded(QObject* obj) @@ -186,11 +147,11 @@ void SoundNotifyPlugin::onAutopilotDisconnect() void SoundNotifyPlugin::resetNotification(void) { //first, reject empty args and unknown fields. - foreach(NotificationItem* ntf, lstNotifications) { + foreach(NotificationItem* ntf, _notificationList) { ntf->disposeTimer(); - disconnect(ntf->getTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); + disconnect(ntf->getTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification())); ntf->disposeExpireTimer(); - disconnect(ntf->getExpireTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); + disconnect(ntf->getExpireTimer(), SIGNAL(timeout()), this, SLOT(on_timerRepeated_Notification())); } } @@ -200,10 +161,10 @@ void SoundNotifyPlugin::resetNotification(void) */ void SoundNotifyPlugin::updateNotificationList(QList list) { - removedNotifies.clear(); + _toRemoveNotifications.clear(); resetNotification(); - lstNotifications.clear(); - lstNotifications=list; + _notificationList.clear(); + _notificationList=list; connectNotifications(); Core::ICore::instance()->saveSettings(this); @@ -213,7 +174,7 @@ void SoundNotifyPlugin::connectNotifications() { foreach(UAVDataObject* obj,lstNotifiedUAVObjects) { if (obj != NULL) - disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(appendNotification(UAVObject*))); + disconnect(obj,SIGNAL(objectUpdated(UAVObject*)),this,SLOT(on_arrived_Notification(UAVObject*))); } if (phonon.mo != NULL) { delete phonon.mo; @@ -226,29 +187,33 @@ void SoundNotifyPlugin::connectNotifications() UAVObjectManager *objManager = pm->getObject(); lstNotifiedUAVObjects.clear(); - pendingNotifications.clear(); - lstNotifications.append(removedNotifies); - removedNotifies.clear(); + _pendingNotifications.clear(); + _notificationList.append(_toRemoveNotifications); + _toRemoveNotifications.clear(); //first, reject empty args and unknown fields. - foreach(NotificationItem* notify, lstNotifications) { - notify->firstStart=true; + foreach(NotificationItem* notify, _notificationList) { + notify->_isPlayed = false; notify->isNowPlaying=false; if(notify->mute()) continue; + // check is all sounds presented for notification, + // if not - we must not subscribe to it at all + if(notify->toSoundList().isEmpty()) continue; UAVDataObject* obj = dynamic_cast( objManager->getObject(notify->getDataObject()) ); if (obj != NULL ) { if (!lstNotifiedUAVObjects.contains(obj)) { lstNotifiedUAVObjects.append(obj); - connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + + connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(on_arrived_Notification(UAVObject*))); } } else { qNotifyDebug() << "Error: Object is unknown (" << notify->getDataObject() << ")."; } } - if (lstNotifications.isEmpty()) return; + if (_notificationList.isEmpty()) return; // set notification message to current event phonon.mo = Phonon::createPlayer(Phonon::NotificationCategory); phonon.mo->clearQueue(); @@ -262,138 +227,66 @@ void SoundNotifyPlugin::connectNotifications() this, SLOT(stateChanged(Phonon::State,Phonon::State))); } -void SoundNotifyPlugin::appendNotification(UAVObject *object) +void SoundNotifyPlugin::on_arrived_Notification(UAVObject *object) { - disconnect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); - - foreach(NotificationItem* ntf, lstNotifications) { + foreach(NotificationItem* ntf, _notificationList) { if (object->getName() != ntf->getDataObject()) continue; - if (nowPlayingConfiguration == ntf) + + // skip duplicate notifications + if (_nowPlayingNotification == ntf) continue; + // skip periodical notifications + // this condition accepts: + // 1. Periodical notifications played firstly; + // NOTE: At first time it will be played, then it played only by timer, + // when conditions became false firstStart flag has been cleared and + // notification can be accepted again; + // 2. Once time notifications, they removed immediately after first playing; + // 3. Instant notifications(played one by one without interval); if (ntf->retryString() != "Repeat Instantly" && - ntf->retryString() != "Repeat Once" && !ntf->firstStart) + ntf->retryString() != "Repeat Once" && ntf->_isPlayed) continue; - checkNotificationRule(ntf,object); + qNotifyDebug() << QString("new notification: | %1 | %2 | val1: %3 | val2: %4") + .arg(ntf->getDataObject()) + .arg(ntf->getObjectField()) + .arg(ntf->singleValue().toString()) + .arg(ntf->valueRange2()); + + QString fieldName = ntf->getObjectField(); + UAVObjectField* field = object->getField(fieldName); + + qNotifyDebug() << QString("UAV object: %1 | value: %2") + .arg(object->getName()) + .arg(field->getValue().toString()); + + checkNotificationRule(ntf, object); } - connect(object, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(appendNotification(UAVObject*))); + connect(object, SIGNAL(objectUpdated(UAVObject*)), + this, SLOT(on_arrived_Notification(UAVObject*)), Qt::UniqueConnection); } -void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) -{ - bool condition=false; - double threshold; - QString direction; - QString fieldName; - - threshold = notification->singleValue(); - direction = notification->range(); - fieldName = notification->getObjectField(); - UAVObjectField* field = object->getField(fieldName); - - if (field->getName().isEmpty()) - return; - - double value = field->getDouble(); - switch(direction[0].toAscii()) - { - case 'E': - condition = (value == threshold); - break; - - case 'G': - condition = (value > threshold); - break; - - case 'L': - condition = (value < threshold); - break; - - case 'R': - condition = (value > threshold) && (value < notification->valueRange2()); - break; - - } - - if (!condition) - return; - - if (!playNotification(notification)) { - if (!pendingNotifications.contains(notification)) { - notification->stopTimer(); - - qNotifyDebug() << "add to pending list - " << notification->toString(); - // if audio is busy, start expiration timer - //ms = (notification->getExpiredTimeout()[in sec])*1000 - //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); - pendingNotifications.append(notification); - notification->startExpireTimer(); - connect(notification->getExpireTimer(), SIGNAL(timeout()), this, SLOT(expireTimerHandler())); - } - } -} - -bool SoundNotifyPlugin::playNotification(NotificationItem* notification) -{ - // Check: race condition, if phonon.mo got deleted don't go further - if (phonon.mo == NULL) - return false; - - if (notification->mute()) - return false; - - qNotifyDebug() << "Phonon State: " << phonon.mo->state(); - if ((phonon.mo->state()==Phonon::PausedState) - || (phonon.mo->state()==Phonon::StoppedState) - || phonon.firstPlay) - { - // don't fire expire timer - nowPlayingConfiguration = notification; - notification->stopExpireTimer(); - - if (notification->retryString() == "Repeat Once") { - removedNotifies.append(lstNotifications.takeAt(lstNotifications.indexOf(notification))); - } else { - if (notification->retryString() != "Repeat Instantly") { - QRegExp rxlen("(\\d+)"); - QString value; - int timer_value; - int pos = rxlen.indexIn(notification->retryString()); - if (pos > -1) { - value = rxlen.cap(1); // "189" - timer_value = (value.toInt()+8)*1000; //ms*1000 + average duration of meassage - } - - notification->startTimer(timer_value); - connect(notification->getTimer(), SIGNAL(timeout()), this, SLOT(repeatTimerHandler())); - } - } - notification->firstStart=false; - phonon.mo->clear(); - qNotifyDebug() << "play notification - " << notification->toString(); - foreach (QString item, notification->toSoundList()) { - Phonon::MediaSource *ms = new Phonon::MediaSource(item); - ms->setAutoDelete(true); - phonon.mo->enqueue(*ms); - } - phonon.mo->play(); - phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before - // the state is not "Loading" anymore. - } else { - return false; // if audio is busy - } - return true; -} - -void SoundNotifyPlugin::repeatTimerHandler() +void SoundNotifyPlugin::on_timerRepeated_Notification() { NotificationItem* notification = static_cast(sender()->parent()); + if (!notification) + return; + // skip duplicate notifications + // WARNING: generally we shoudn't ever trap here + // this means, that timer fires to early and notification overlap itself + if (_nowPlayingNotification == notification) { + qNotifyDebug() << "WARN: on_timerRepeated - notification was skipped!"; + notification->restartTimer(); + return; + } - qNotifyDebug() << "repeatTimerHandler - " << notification->toString(); + qNotifyDebug() << QString("repeatTimer: %1% | %2 | %3").arg(notification->getDataObject()) + .arg(notification->getObjectField()) + .arg(notification->toString()); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); UAVObjectManager *objManager = pm->getObject(); @@ -402,15 +295,23 @@ void SoundNotifyPlugin::repeatTimerHandler() checkNotificationRule(notification,object); } -void SoundNotifyPlugin::expireTimerHandler() + +void SoundNotifyPlugin::on_expiredTimer_Notification() { // fire expire timer NotificationItem* notification = static_cast(sender()->parent()); + if(!notification) + return; notification->stopExpireTimer(); - if (!pendingNotifications.isEmpty()) { - qNotifyDebug() << "expireTimerHandler - " << notification->toString(); - pendingNotifications.removeOne(notification); + volatile QMutexLocker lock(&_mutex); + + if (!_pendingNotifications.isEmpty()) { + qNotifyDebug() << QString("expireTimer: %1% | %2 | %3").arg(notification->getDataObject()) + .arg(notification->getObjectField()) + .arg(notification->toString()); + + _pendingNotifications.removeOne(notification); } } @@ -418,8 +319,7 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst { Q_UNUSED(oldstate) - qNotifyDebug() << "File length (ms): " << phonon.mo->totalTime(); - qNotifyDebug() << "New State: " << newstate; + //qNotifyDebug() << "File length (ms): " << phonon.mo->totalTime(); #ifndef Q_OS_WIN // This is a hack to force Linux to wait until the end of the @@ -432,11 +332,18 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst if ((newstate == Phonon::PausedState) || (newstate == Phonon::StoppedState)) { - nowPlayingConfiguration=NULL; - if (!pendingNotifications.isEmpty()) + qNotifyDebug() << "New State: " << QVariant(newstate).toString(); + + volatile QMutexLocker lock(&_mutex); + // assignment to NULL needed to detect that palying is finished + // it's useful in repeat timer handler, where we can detect + // that notification has not overlap with itself + _nowPlayingNotification = NULL; + + if (!_pendingNotifications.isEmpty()) { - NotificationItem* notification = pendingNotifications.takeFirst(); - qNotifyDebug() << "play audioFree - " << notification->toString(); + NotificationItem* notification = _pendingNotifications.takeFirst(); + qNotifyDebug_if(notification) << "play audioFree - " << notification->toString(); playNotification(notification); } } else { @@ -449,4 +356,163 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst } } +bool checkRange(QString fieldValue, QString enumValue, QStringList values, char direction) +{ + + bool ret = false; + switch(direction) + { + case 'E': + ret = !QString::compare(enumValue, fieldValue, Qt::CaseInsensitive) ? true : false; + break; + + default: + ret = true; + break; + }; + return ret; +} + +bool checkRange(double fieldValue, double min, double max, char direction) +{ + bool ret = false; + Q_ASSERT(min < max); + switch(direction) + { + case 'E': + ret = (fieldValue == min); + break; + + case 'G': + ret = (fieldValue > min); + break; + + case 'L': + ret = (fieldValue < min); + break; + + default: + ret = (fieldValue > min) && (fieldValue < max); + break; + }; + + return ret; +} + +void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) +{ + bool condition=false; + + if (notification->mute()) + return; + + QString direction = notification->range(); + QString fieldName = notification->getObjectField(); + UAVObjectField* field = object->getField(fieldName); + + if (field->getName().isEmpty()) + return; + + QVariant value = field->getValue(); + if(UAVObjectField::ENUM == field->getType()) { + condition = checkRange(value.toString(), + notification->singleValue().toString(), + field->getOptions(), + direction[0].toAscii()); + } else { + condition = checkRange(value.toDouble(), + notification->singleValue().toDouble(), + notification->valueRange2(), + direction[0].toAscii()); + } + + notification->_isPlayed = condition; + // if condition has been changed, and already in false state + // we should reset _isPlayed flag and stop repeat timer + if (!notification->_isPlayed) { + notification->stopTimer(); + return; + } + + volatile QMutexLocker lock(&_mutex); + + if (!playNotification(notification)) { + if (!_pendingNotifications.contains(notification) + && (_nowPlayingNotification != notification)) { + notification->stopTimer(); + + qNotifyDebug() << "add to pending list - " << notification->toString(); + // if audio is busy, start expiration timer + //ms = (notification->getExpiredTimeout()[in sec])*1000 + //QxtTimer::singleShot(notification->getExpireTimeout()*1000, this, SLOT(expirationTimerHandler(NotificationItem*)), qVariantFromValue(notification)); + _pendingNotifications.append(notification); + notification->startExpireTimer(); + connect(notification->getExpireTimer(), SIGNAL(timeout()), + this, SLOT(on_expiredTimer_Notification()), Qt::UniqueConnection); + } + } +} + +bool SoundNotifyPlugin::playNotification(NotificationItem* notification) +{ + if(!notification) + return false; + + // Check: race condition, if phonon.mo got deleted don't go further + if (phonon.mo == NULL) + return false; + + //qNotifyDebug() << "Phonon State: " << phonon.mo->state(); + + if ((phonon.mo->state()==Phonon::PausedState) + || (phonon.mo->state()==Phonon::StoppedState) + || phonon.firstPlay) + { + _nowPlayingNotification = notification; + notification->stopExpireTimer(); + + if (notification->retryString() == "Repeat Once") { + _toRemoveNotifications.append(_notificationList.takeAt(_notificationList.indexOf(notification))); + } else { + if (notification->retryString() != "Repeat Instantly") { + QRegExp rxlen("(\\d+)"); + QString value; + int timer_value; + int pos = rxlen.indexIn(notification->retryString()); + if (pos > -1) { + value = rxlen.cap(1); // "189" + + // needs to correct repeat timer value, + // acording to message play duration, + // we don't measure duration of each message, + // simply take average duration + enum { eAverageDurationSec = 8 }; + + enum { eSecToMsec = 1000 }; + + timer_value = (value.toInt() + eAverageDurationSec) * eSecToMsec; + } + + notification->startTimer(timer_value); + connect(notification->getTimer(), SIGNAL(timeout()), + this, SLOT(on_timerRepeated_Notification()), Qt::UniqueConnection); + } + } + phonon.mo->clear(); + qNotifyDebug() << "play: " << notification->toString(); + foreach (QString item, notification->toSoundList()) { + Phonon::MediaSource *ms = new Phonon::MediaSource(item); + ms->setAutoDelete(true); + phonon.mo->enqueue(*ms); + } + phonon.mo->play(); + phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before + // the state is not "Loading" anymore. + return true; + + } + + return false; +} + Q_EXPORT_PLUGIN(SoundNotifyPlugin) diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h index 0b7a31f3b..6a142ff03 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.h +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.h @@ -63,7 +63,7 @@ public: void shutdown(); - QList getListNotifications() { return lstNotifications; } + QList getListNotifications() { return _notificationList; } NotificationItem* getCurrentNotification(){ return ¤tNotification;} bool getEnableSound() const { return enableSound; } @@ -83,14 +83,12 @@ private slots: void connectNotifications(); void updateNotificationList(QList list); void resetNotification(void); - void appendNotification(UAVObject *object); - void repeatTimerHandler(void); - void expireTimerHandler(void); + void on_arrived_Notification(UAVObject *object); + void on_timerRepeated_Notification(void); + void on_expiredTimer_Notification(void); void stateChanged(Phonon::State newstate, Phonon::State oldstate); private: - - bool configured; // just for migration,delete later bool enableSound; QList< QList* > lstMediaSource; QStringList mediaSource; @@ -98,17 +96,17 @@ private: QSettings* settings; QList lstNotifiedUAVObjects; - QList lstNotifications; - QList pendingNotifications; - QList removedNotifies; + QList _notificationList; + QList _pendingNotifications; + QList _toRemoveNotifications; NotificationItem currentNotification; - NotificationItem* nowPlayingConfiguration; + NotificationItem* _nowPlayingNotification; - QString m_field; PhononObject phonon; - NotifyPluginOptionsPage *mop; + NotifyPluginOptionsPage* mop; TelemetryManager* telMngr; + QMutex _mutex; }; #endif // SOUNDNOTIFYPLUGIN_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index fdf0f5cc9..49b274e38 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -57,11 +57,10 @@ NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) : IOptionsPage(parent) , _objManager(*ExtensionSystem::PluginManager::instance()->getObject()) , _owner(qobject_cast(parent)) - , _currentCollectionPath("") - , _valueRange(NULL) + , _dynamicFieldLimit(NULL) + , _dynamicFieldWidget(NULL) + , _dynamicFieldType(-1) , _sayOrder(NULL) - , _fieldValue(NULL) - , _fieldType(-1) , _form(NULL) , _selectedNotification(NULL) {} @@ -74,23 +73,21 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) _optionsPage.reset(new Ui::NotifyPluginOptionsPage()); //main widget QWidget* optionsPageWidget = new QWidget; - _fieldValue = NULL; - _valueRange = NULL; + _dynamicFieldWidget = NULL; + _dynamicFieldLimit = NULL; resetFieldType(); //save ref to form, needed for binding dynamic fields in future _form = optionsPageWidget; //main layout _optionsPage->setupUi(optionsPageWidget); - _listSoundFiles.clear(); - _optionsPage->SoundDirectoryPathChooser->setExpectedKind(Utils::PathChooser::Directory); _optionsPage->SoundDirectoryPathChooser->setPromptDialogTitle(tr("Choose sound collection directory")); connect(_optionsPage->SoundDirectoryPathChooser, SIGNAL(changed(const QString&)), - this, SLOT(on_buttonSoundFolder_clicked(const QString&))); + this, SLOT(on_clicked_buttonSoundFolder(const QString&))); connect(_optionsPage->SoundCollectionList, SIGNAL(currentIndexChanged (int)), - this, SLOT(on_soundLanguage_indexChanged(int))); + this, SLOT(on_changedIndex_soundLanguage(int))); connect(this, SIGNAL(updateNotifications(QList)), _owner, SLOT(updateNotificationList(QList))); @@ -100,8 +97,8 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) // [1] - _selectedNotification = _owner->getCurrentNotification(); - addDynamicValueLayout(); + setSelectedNotification(_owner->getCurrentNotification()); + addDynamicFieldLayout(); // [2] updateConfigView(_selectedNotification); @@ -109,7 +106,8 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) initButtons(); initPhononPlayer(); - _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(0, 0, QModelIndex()), + int curr_row = _privListNotifications.indexOf(_selectedNotification); + _notifyRulesSelection->setCurrentIndex(_notifyRulesModel->index(curr_row, 0, QModelIndex()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); return optionsPageWidget; @@ -125,151 +123,41 @@ void NotifyPluginOptionsPage::apply() void NotifyPluginOptionsPage::finish() { disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_UAVField_indexChanged(QString))); + this, SLOT(on_changedIndex_UAVField(QString))); - disconnect(_notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(on_changeButtonText(Phonon::State,Phonon::State))); - if (_notifySound) { - _notifySound->stop(); - _notifySound->clear(); + disconnect(_testSound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(on_changed_playButtonText(Phonon::State,Phonon::State))); + if (_testSound) { + _testSound->stop(); + _testSound->clear(); } } -void NotifyPluginOptionsPage::addDynamicValueLayout() -{ - NotificationItem* curr = _owner->getCurrentNotification(); - Q_ASSERT(curr); - _optionsPage->dynamicValueLayout->addWidget(new QLabel("Say order ", _form)); - - _sayOrder = new QComboBox(_form); - _optionsPage->dynamicValueLayout->addWidget(_sayOrder); - _sayOrder->addItems(NotificationItem::sayOrderValues); - - _optionsPage->dynamicValueLayout->addWidget(new QLabel("Value is ", _form)); - - UAVDataObject* obj = dynamic_cast(_objManager.getObject(curr->getDataObject())); - UAVObjectField* field = obj->getField(curr->getObjectField()); - Q_ASSERT(obj); - Q_ASSERT(field); - _valueRange = new QComboBox(_form); - _optionsPage->dynamicValueLayout->addWidget(_valueRange); - - addDynamicField(field); -} - -void NotifyPluginOptionsPage::resetValueRange() -{ - (static_cast(_fieldValue))->setInputMask("999.99 - 999.99;"); - (static_cast(_fieldValue))->setText("0000000000"); - (static_cast(_fieldValue))->setCursorPosition(0); -} - -void NotifyPluginOptionsPage::on_rangeValue_indexChanged(QString rangeStr) -{ - Q_ASSERT(_fieldValue); - UAVObjectField* field = getObjectFieldFromPage(); - Q_ASSERT(!!field); - setDynamicValueWidget(field); - setDynamicValueField(_selectedNotification); -} - -void NotifyPluginOptionsPage::resetFieldType() -{ - _fieldType = -1; -} - -void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) -{ - //qDebugNotify_ if (!objField || !parent) << "null input params"; - Q_ASSERT(objField); - if (objField->getType() == _fieldType) { - if (QComboBox* fieldValue = dynamic_cast(_fieldValue)) { - fieldValue->clear(); - QStringList enumValues(objField->getOptions()); - fieldValue->addItems(enumValues); - } - return; - } - - disconnect(_valueRange, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_rangeValue_indexChanged(QString))); - - _valueRange->clear(); - QStringList rangeValues; - if (UAVObjectField::ENUM == objField->getType()) { - rangeValues << cStrEqualTo << cStrInRange; - _valueRange->addItems(rangeValues); - _valueRange->setCurrentIndex(rangeValues.indexOf(_selectedNotification->range())); - - } else { - rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; - _valueRange->addItems(rangeValues); - connect(_valueRange, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_rangeValue_indexChanged(QString))); - } - - setDynamicValueWidget(objField); -} - -void NotifyPluginOptionsPage::setDynamicValueWidget(UAVObjectField* objField) -{ - Q_ASSERT(_valueRange); - - // check if dynamic fileld already settled, - // so if its exists remove it and install new field - if (_fieldValue) { - _optionsPage->dynamicValueLayout->removeWidget(_fieldValue); - delete _fieldValue; - _fieldValue = NULL; - } - _fieldType = objField->getType(); - switch(_fieldType) - { - case UAVObjectField::ENUM: - { - _fieldValue = new QComboBox(_form); - QStringList enumValues(objField->getOptions()); - (dynamic_cast(_fieldValue))->addItems(enumValues); - } - break; - - default: - if (_valueRange->currentText() == cStrInRange) { - _fieldValue = new QLineEdit(_form); - resetValueRange(); - } else { - _fieldValue = new QSpinBox(_form); - } - break; - }; - _optionsPage->dynamicValueLayout->addWidget(_fieldValue); -} - void NotifyPluginOptionsPage::initButtons() { _optionsPage->chkEnableSound->setChecked(_owner->getEnableSound()); connect(_optionsPage->chkEnableSound, SIGNAL(toggled(bool)), - this, SLOT(on_checkEnableSound_toggled(bool))); + this, SLOT(on_toggled_checkEnableSound(bool))); _optionsPage->buttonModify->setEnabled(false); _optionsPage->buttonDelete->setEnabled(false); _optionsPage->buttonPlayNotification->setEnabled(false); connect(_optionsPage->buttonAdd, SIGNAL(pressed()), - this, SLOT(on_button_AddNotification_clicked())); + this, SLOT(on_clicked_buttonAddNotification())); connect(_optionsPage->buttonDelete, SIGNAL(pressed()), - this, SLOT(on_button_DeleteNotification_clicked())); + this, SLOT(on_clicked_buttonDeleteNotification())); connect(_optionsPage->buttonModify, SIGNAL(pressed()), - this, SLOT(on_button_ModifyNotification_clicked())); + this, SLOT(on_clicked_buttonModifyNotification())); connect(_optionsPage->buttonPlayNotification, SIGNAL(clicked()), - this, SLOT(on_button_TestSoundNotification_clicked())); + this, SLOT(on_clicked_buttonTestSoundNotification())); } void NotifyPluginOptionsPage::initPhononPlayer() { - _notifySound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); - connect(_notifySound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), - this,SLOT(on_changeButtonText(Phonon::State,Phonon::State))); - connect(_notifySound.data(), SIGNAL(finished(void)), this, SLOT(on_FinishedPlaying(void))); + _testSound.reset(Phonon::createPlayer(Phonon::NotificationCategory)); + connect(_testSound.data(),SIGNAL(stateChanged(Phonon::State,Phonon::State)), + this,SLOT(on_changed_playButtonText(Phonon::State,Phonon::State))); + connect(_testSound.data(), SIGNAL(finished(void)), this, SLOT(on_FinishedPlaying(void))); } void NotifyPluginOptionsPage::initRulesTable() @@ -280,7 +168,7 @@ void NotifyPluginOptionsPage::initRulesTable() _notifyRulesSelection = new QItemSelectionModel(_notifyRulesModel.data()); connect(_notifyRulesSelection, SIGNAL(selectionChanged ( const QItemSelection &, const QItemSelection & )), - this, SLOT(on_table_changeSelection( const QItemSelection & , const QItemSelection & ))); + this, SLOT(on_changedSelection_notifyTable( const QItemSelection & , const QItemSelection & ))); connect(this, SIGNAL(entryUpdated(int)), _notifyRulesModel.data(), SLOT(entryUpdated(int))); @@ -299,6 +187,159 @@ void NotifyPluginOptionsPage::initRulesTable() _optionsPage->notifyRulesView->setDragDropMode(QAbstractItemView::InternalMove); } +UAVObjectField* NotifyPluginOptionsPage::getObjectFieldFromSelected() +{ + return (_currUAVObject) ? _currUAVObject->getField(_selectedNotification->getObjectField()) : NULL; +} + +void NotifyPluginOptionsPage::setSelectedNotification(NotificationItem* ntf) +{ + _selectedNotification = ntf; + _currUAVObject = dynamic_cast(_objManager.getObject(_selectedNotification->getDataObject())); + if(!_currUAVObject) { + qNotifyDebug() << "no such UAVObject: " << _selectedNotification->getDataObject(); + } +} + +void NotifyPluginOptionsPage::addDynamicFieldLayout() +{ + // there is no need to check (objField == NULL), + // thus it doesn't use in this field directly + + QSizePolicy labelSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + labelSizePolicy.setHorizontalStretch(0); + labelSizePolicy.setVerticalStretch(0); +// labelSizePolicy.setHeightForWidth(UAVObject->sizePolicy().hasHeightForWidth()); + + + QLabel* labelSayOrder = new QLabel("Say order ", _form); + labelSayOrder->setSizePolicy(labelSizePolicy); + + _optionsPage->dynamicValueLayout->addWidget(labelSayOrder); + _sayOrder = new QComboBox(_form); + _optionsPage->dynamicValueLayout->addWidget(_sayOrder); + _sayOrder->addItems(NotificationItem::sayOrderValues); + + QLabel* labelValueIs = new QLabel("Value is ", _form); + labelValueIs->setSizePolicy(labelSizePolicy); + _optionsPage->dynamicValueLayout->addWidget(labelValueIs); + + _dynamicFieldLimit = new QComboBox(_form); + _optionsPage->dynamicValueLayout->addWidget(_dynamicFieldLimit); + UAVObjectField* field = getObjectFieldFromSelected(); + addDynamicField(field); +} + +void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) +{ + if(!objField) { + qNotifyDebug() << "addDynamicField | input objField == NULL"; + return; + } + if (objField->getType() == _dynamicFieldType) { + if (QComboBox* fieldValue = dynamic_cast(_dynamicFieldWidget)) { + fieldValue->clear(); + QStringList enumValues(objField->getOptions()); + fieldValue->addItems(enumValues); + } + return; + } + + disconnect(_dynamicFieldLimit, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_changedIndex_rangeValue(QString))); + + _dynamicFieldLimit->clear(); + QStringList rangeValues; + if (UAVObjectField::ENUM == objField->getType()) { + rangeValues << cStrEqualTo << cStrInRange; + _dynamicFieldLimit->addItems(rangeValues); + _dynamicFieldLimit->setCurrentIndex(rangeValues.indexOf(_selectedNotification->range())); + + } else { + rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; + _dynamicFieldLimit->addItems(rangeValues); + connect(_dynamicFieldLimit, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_changedIndex_rangeValue(QString))); + } + + addDynamicFieldWidget(objField); +} + +void NotifyPluginOptionsPage::addDynamicFieldWidget(UAVObjectField* objField) +{ + if(!objField) { + qNotifyDebug() << "objField == NULL!"; + return; + } + // check if dynamic fileld already settled, + // so if its exists remove it and install new field + if (_dynamicFieldWidget) { + _optionsPage->dynamicValueLayout->removeWidget(_dynamicFieldWidget); + delete _dynamicFieldWidget; + _dynamicFieldWidget = NULL; + } + + QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + + _dynamicFieldType = objField->getType(); + switch(_dynamicFieldType) + { + case UAVObjectField::ENUM: + { + _dynamicFieldWidget = new QComboBox(_form); + QStringList enumValues(objField->getOptions()); + (dynamic_cast(_dynamicFieldWidget))->addItems(enumValues); + } + break; + + default: + Q_ASSERT(_dynamicFieldLimit); + if (_dynamicFieldLimit->currentText() == cStrInRange) { + _dynamicFieldWidget = new QLineEdit(_form); + + (static_cast(_dynamicFieldWidget))->setInputMask("999.99 - 999.99;"); + (static_cast(_dynamicFieldWidget))->setText("0000000000"); + (static_cast(_dynamicFieldWidget))->setCursorPosition(0); + } else { + _dynamicFieldWidget = new QDoubleSpinBox(_form); + (dynamic_cast(_dynamicFieldWidget))->setRange(000.00, 999.99); + } + break; + }; + enum { eDynamicFieldWidth = 100 }; + _dynamicFieldWidget->setSizePolicy(sizePolicy); + _dynamicFieldWidget->setFixedWidth(eDynamicFieldWidth); + _optionsPage->dynamicValueLayout->addWidget(_dynamicFieldWidget); +} + +void NotifyPluginOptionsPage::setDynamicFieldValue(NotificationItem* notification) +{ + if (QDoubleSpinBox* seValue = dynamic_cast(_dynamicFieldWidget)) + seValue->setValue(notification->singleValue().toDouble()); + else { + if (QComboBox* cbValue = dynamic_cast(_dynamicFieldWidget)) { + int idx = cbValue->findText(notification->singleValue().toString()); + if(-1 != idx) + cbValue->setCurrentIndex(idx); + } else { + if (QLineEdit* rangeValue = dynamic_cast(_dynamicFieldWidget)) { + QString str = QString("%1%2").arg(notification->singleValue().toDouble(), 5, 'f', 2, '0') + .arg(notification->valueRange2(), 5, 'f', 2, '0'); + rangeValue->setText(str); + } else { + qNotifyDebug() << "NotifyPluginOptionsPage::setDynamicValueField | unknown _fieldValue: " << _dynamicFieldWidget; + } + } + } +} + +void NotifyPluginOptionsPage::resetFieldType() +{ + _dynamicFieldType = -1; +} + void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notification) { Q_ASSERT(notification); @@ -310,14 +351,14 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio notification->setSound2(_optionsPage->Sound2->currentText()); notification->setSound3(_optionsPage->Sound3->currentText()); notification->setSayOrder(_sayOrder->currentText()); - notification->setRange(_valueRange->currentText()); - if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) + notification->setRange(_dynamicFieldLimit->currentText()); + if (QDoubleSpinBox* spinValue = dynamic_cast(_dynamicFieldWidget)) notification->setSingleValue(spinValue->value()); else { - if (QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) - notification->setSingleValue(comboBoxValue->currentIndex()); + if (QComboBox* comboBoxValue = dynamic_cast(_dynamicFieldWidget)) + notification->setSingleValue(comboBoxValue->currentText()); else { - if (QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { + if (QLineEdit* rangeValue = dynamic_cast(_dynamicFieldWidget)) { QString str = rangeValue->text(); QStringList range = str.split('-'); notification->setSingleValue(range.at(0).toDouble()); @@ -327,113 +368,13 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio } } -void NotifyPluginOptionsPage::on_UAVField_indexChanged(QString field) -{ - resetFieldType(); - UAVDataObject* obj = dynamic_cast( _objManager.getObject(_optionsPage->UAVObject->currentText())); - addDynamicField(obj->getField(field)); - -} - -void NotifyPluginOptionsPage::on_UAVObject_indexChanged(QString val) -{ - resetFieldType(); - UAVDataObject* obj = dynamic_cast( _objManager.getObject(val) ); - QList fieldList = obj->getFields(); - disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVField_indexChanged(QString))); - _optionsPage->UAVObjectField->clear(); - foreach (UAVObjectField* field, fieldList) { - _optionsPage->UAVObjectField->addItem(field->getName()); - } - connect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_UAVField_indexChanged(QString))); - addDynamicField(fieldList.at(0)); -} - -void NotifyPluginOptionsPage::on_buttonSoundFolder_clicked(const QString& path) -{ - QDir dirPath(path); - _listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); - _optionsPage->SoundCollectionList->clear(); - _optionsPage->SoundCollectionList->addItems(_listDirCollections); -} - -void NotifyPluginOptionsPage::on_soundLanguage_indexChanged(int index) -{ - _optionsPage->SoundCollectionList->setCurrentIndex(index); - _currentCollectionPath = _optionsPage->SoundDirectoryPathChooser->path() - + QDir::toNativeSeparators("/" + _optionsPage->SoundCollectionList->currentText()); - - QDir dirPath(_currentCollectionPath); - QStringList filters; - filters << "*.mp3" << "*.wav"; - dirPath.setNameFilters(filters); - _listSoundFiles = dirPath.entryList(filters); - _listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); - _optionsPage->Sound1->clear(); - _optionsPage->Sound2->clear(); - _optionsPage->Sound3->clear(); - _optionsPage->Sound1->addItems(_listSoundFiles); - _optionsPage->Sound2->addItem(""); - _optionsPage->Sound2->addItems(_listSoundFiles); - _optionsPage->Sound3->addItem(""); - _optionsPage->Sound3->addItems(_listSoundFiles); -} - -void NotifyPluginOptionsPage::on_changeButtonText(Phonon::State newstate, Phonon::State oldstate) -{ - //Q_ASSERT(Phonon::ErrorState != newstate); - - if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { - _optionsPage->buttonPlayNotification->setText("Play"); - _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); - } else { - if (newstate == Phonon::PlayingState) { - _optionsPage->buttonPlayNotification->setText("Stop"); - _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); - } - } -} - -void NotifyPluginOptionsPage::on_FinishedPlaying() -{ - _notifySound->clear(); -} - -void NotifyPluginOptionsPage::on_button_TestSoundNotification_clicked() -{ - NotificationItem* notification = NULL; - qNotifyDebug() << "on_buttonTestSoundNotification_clicked"; - Q_ASSERT(-1 != _notifyRulesSelection->currentIndex().row()); - _notifySound->clearQueue(); - notification = _privListNotifications.at(_notifyRulesSelection->currentIndex().row()); - QStringList sequence = notification->toSoundList(); - if (sequence.isEmpty()) { - qNotifyDebug() << "message sequense is empty!"; - return; - } - foreach(QString item, sequence) { - qNotifyDebug() << item; - _notifySound->enqueue(Phonon::MediaSource(item)); - } - _notifySound->play(); -} - -void NotifyPluginOptionsPage::on_checkEnableSound_toggled(bool state) -{ - bool state1 = 1^state; - - QList listOutputs = _notifySound->outputPaths(); - Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); - audioOutput->setMuted(state1); -} - void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) { Q_ASSERT(notification); disconnect(_optionsPage->UAVObject, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_UAVObject_indexChanged(QString))); + this, SLOT(on_changedIndex_UAVObject(QString))); disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_UAVField_indexChanged(QString))); + this, SLOT(on_changedIndex_UAVField(QString))); QString path = notification->getSoundCollectionPath(); if (path.isEmpty()) { @@ -461,13 +402,10 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) } _optionsPage->UAVObjectField->clear(); - QString uavDataObject = notification->getDataObject(); - UAVDataObject* obj = dynamic_cast(_objManager.getObject(uavDataObject)); - if (obj != NULL ) { - QList fieldList = obj->getFields(); - foreach (UAVObjectField* field, fieldList) { + if(_currUAVObject) { + QList fieldList = _currUAVObject->getFields(); + foreach (UAVObjectField* field, fieldList) _optionsPage->UAVObjectField->addItem(field->getName()); - } } if (-1 != _optionsPage->UAVObjectField->findText(notification->getObjectField())) { @@ -498,63 +436,105 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) _optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3())); } - if (-1 != _valueRange->findText(notification->range())) { - _valueRange->setCurrentIndex(_valueRange->findText(notification->range())); + if (-1 != _dynamicFieldLimit->findText(notification->range())) { + _dynamicFieldLimit->setCurrentIndex(_dynamicFieldLimit->findText(notification->range())); } if (-1 != _sayOrder->findText(notification->getSayOrder())) { _sayOrder->setCurrentIndex(_sayOrder->findText(notification->getSayOrder())); } - setDynamicValueField(notification); + setDynamicFieldValue(notification); connect(_optionsPage->UAVObject, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_UAVObject_indexChanged(QString))); + this, SLOT(on_changedIndex_UAVObject(QString))); connect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_UAVField_indexChanged(QString))); + this, SLOT(on_changedIndex_UAVField(QString))); } -void NotifyPluginOptionsPage::setDynamicValueField(NotificationItem* notification) +void NotifyPluginOptionsPage::on_changedIndex_rangeValue(QString rangeStr) { - if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) - spinValue->setValue(notification->singleValue()); - else { - if (QComboBox* comboBoxValue = dynamic_cast(_fieldValue)) - comboBoxValue->setCurrentIndex(notification->singleValue()); - else { - if (QLineEdit* rangeValue = dynamic_cast(_fieldValue)) { - //resetValueRange(); - QString str = QString("%1%2").arg(notification->singleValue(), 5, 'f', 2, '0') - .arg(notification->valueRange2(), 5, 'f', 2, '0'); - rangeValue->setText(str); - } else { - qNotifyDebug() << "NotifyPluginOptionsPage::setDynamicValueField | unknown _fieldValue: " << _fieldValue; - } + Q_ASSERT(_dynamicFieldWidget); + UAVObjectField* field = getObjectFieldFromSelected(); + Q_ASSERT(!!field); + addDynamicFieldWidget(field); + setDynamicFieldValue(_selectedNotification); +} + +void NotifyPluginOptionsPage::on_changedIndex_UAVField(QString field) +{ + resetFieldType(); + Q_ASSERT(_currUAVObject); + addDynamicField(_currUAVObject->getField(field)); + +} + +void NotifyPluginOptionsPage::on_changedIndex_UAVObject(QString val) +{ + resetFieldType(); + _currUAVObject = dynamic_cast( _objManager.getObject(val) ); + if(!_currUAVObject) { + qNotifyDebug() << "on_UAVObject_indexChanged | no such UAVOBject"; + return; + } + QList fieldList = _currUAVObject->getFields(); + disconnect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_changedIndex_UAVField(QString))); + _optionsPage->UAVObjectField->clear(); + foreach (UAVObjectField* field, fieldList) { + _optionsPage->UAVObjectField->addItem(field->getName()); + } + connect(_optionsPage->UAVObjectField, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_changedIndex_UAVField(QString))); + _selectedNotification->setObjectField(fieldList.at(0)->getName()); + addDynamicField(fieldList.at(0)); +} + + +void NotifyPluginOptionsPage::on_changedIndex_soundLanguage(int index) +{ + _optionsPage->SoundCollectionList->setCurrentIndex(index); + QString collectionPath = _optionsPage->SoundDirectoryPathChooser->path() + + QDir::toNativeSeparators("/" + _optionsPage->SoundCollectionList->currentText()); + + QDir dirPath(collectionPath); + QStringList filters; + filters << "*.mp3" << "*.wav"; + dirPath.setNameFilters(filters); + QStringList listSoundFiles = dirPath.entryList(filters); + listSoundFiles.replaceInStrings(QRegExp(".mp3|.wav"), ""); + _optionsPage->Sound1->clear(); + _optionsPage->Sound2->clear(); + _optionsPage->Sound3->clear(); + _optionsPage->Sound1->addItems(listSoundFiles); + _optionsPage->Sound2->addItem(""); + _optionsPage->Sound2->addItems(listSoundFiles); + _optionsPage->Sound3->addItem(""); + _optionsPage->Sound3->addItems(listSoundFiles); +} + + +void NotifyPluginOptionsPage::on_changed_playButtonText(Phonon::State newstate, Phonon::State oldstate) +{ + //Q_ASSERT(Phonon::ErrorState != newstate); + + if (newstate == Phonon::PausedState || newstate == Phonon::StoppedState) { + _optionsPage->buttonPlayNotification->setText("Play"); + _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/play.png")); + } else { + if (newstate == Phonon::PlayingState) { + _optionsPage->buttonPlayNotification->setText("Stop"); + _optionsPage->buttonPlayNotification->setIcon(QPixmap(":/notify/images/stop.png")); } } } -UAVObjectField* NotifyPluginOptionsPage::getObjectFieldFromPage() -{ - UAVDataObject* obj = dynamic_cast( _objManager.getObject(_optionsPage->UAVObject->currentText())); - return obj->getField(_optionsPage->UAVObjectField->currentText()); -} - - -UAVObjectField* NotifyPluginOptionsPage::getObjectFieldFromSelected() -{ - UAVDataObject* obj = dynamic_cast(_objManager.getObject(_selectedNotification->getDataObject())); - return obj->getField(_selectedNotification->getObjectField()); -} - -void NotifyPluginOptionsPage::on_table_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ) +void NotifyPluginOptionsPage::on_changedSelection_notifyTable(const QItemSelection & selected, const QItemSelection & deselected ) { bool select = false; - _notifySound->stop(); + _testSound->stop(); if (selected.indexes().size()) { select = true; - _selectedNotification = _privListNotifications.at(selected.indexes().at(0).row()); + setSelectedNotification(_privListNotifications.at(selected.indexes().at(0).row())); UAVObjectField* field = getObjectFieldFromSelected(); addDynamicField(field); updateConfigView(_selectedNotification); @@ -565,7 +545,34 @@ void NotifyPluginOptionsPage::on_table_changeSelection( const QItemSelection & s _optionsPage->buttonPlayNotification->setEnabled(select); } -void NotifyPluginOptionsPage::on_button_AddNotification_clicked() +void NotifyPluginOptionsPage::on_clicked_buttonSoundFolder(const QString& path) +{ + QDir dirPath(path); + QStringList listDirCollections = dirPath.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); + _optionsPage->SoundCollectionList->clear(); + _optionsPage->SoundCollectionList->addItems(listDirCollections); +} + +void NotifyPluginOptionsPage::on_clicked_buttonTestSoundNotification() +{ + NotificationItem* notification = NULL; + qNotifyDebug() << "on_buttonTestSoundNotification_clicked"; + Q_ASSERT(-1 != _notifyRulesSelection->currentIndex().row()); + _testSound->clearQueue(); + notification = _privListNotifications.at(_notifyRulesSelection->currentIndex().row()); + QStringList sequence = notification->toSoundList(); + if (sequence.isEmpty()) { + qNotifyDebug() << "message sequense is empty!"; + return; + } + foreach(QString item, sequence) { + qNotifyDebug() << item; + _testSound->enqueue(Phonon::MediaSource(item)); + } + _testSound->play(); +} + +void NotifyPluginOptionsPage::on_clicked_buttonAddNotification() { NotificationItem* notification = new NotificationItem; @@ -574,27 +581,15 @@ void NotifyPluginOptionsPage::on_button_AddNotification_clicked() textPalette.setColor(QPalette::Normal,QPalette::Text, Qt::red); _optionsPage->SoundDirectoryPathChooser->setPalette(textPalette); _optionsPage->SoundDirectoryPathChooser->setPath("please select sound collection folder"); + delete notification; return; } + getOptionsPageValues(notification); - notification->setSoundCollectionPath(_optionsPage->SoundDirectoryPathChooser->path()); - notification->setCurrentLanguage(_optionsPage->SoundCollectionList->currentText()); - notification->setDataObject(_optionsPage->UAVObject->currentText()); - notification->setObjectField(_optionsPage->UAVObjectField->currentText()); - notification->setRange(_valueRange->currentText()); - - if (QSpinBox* spinValue = dynamic_cast(_fieldValue)) - notification->setSingleValue(spinValue->value()); - - if (_optionsPage->Sound1->currentText().size() > 0) - notification->setSound1(_optionsPage->Sound1->currentText()); - - notification->setSound2(_optionsPage->Sound2->currentText()); - notification->setSound3(_optionsPage->Sound3->currentText()); - - if ( ((!_optionsPage->Sound2->currentText().size()) && (_sayOrder->currentText()=="After second")) - || ((!_optionsPage->Sound3->currentText().size()) && (_sayOrder->currentText()=="After third")) ) { - return; + if ( ((!_optionsPage->Sound2->currentText().isEmpty()) && (_sayOrder->currentText()=="After second")) + || ((!_optionsPage->Sound3->currentText().isEmpty()) && (_sayOrder->currentText()=="After third")) ) { + delete notification; + return; } else { notification->setSayOrder(_sayOrder->currentText()); } @@ -604,7 +599,7 @@ void NotifyPluginOptionsPage::on_button_AddNotification_clicked() QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } -void NotifyPluginOptionsPage::on_button_DeleteNotification_clicked() +void NotifyPluginOptionsPage::on_clicked_buttonDeleteNotification() { _notifyRulesModel->removeRow(_notifyRulesSelection->currentIndex().row()); if (!_notifyRulesModel->rowCount() @@ -617,7 +612,7 @@ void NotifyPluginOptionsPage::on_button_DeleteNotification_clicked() } } -void NotifyPluginOptionsPage::on_button_ModifyNotification_clicked() +void NotifyPluginOptionsPage::on_clicked_buttonModifyNotification() { NotificationItem* notification = new NotificationItem; getOptionsPageValues(notification); @@ -628,3 +623,17 @@ void NotifyPluginOptionsPage::on_button_ModifyNotification_clicked() _privListNotifications.replace(_notifyRulesSelection->currentIndex().row(),notification); entryUpdated(_notifyRulesSelection->currentIndex().row()); } + +void NotifyPluginOptionsPage::on_FinishedPlaying() +{ + _testSound->clear(); +} + +void NotifyPluginOptionsPage::on_toggled_checkEnableSound(bool state) +{ + bool state1 = 1^state; + + QList listOutputs = _testSound->outputPaths(); + Phonon::AudioOutput * audioOutput = (Phonon::AudioOutput*)listOutputs.last().sink(); + audioOutput->setMuted(state1); +} diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 3f36f3f4d..b270e72a0 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -73,33 +73,28 @@ public: void finish(); void restoreFromSettings(); - void updateConfigView(NotificationItem* notification); - void getOptionsPageValues(NotificationItem* notification); - UAVObjectField* getObjectFieldFromPage(); - UAVObjectField* getObjectFieldFromSelected(); - signals: void updateNotifications(QList list); void entryUpdated(int index); private slots: - void on_button_TestSoundNotification_clicked(); - void on_button_AddNotification_clicked(); - void on_button_DeleteNotification_clicked(); - void on_button_ModifyNotification_clicked(); + void on_clicked_buttonTestSoundNotification(); + void on_clicked_buttonAddNotification(); + void on_clicked_buttonDeleteNotification(); + void on_clicked_buttonModifyNotification(); /** * We can use continuous selection, to select simultaneously * multiple rows to move them(using drag & drop) inside table ranges. */ - void on_table_changeSelection( const QItemSelection & selected, const QItemSelection & deselected ); + void on_changedSelection_notifyTable( const QItemSelection & selected, const QItemSelection & deselected ); - void on_soundLanguage_indexChanged(int index); - void on_buttonSoundFolder_clicked(const QString& path); - void on_UAVObject_indexChanged(QString val); - void on_UAVField_indexChanged(QString val); - void on_changeButtonText(Phonon::State newstate, Phonon::State oldstate); - void on_checkEnableSound_toggled(bool state); + void on_changedIndex_soundLanguage(int index); + void on_clicked_buttonSoundFolder(const QString& path); + void on_changedIndex_UAVObject(QString val); + void on_changedIndex_UAVField(QString val); + void on_changed_playButtonText(Phonon::State newstate, Phonon::State oldstate); + void on_toggled_checkEnableSound(bool state); /** * Important when we change to or from "In range" value @@ -107,7 +102,7 @@ private slots: * we need to change UI to show edit line, * to have possibility assign range limits for value. */ - void on_rangeValue_indexChanged(QString); + void on_changedIndex_rangeValue(QString); void on_FinishedPlaying(void); @@ -115,29 +110,31 @@ private slots: private: Q_DISABLE_COPY(NotifyPluginOptionsPage) - void resetValueRange(); - void resetFieldType(); - - void setDynamicValueField(NotificationItem* notification); - void addDynamicField(UAVObjectField* objField); - void addDynamicValueLayout(); - void setDynamicValueWidget(UAVObjectField* objField); - void initButtons(); void initPhononPlayer(); void initRulesTable(); + void setSelectedNotification(NotificationItem* ntf); + void resetValueRange(); + void resetFieldType(); + + void updateConfigView(NotificationItem* notification); + void getOptionsPageValues(NotificationItem* notification); + UAVObjectField* getObjectFieldFromPage(); + UAVObjectField* getObjectFieldFromSelected(); + + void addDynamicFieldLayout(); + void addDynamicField(UAVObjectField* objField); + void addDynamicFieldWidget(UAVObjectField* objField); + void setDynamicFieldValue(NotificationItem* notification); + private: UAVObjectManager& _objManager; SoundNotifyPlugin* _owner; - QStringList _listDirCollections; - QStringList _listSoundFiles; - QString _currentCollectionPath; - Phonon::MediaObject* _sound1; - Phonon::MediaObject* _sound2; - QScopedPointer _notifySound; - Phonon::AudioOutput* _audioOutput; + + //! Media object uses to test sound playing + QScopedPointer _testSound; QScopedPointer _notifyRulesModel; QItemSelectionModel* _notifyRulesSelection; @@ -154,34 +151,36 @@ private: QScopedPointer _optionsPage; - //! widget to convinient selection of condition for field value (equal, lower, greater) - QComboBox* _valueRange; + //! Widget to convinient selection of condition for field value (equal, lower, greater) + QComboBox* _dynamicFieldLimit; - //! widget to convinient selection of order in which sounds will be played + //! Represents edit widget for dynamic UAVObjectfield, + //! can be spinbox - for numerics, combobox - enums, or + //! lineedit - for numerics with range constraints + QWidget* _dynamicFieldWidget; + + //! Type of UAVObjectField - numeric or ENUM, + //! this variable needs to correctly set appropriate dynamic UI element (_dynamicFieldWidget) + //! NOTE: ocassionaly it should be invalidated (= -1) to reset _dynamicFieldWidget + int _dynamicFieldType; + + //! Widget to convinient selection of position of + //! between sounds[1..3] QComboBox* _sayOrder; - //! widget to represent edit widget for UAVObjectfield, - //! can be spinbox - for numerics, combobox - enums, or - //! lineedit - for range limits - QWidget* _fieldValue; - - //! type of UAVObjectField - numeric or ENUM - //! this variable needs to correctly set dynamic UI elemen _fieldValue - //! NOTE: ocassionaly it should be invalidated (= -1) to reset _fieldValue - int _fieldType; - - //! actualy reference to optionsPageWidget, + //! Actualy reference to optionsPageWidget, //! we MUST hold it beyond the scope of createPage func //! to have possibility change dynamic parts of options page layout in future QWidget* _form; - //! needs to correctly update UI during transitions from "In Range" to other - //! _valueRange entries and back direction as well - QString _prevRangeValue; - //! Currently selected notification, all controls filled accroding to it. //! On options page startup, always points to first row. NotificationItem* _selectedNotification; + + //! Retrieved from UAVObjectManager by name from _selectedNotification, + //! if UAVObjectManager doesn't have such object, this field will be NULL + UAVDataObject* _currUAVObject; + }; #endif // NOTIFYPLUGINOPTIONSPAGE_H diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index b1fd1c737..ed4eb0e56 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -45,19 +45,19 @@ bool NotifyTableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::DisplayRole) { - if(eMessageName == index.column()) { + if (eMessageName == index.column()) { emit dataChanged(index, index); return true; } } if (index.isValid() && role == Qt::EditRole) { - if(eRepeatValue == index.column()) + if (eRepeatValue == index.column()) _list.at(index.row())->setRetryString(value.toString()); else { - if(eExpireTimer == index.column()) + if (eExpireTimer == index.column()) _list.at(index.row())->setLifetime(value.toInt()); else { - if(eTurnOn == index.column()) + if (eTurnOn == index.column()) _list.at(index.row())->setMute(value.toBool()); } } @@ -114,7 +114,7 @@ QVariant NotifyTableModel::headerData(int section, Qt::Orientation orientation, if (orientation == Qt::Horizontal) return _headerStrings.at(section); else - if(orientation == Qt::Vertical) + if (orientation == Qt::Vertical) return QString("%1").arg(section); return QVariant(); @@ -141,7 +141,7 @@ bool NotifyTableModel::removeRows(int position, int rows, const QModelIndex& ind { Q_UNUSED(index); - if((-1 == position) || (-1 == rows) ) + if ((-1 == position) || (-1 == rows) ) return false; beginRemoveRows(QModelIndex(), position, position + rows - 1); @@ -201,7 +201,7 @@ bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction acti beginRow = rowCount(QModelIndex()); } - if(-1 == beginRow) + if (-1 == beginRow) return false; QByteArray encodedData = data->data(mime_type_notify_table); @@ -217,15 +217,18 @@ bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction acti // or from bottom rows to top rows (UP_DIRECTION) enum { UP_DIRECTION, DOWN_DIRECTION }; int direction = (dragged < rows) ? DOWN_DIRECTION : (dragged += 1, UP_DIRECTION); - Q_ASSERT(insertRows(rows + direction, 1, QModelIndex())); - if(-1 == dragged || rows >= _list.size() || dragged == rows) { + // check drop bounds + if (dragged < 0 || ((dragged + 1) >= _list.size() && direction == DOWN_DIRECTION) || dragged == rows) { qNotifyDebug() << "no such item"; - - return false; + continue; } + // addiional check in case dropping of multiple rows + if(rows + direction > _list.size()) continue; + + Q_ASSERT(insertRows(rows + direction, 1, QModelIndex())); _list.replace(rows + direction, item); Q_ASSERT(removeRows(dragged, 1, QModelIndex())); - if(direction == UP_DIRECTION) + if (direction == UP_DIRECTION) ++rows; }; From 44c8c9fbe51a2e66d88f09bea21c68cb6b00a74b Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Fri, 18 Nov 2011 18:30:58 +0100 Subject: [PATCH 10/72] GCS/ScopePlugin: Allow SoftwareInterpolation of measurement value --- .../src/plugins/scope/plotdata.cpp | 21 +++++++++++++-- .../openpilotgcs/src/plugins/scope/plotdata.h | 3 +++ .../src/plugins/scope/scopegadget.cpp | 2 ++ .../scope/scopegadgetconfiguration.cpp | 3 +++ .../plugins/scope/scopegadgetconfiguration.h | 1 + .../plugins/scope/scopegadgetoptionspage.cpp | 23 +++++++++++----- .../plugins/scope/scopegadgetoptionspage.h | 4 +-- .../plugins/scope/scopegadgetoptionspage.ui | 26 +++++++++++++++++++ .../src/plugins/scope/scopegadgetwidget.cpp | 3 ++- .../src/plugins/scope/scopegadgetwidget.h | 2 +- 10 files changed, 76 insertions(+), 12 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp index f2d4bb5af..fdcb75a83 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp @@ -49,9 +49,12 @@ PlotData::PlotData(QString p_uavObject, QString p_uavField) xData = new QVector(); yData = new QVector(); + yDataHistory = new QVector(); curve = 0; scalePower = 0; + interpolationSamples = 1; + interpolationSum = 0.0f; yMinimum = 0; yMaximum = 0; @@ -78,6 +81,7 @@ PlotData::~PlotData() { delete xData; delete yData; + delete yDataHistory; } @@ -91,7 +95,13 @@ bool SequencialPlotData::append(UAVObject* obj) if (field) { //Shift data forward and put the new value at the front - yData->append( valueAsDouble(obj, field) * pow(10, scalePower)); + yDataHistory->append( valueAsDouble(obj, field) * pow(10, scalePower)); + interpolationSum += valueAsDouble(obj, field) * pow(10, scalePower); + if(yDataHistory->size() > interpolationSamples) { + interpolationSum -= yDataHistory->first(); + yDataHistory->pop_front(); + } + yData->append(interpolationSum/yDataHistory->size()); if (yData->size() > m_xWindowSize) { yData->pop_front(); } else @@ -117,8 +127,15 @@ bool ChronoPlotData::append(UAVObject* obj) //Put the new value at the front QDateTime NOW = QDateTime::currentDateTime(); + yDataHistory->append( valueAsDouble(obj, field) * pow(10, scalePower)); + interpolationSum += valueAsDouble(obj, field) * pow(10, scalePower); + if(yDataHistory->size() > interpolationSamples) { + interpolationSum -= yDataHistory->first(); + yDataHistory->pop_front(); + } + double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0; - double valueY = valueAsDouble(obj, field) * pow(10, scalePower); + double valueY = interpolationSum/yDataHistory->size(); xData->append(valueX); yData->append(valueY); diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.h b/ground/openpilotgcs/src/plugins/scope/plotdata.h index 2d61f12c6..0b87c9937 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.h +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.h @@ -72,12 +72,15 @@ public: QString uavSubField; bool haveSubField; int scalePower; //This is the power to which each value must be raised + int interpolationSamples; + double interpolationSum; double yMinimum; double yMaximum; double m_xWindowSize; QwtPlotCurve* curve; QVector* xData; QVector* yData; + QVector* yDataHistory; virtual bool append(UAVObject* obj) = 0; virtual PlotType plotType() = 0; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp index ccf4a8b82..b4b1f24fa 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadget.cpp @@ -61,12 +61,14 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config) QString uavObject = plotCurveConfig->uavObject; QString uavField = plotCurveConfig->uavField; int scale = plotCurveConfig->yScalePower; + int interpolation = plotCurveConfig->yInterpolationSamples; QRgb color = plotCurveConfig->color; widget->addCurvePlot( uavObject, uavField, scale, + interpolation, QPen( QBrush(QColor(color),Qt::SolidPattern), // (qreal)2, (qreal)1, diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp index 63a48e495..6337be38f 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp @@ -65,6 +65,7 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* q color = qSettings->value("color").value(); plotCurveConf->color = color; plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt(); + plotCurveConf->yInterpolationSamples = qSettings->value("yInterpolationSamples").toInt(); plotCurveConf->yMinimum = qSettings->value("yMinimum").toDouble(); plotCurveConf->yMaximum = qSettings->value("yMaximum").toDouble(); @@ -118,6 +119,7 @@ IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone() newPlotCurveConf->uavField = currentPlotCurveConf->uavField; newPlotCurveConf->color = currentPlotCurveConf->color; newPlotCurveConf->yScalePower = currentPlotCurveConf->yScalePower; + newPlotCurveConf->yInterpolationSamples = currentPlotCurveConf->yInterpolationSamples; newPlotCurveConf->yMinimum = currentPlotCurveConf->yMinimum; newPlotCurveConf->yMaximum = currentPlotCurveConf->yMaximum; @@ -157,6 +159,7 @@ void ScopeGadgetConfiguration::saveConfig(QSettings* qSettings) const { qSettings->setValue("uavField", plotCurveConf->uavField); qSettings->setValue("color", plotCurveConf->color); qSettings->setValue("yScalePower", plotCurveConf->yScalePower); + qSettings->setValue("yInterpolationSamples", plotCurveConf->yInterpolationSamples); qSettings->setValue("yMinimum", plotCurveConf->yMinimum); qSettings->setValue("yMaximum", plotCurveConf->yMaximum); diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h index 1aadcaf5b..570ebe1f9 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.h @@ -41,6 +41,7 @@ struct PlotCurveConfiguration QString uavField; int yScalePower; //This is the power to which each value must be raised QRgb color; + int yInterpolationSamples; double yMinimum; double yMaximum; }; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp index e44ccb08f..d0d364b68 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp @@ -101,9 +101,10 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent) QString uavObject = plotData->uavObject; QString uavField = plotData->uavField; int scale = plotData->yScalePower; + int interpolation = plotData->yInterpolationSamples; QVariant varColor = plotData->color; - addPlotCurveConfig(uavObject,uavField,scale,varColor); + addPlotCurveConfig(uavObject,uavField,scale,interpolation,varColor); } if(m_config->plotCurveConfigs().count() > 0) @@ -163,6 +164,10 @@ void ScopeGadgetOptionsPage::setYAxisWidgetFromPlotCurve() int rgb = varColor.toInt(&parseOK); setButtonColor(QColor((QRgb)rgb)); + + int interpolation = listItem->data(Qt::UserRole + 4).toInt(&parseOK); + if(!parseOK) interpolation = 1; + options_page->spnInterpolationSamples->setValue(interpolation); } void ScopeGadgetOptionsPage::setButtonColor(const QColor &color) @@ -235,6 +240,10 @@ void ScopeGadgetOptionsPage::apply() newPlotCurveConfigs->color = QColor(Qt::black).rgb(); else newPlotCurveConfigs->color = (QRgb)rgb; + + newPlotCurveConfigs->yInterpolationSamples = listItem->data(Qt::UserRole + 4).toInt(&parseOK); + if(!parseOK) + newPlotCurveConfigs->yInterpolationSamples = 1; plotCurveConfigs.append(newPlotCurveConfigs); } @@ -261,6 +270,7 @@ void ScopeGadgetOptionsPage::on_btnAddCurve_clicked() if(!parseOK) scale = 0; + int interpolation = options_page->spnInterpolationSamples->value(); QVariant varColor = (int)QColor(options_page->btnColor->text()).rgb(); @@ -270,27 +280,27 @@ void ScopeGadgetOptionsPage::on_btnAddCurve_clicked() options_page->lstCurves->currentItem()->text() == uavObject + "." + uavField) { QListWidgetItem *listWidgetItem = options_page->lstCurves->currentItem(); - setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,varColor); + setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,interpolation,varColor); }else { - addPlotCurveConfig(uavObject,uavField,scale,varColor); + addPlotCurveConfig(uavObject,uavField,scale,interpolation,varColor); options_page->lstCurves->setCurrentRow(options_page->lstCurves->count() - 1); } } -void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor) +void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor) { //Add a new curve config to the list QString listItemDisplayText = uavObject + "." + uavField; options_page->lstCurves->addItem(listItemDisplayText); QListWidgetItem *listWidgetItem = options_page->lstCurves->item(options_page->lstCurves->count() - 1); - setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,varColor); + setCurvePlotProperties(listWidgetItem,uavObject,uavField,scale,interpolation,varColor); } -void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetItem,QString uavObject, QString uavField, int scale, QVariant varColor) +void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetItem,QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor) { bool parseOK = false; @@ -306,6 +316,7 @@ void ScopeGadgetOptionsPage::setCurvePlotProperties(QListWidgetItem *listWidgetI listWidgetItem->setData(Qt::UserRole + 1,QVariant(uavField)); listWidgetItem->setData(Qt::UserRole + 2,QVariant(scale)); listWidgetItem->setData(Qt::UserRole + 3,varColor); + listWidgetItem->setData(Qt::UserRole + 4,QVariant(interpolation)); } /*! diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h index cbbf9201b..39c0b3ea5 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.h @@ -66,8 +66,8 @@ private: Ui::ScopeGadgetOptionsPage *options_page; ScopeGadgetConfiguration *m_config; - void addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor); - void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, QVariant varColor); + void addPlotCurveConfig(QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor); + void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, int interpolation, QVariant varColor); void setYAxisWidgetFromPlotCurve(); void setButtonColor(const QColor &color); diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui index 2aaee1942..147f972f1 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui @@ -159,6 +159,32 @@ + + + + Smooth Interpolation: + + + + + + + samples + + + 1 + + + 1001 + + + 10 + + + 1 + + + diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index dfbd9d614..2270178cd 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -356,7 +356,7 @@ void ScopeGadgetWidget::setupChronoPlot() // scaleWidget->setMinBorderDist(0, fmw); } -void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor, QPen pen) +void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor, int interpolationSamples, QPen pen) { PlotData* plotData; @@ -369,6 +369,7 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField plotData->m_xWindowSize = m_xWindowSize; plotData->scalePower = scaleOrderFactor; + plotData->interpolationSamples = interpolationSamples; //If the y-bounds are supplied, set them if (plotData->yMinimum != plotData->yMaximum) diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h index fd8aaf550..09e79d6b0 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h @@ -110,7 +110,7 @@ public: int refreshInterval(){return m_refreshInterval;} - void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, QPen pen = QPen(Qt::black)); + void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, int interpolationSamples = 1, QPen pen = QPen(Qt::black)); //void removeCurvePlot(QString uavObject, QString uavField); void clearCurvePlots(); int csvLoggingStart(); From dfd18d43b5328827b215277b4592b20d10f32756 Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Sat, 26 Nov 2011 22:06:21 +0100 Subject: [PATCH 11/72] GCS/Scope: CSV export exports non-interpolated data --- ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index 2270178cd..fe322f06b 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -710,7 +710,7 @@ int ScopeGadgetWidget::csvLoggingInsertData() } else { - ss << QString().sprintf("%3.6g",plotData2->yData->last()/pow(10,plotData2->scalePower)); + ss << QString().sprintf("%3.6g",plotData2->yDataHistory->last()/pow(10,plotData2->scalePower)); m_csvLoggingDataValid=1; } } From 5af9a2558c8f61a87d9d3db506ccc6a5eb5b61ce Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Sat, 26 Nov 2011 22:06:46 +0100 Subject: [PATCH 12/72] GCS/Scope: Make smooth interpolation (and internal sum) be long term correct despite limited floating point accuracy, but keep constant overhead --- .../src/plugins/scope/plotdata.cpp | 31 ++++++++++++++++--- .../openpilotgcs/src/plugins/scope/plotdata.h | 2 ++ .../plugins/scope/scopegadgetoptionspage.ui | 4 +-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp index fdcb75a83..e05bf7a1b 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp @@ -55,6 +55,8 @@ PlotData::PlotData(QString p_uavObject, QString p_uavField) scalePower = 0; interpolationSamples = 1; interpolationSum = 0.0f; + correctionSum = 0.0f; + correctionCount = 0; yMinimum = 0; yMaximum = 0; @@ -95,12 +97,23 @@ bool SequencialPlotData::append(UAVObject* obj) if (field) { //Shift data forward and put the new value at the front - yDataHistory->append( valueAsDouble(obj, field) * pow(10, scalePower)); - interpolationSum += valueAsDouble(obj, field) * pow(10, scalePower); + + // calculate interpolated (smoothed) value + double currentValue = valueAsDouble(obj, field) * pow(10, scalePower); + yDataHistory->append( currentValue ); + interpolationSum += currentValue; if(yDataHistory->size() > interpolationSamples) { interpolationSum -= yDataHistory->first(); yDataHistory->pop_front(); } + // make sure to correct the sum every interpolationSamples steps to prevent it + // from running away due to flouting point rounding errors + correctionSum += currentValue; + if (++correctionCount >= interpolationSamples) { + interpolationSum = correctionSum; + correctionSum = 0.0f; + correctionCount = 0; + } yData->append(interpolationSum/yDataHistory->size()); if (yData->size() > m_xWindowSize) { yData->pop_front(); @@ -127,12 +140,22 @@ bool ChronoPlotData::append(UAVObject* obj) //Put the new value at the front QDateTime NOW = QDateTime::currentDateTime(); - yDataHistory->append( valueAsDouble(obj, field) * pow(10, scalePower)); - interpolationSum += valueAsDouble(obj, field) * pow(10, scalePower); + // calculate interpolated (smoothed) value + double currentValue = valueAsDouble(obj, field) * pow(10, scalePower); + yDataHistory->append( currentValue ); + interpolationSum += currentValue; if(yDataHistory->size() > interpolationSamples) { interpolationSum -= yDataHistory->first(); yDataHistory->pop_front(); } + // make sure to correct the sum every interpolationSamples steps to prevent it + // from running away due to flouting point rounding errors + correctionSum += currentValue; + if (++correctionCount >= interpolationSamples) { + interpolationSum = correctionSum; + correctionSum = 0.0f; + correctionCount = 0; + } double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0; double valueY = interpolationSum/yDataHistory->size(); diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.h b/ground/openpilotgcs/src/plugins/scope/plotdata.h index 0b87c9937..a547f2b91 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.h +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.h @@ -74,6 +74,8 @@ public: int scalePower; //This is the power to which each value must be raised int interpolationSamples; double interpolationSum; + double correctionSum; + int correctionCount; double yMinimum; double yMaximum; double m_xWindowSize; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui index 147f972f1..b3d22faa0 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.ui @@ -162,7 +162,7 @@ - Smooth Interpolation: + Display smoothed interpolation: @@ -294,7 +294,7 @@ Update - Log data to csv file + Log data to csv file (not interpolated) From 15c1ca4af117e29326ef85196e0fa83b029c53df Mon Sep 17 00:00:00 2001 From: Corvus Corax Date: Sat, 26 Nov 2011 22:51:20 +0100 Subject: [PATCH 13/72] GVS/Scope: Bugfix: Export all known data points into CSV not just one per screen redraw --- .../src/plugins/scope/scopegadgetwidget.cpp | 78 +++++++++++-------- .../src/plugins/scope/scopegadgetwidget.h | 2 + 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index fe322f06b..12f6974b8 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -447,6 +447,7 @@ void ScopeGadgetWidget::uavObjectReceived(UAVObject* obj) foreach(PlotData* plotData, m_curvesData.values()) { if (plotData->append(obj)) m_csvLoggingDataUpdated=1; } + csvLoggingAddData(); } void ScopeGadgetWidget::replotNewData() @@ -610,6 +611,7 @@ int ScopeGadgetWidget::csvLoggingStart() m_csvLoggingStartTime = NOW; m_csvLoggingHeaderSaved=0; m_csvLoggingDataSaved=0; + m_csvLoggingBuffer.clear(); QDir PathCheck(m_csvLoggingPath); if (!PathCheck.exists()) { @@ -677,13 +679,50 @@ int ScopeGadgetWidget::csvLoggingInsertHeader() return 0; } +int ScopeGadgetWidget::csvLoggingAddData() +{ + if (!m_csvLoggingStarted) return -1; + m_csvLoggingDataValid=0; + QDateTime NOW = QDateTime::currentDateTime(); + QString tempString; + + QTextStream ss( &tempString ); + ss << NOW.toString("yyyy-MM-dd") << ", " << NOW.toString("hh:mm:ss.z") << ", " ; + +#if QT_VERSION >= 0x040700 + ss <<(NOW.toMSecsSinceEpoch() - m_csvLoggingStartTime.toMSecsSinceEpoch())/1000.00; +#else + ss <<(NOW.toTime_t() - m_csvLoggingStartTime.toTime_t()); +#endif + ss << ", " << m_csvLoggingConnected << ", " << m_csvLoggingDataUpdated; + m_csvLoggingDataUpdated=0; + + foreach(PlotData* plotData2, m_curvesData.values()) + { + ss << ", "; + if (plotData2->xData->isEmpty ()) + { + } + else + { + ss << QString().sprintf("%3.6g",plotData2->yDataHistory->last()/pow(10,plotData2->scalePower)); + m_csvLoggingDataValid=1; + } + } + ss << endl; + if (m_csvLoggingDataValid) + { + QTextStream ts( &m_csvLoggingBuffer ); + ts << tempString; + } + + return 0; +} + int ScopeGadgetWidget::csvLoggingInsertData() { if (!m_csvLoggingStarted) return -1; m_csvLoggingDataSaved=1; - m_csvLoggingDataValid=0; - QDateTime NOW = QDateTime::currentDateTime(); - QString tempString; if(m_csvLoggingFile.open(QIODevice::WriteOnly | QIODevice::Append)== FALSE) { @@ -691,38 +730,11 @@ int ScopeGadgetWidget::csvLoggingInsertData() } else { - QTextStream ss( &tempString ); - ss << NOW.toString("yyyy-MM-dd") << ", " << NOW.toString("hh:mm:ss.z") << ", " ; - -#if QT_VERSION >= 0x040700 - ss <<(NOW.toMSecsSinceEpoch() - m_csvLoggingStartTime.toMSecsSinceEpoch())/1000.00; -#else - ss <<(NOW.toTime_t() - m_csvLoggingStartTime.toTime_t()); -#endif - ss << ", " << m_csvLoggingConnected << ", " << m_csvLoggingDataUpdated; - m_csvLoggingDataUpdated=0; - - foreach(PlotData* plotData2, m_curvesData.values()) - { - ss << ", "; - if (plotData2->xData->isEmpty ()) - { - } - else - { - ss << QString().sprintf("%3.6g",plotData2->yDataHistory->last()/pow(10,plotData2->scalePower)); - m_csvLoggingDataValid=1; - } - } - ss << endl; - if (m_csvLoggingDataValid) - { - QTextStream ts( &m_csvLoggingFile ); - ts << tempString; - } + QTextStream ts( &m_csvLoggingFile ); + ts << m_csvLoggingBuffer; m_csvLoggingFile.close(); } - + m_csvLoggingBuffer.clear(); return 0; } diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h index 09e79d6b0..98da3beb6 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h @@ -166,11 +166,13 @@ private: QString m_csvLoggingName; QString m_csvLoggingPath; + QString m_csvLoggingBuffer; QFile m_csvLoggingFile; QMutex mutex; int csvLoggingInsertHeader(); + int csvLoggingAddData(); int csvLoggingInsertData(); void deleteLegend(); From 78e25b1b8c4109d393f51c9dce6568ef9ff136be Mon Sep 17 00:00:00 2001 From: zedamota Date: Sat, 3 Dec 2011 02:36:47 +0000 Subject: [PATCH 14/72] Fixed conditions Added support for negative values Added support to "play once per update" Added "never" rule for value sound Several other bugfixes --- .../src/plugins/notify/NotificationItem.h | 16 +++-- .../src/plugins/notify/notificationitem.cpp | 31 ++++++--- .../src/plugins/notify/notifyplugin.cpp | 42 ++++++++---- .../notify/notifypluginoptionspage.cpp | 64 +++++++++++++------ .../plugins/notify/notifypluginoptionspage.h | 2 +- 5 files changed, 106 insertions(+), 49 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index d4929a1e5..e64609a53 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -49,6 +49,7 @@ class NotificationItem : public QObject public: enum { eDefaultTimeout = 15 }; // in sec + enum {equal,bigger,smaller,inrange}; explicit NotificationItem(QObject *parent = 0); void copyTo(NotificationItem*) const; @@ -57,8 +58,11 @@ public: DECLARE_SOUND(2) DECLARE_SOUND(3) - QString range() const { return _rangeLimit; } - void setRange(QString text) { _rangeLimit = text; } + bool getCurrentUpdatePlayed() const {return _currentUpdatePlayed;} + void setCurrentUpdatePlayed(bool value){_currentUpdatePlayed=value;} + + int getCondition() const { return _condition; } + void setCondition(int value) { _condition = value; } QString getSayOrder() const { return _sayOrder; } void setSayOrder(QString text) { _sayOrder = text; } @@ -100,8 +104,8 @@ public: UAVDataObject* getUAVObject(void); UAVObjectField* getUAVObjectField(void); - void seriaize(QDataStream& stream); - void deseriaize(QDataStream& stream); + void serialize(QDataStream& stream); + void deserialize(QDataStream& stream); /** * Convert notification item fields in single string, @@ -152,6 +156,8 @@ private: private: + bool _currentUpdatePlayed; + QTimer* _timer; //! time from putting notification in queue till moment when notification became out-of-date @@ -175,7 +181,7 @@ private: QString _objectField; //! fire condition for UAV field value (lower, greater, in range) - QString _rangeLimit; + int _condition; //! possible sounds(at least one required to play notification) QString _sound1; diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index ec86aabcd..68674bc90 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -45,7 +45,9 @@ static const QString cStrBefore1st("Before first"); static const QString cStrBefore2nd("Before second"); static const QString cStrAfter2nd("After second"); +static const QString cStrRetryOncePUpdate("Repeat Once per update"); static const QString cStrRetryOnce("Repeat Once"); + static const QString cStrRetryInstantly("Repeat Instantly"); static const QString cStrRetry10sec("Repeat 10 seconds"); static const QString cStrRetry30sec("Repeat 30 seconds"); @@ -58,6 +60,7 @@ QStringList NotificationItem::retryValues; NotificationItem::NotificationItem(QObject *parent) : QObject(parent) + , _currentUpdatePlayed(false) , isNowPlaying(0) , _isPlayed(false) , _timer(NULL) @@ -66,7 +69,7 @@ NotificationItem::NotificationItem(QObject *parent) , _currentLanguage("default") , _dataObject("") , _objectField("") - , _rangeLimit("Equal to") + , _condition(0) , _sound1("") , _sound2("") , _sound3("") @@ -78,12 +81,14 @@ NotificationItem::NotificationItem(QObject *parent) , _mute(false) { NotificationItem::sayOrderValues.clear(); + NotificationItem::sayOrderValues.append(cStrNever); NotificationItem::sayOrderValues.append(cStrBefore1st); NotificationItem::sayOrderValues.append(cStrBefore2nd); NotificationItem::sayOrderValues.append(cStrAfter2nd); NotificationItem::retryValues.clear(); NotificationItem::retryValues.append(cStrRetryOnce); + NotificationItem::retryValues.append(cStrRetryOncePUpdate); NotificationItem::retryValues.append(cStrRetryInstantly); NotificationItem::retryValues.append(cStrRetry10sec); NotificationItem::retryValues.append(cStrRetry30sec); @@ -100,7 +105,7 @@ void NotificationItem::copyTo(NotificationItem* that) const that->_soundCollectionPath = _soundCollectionPath; that->_dataObject = _dataObject; that->_objectField = _objectField; - that->_rangeLimit = _rangeLimit; + that->_condition = _condition; that->_sound1 = _sound1; that->_sound2 = _sound2; that->_sound3 = _sound3; @@ -120,7 +125,7 @@ void NotificationItem::saveState(QSettings* settings) const settings->setValue(QLatin1String("CurrentLanguage"), getCurrentLanguage()); settings->setValue(QLatin1String("ObjectField"), getObjectField()); settings->setValue(QLatin1String("DataObject"), getDataObject()); - settings->setValue(QLatin1String("RangeLimit"), range()); + settings->setValue(QLatin1String("RangeLimit"), getCondition()); settings->setValue(QLatin1String("Value1"), singleValue()); settings->setValue(QLatin1String("Value2"), valueRange2()); settings->setValue(QLatin1String("Sound1"), getSound1()); @@ -139,7 +144,7 @@ void NotificationItem::restoreState(QSettings* settings) setCurrentLanguage(settings->value(QLatin1String("CurrentLanguage"), tr("")).toString()); setDataObject(settings->value(QLatin1String("DataObject"), tr("")).toString()); setObjectField(settings->value(QLatin1String("ObjectField"), tr("")).toString()); - setRange(settings->value(QLatin1String("RangeLimit"), tr("")).toString()); + setCondition(settings->value(QLatin1String("RangeLimit"), tr("")).toInt()); setSound1(settings->value(QLatin1String("Sound1"), tr("")).toString()); setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); @@ -152,13 +157,14 @@ void NotificationItem::restoreState(QSettings* settings) setMute(settings->value(QLatin1String("Mute"), tr("")).toInt()); } -void NotificationItem::seriaize(QDataStream& stream) +void NotificationItem::serialize(QDataStream& stream) { stream << this->_soundCollectionPath; stream << this->_currentLanguage; stream << this->_dataObject; stream << this->_objectField; - stream << this->_rangeLimit; + stream << this->_condition; + qNotifyDebug()<<"getOptionsPageValues seriaize"<<_condition; stream << this->_sound1; stream << this->_sound2; stream << this->_sound3; @@ -170,13 +176,13 @@ void NotificationItem::seriaize(QDataStream& stream) stream << this->_mute; } -void NotificationItem::deseriaize(QDataStream& stream) +void NotificationItem::deserialize(QDataStream& stream) { stream >> this->_soundCollectionPath; stream >> this->_currentLanguage; stream >> this->_dataObject; stream >> this->_objectField; - stream >> this->_rangeLimit; + stream >> this->_condition; stream >> this->_sound1; stream >> this->_sound2; stream >> this->_sound3; @@ -252,7 +258,7 @@ void NotificationItem::disposeExpireTimer() int getValuePosition(QString sayOrder) { - return NotificationItem::sayOrderValues.indexOf(sayOrder); + return NotificationItem::sayOrderValues.indexOf(sayOrder)-1; } QString NotificationItem::checkSoundExists(QString fileName) @@ -275,11 +281,16 @@ QString NotificationItem::checkSoundExists(QString fileName) QStringList valueToSoundList(QString value) { + // replace point chr if exists value = value.replace(',', '.'); QStringList numberParts = value.trimmed().split("."); QStringList digitWavs; - + if(numberParts.at(0).toInt()<0) + { + digitWavs.append("moved"); + numberParts[0]=QString::number(numberParts.at(0).toInt()*-1); + } if ( (numberParts.at(0).size() == 1) || (numberParts.at(0).toInt() < 20) ) { // [1] check, is this number < 20, these numbers played by one wav file digitWavs.append(numberParts.at(0)); diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 5ac05776a..601bd157d 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -246,7 +246,7 @@ void SoundNotifyPlugin::on_arrived_Notification(UAVObject *object) // notification can be accepted again; // 2. Once time notifications, they removed immediately after first playing; // 3. Instant notifications(played one by one without interval); - if (ntf->retryString() != "Repeat Instantly" && + if (ntf->retryString() != "Repeat Instantly" && ntf->retryString() != "Repeat Once per update" && ntf->retryString() != "Repeat Once" && ntf->_isPlayed) continue; @@ -345,6 +345,7 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst NotificationItem* notification = _pendingNotifications.takeFirst(); qNotifyDebug_if(notification) << "play audioFree - " << notification->toString(); playNotification(notification); + qNotifyDebug()<<"end playNotification"; } } else { if (newstate == Phonon::ErrorState) { @@ -356,13 +357,13 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst } } -bool checkRange(QString fieldValue, QString enumValue, QStringList values, char direction) +bool checkRange(QString fieldValue, QString enumValue, QStringList values, int direction) { bool ret = false; switch(direction) { - case 'E': + case NotificationItem::equal: ret = !QString::compare(enumValue, fieldValue, Qt::CaseInsensitive) ? true : false; break; @@ -373,21 +374,21 @@ bool checkRange(QString fieldValue, QString enumValue, QStringList values, char return ret; } -bool checkRange(double fieldValue, double min, double max, char direction) +bool checkRange(double fieldValue, double min, double max, int direction) { bool ret = false; Q_ASSERT(min < max); switch(direction) { - case 'E': + case NotificationItem::equal: ret = (fieldValue == min); break; - case 'G': + case NotificationItem::bigger: ret = (fieldValue > min); break; - case 'L': + case NotificationItem::smaller: ret = (fieldValue < min); break; @@ -406,7 +407,7 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA if (notification->mute()) return; - QString direction = notification->range(); + int direction = notification->getCondition(); QString fieldName = notification->getObjectField(); UAVObjectField* field = object->getField(fieldName); @@ -415,15 +416,25 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA QVariant value = field->getValue(); if(UAVObjectField::ENUM == field->getType()) { + qNotifyDebug()<<"Check range ENUM"<singleValue().toString()<<"|"<getOptions()<<"|"<< + direction<singleValue().toString(), + field->getOptions(), + direction);; condition = checkRange(value.toString(), notification->singleValue().toString(), field->getOptions(), - direction[0].toAscii()); + direction); } else { + qNotifyDebug()<<"Check range VAL"<singleValue().toString()<<"|"<getOptions()<<"|"<< + direction<singleValue().toDouble(), + notification->valueRange2(), + direction); condition = checkRange(value.toDouble(), notification->singleValue().toDouble(), notification->valueRange2(), - direction[0].toAscii()); + direction); } notification->_isPlayed = condition; @@ -431,9 +442,11 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA // we should reset _isPlayed flag and stop repeat timer if (!notification->_isPlayed) { notification->stopTimer(); + notification->setCurrentUpdatePlayed(false); return; } - + if(notification->retryString() == "Repeat Once per update" && notification->getCurrentUpdatePlayed()) + return; volatile QMutexLocker lock(&_mutex); if (!playNotification(notification)) { @@ -473,7 +486,10 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) if (notification->retryString() == "Repeat Once") { _toRemoveNotifications.append(_notificationList.takeAt(_notificationList.indexOf(notification))); - } else { + } + else if(notification->retryString() == "Repeat Once per update") + notification->setCurrentUpdatePlayed(true); + else { if (notification->retryString() != "Repeat Instantly") { QRegExp rxlen("(\\d+)"); QString value; @@ -505,7 +521,9 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) ms->setAutoDelete(true); phonon.mo->enqueue(*ms); } + qNotifyDebug()<<"begin play"; phonon.mo->play(); + qNotifyDebug()<<"end play"; phonon.firstPlay = false; // On Linux, you sometimes have to nudge Phonon to play 1 time before // the state is not "Loading" anymore. return true; diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 49b274e38..5eaf13efa 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -57,7 +57,7 @@ NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) : IOptionsPage(parent) , _objManager(*ExtensionSystem::PluginManager::instance()->getObject()) , _owner(qobject_cast(parent)) - , _dynamicFieldLimit(NULL) + , _dynamicFieldCondition(NULL) , _dynamicFieldWidget(NULL) , _dynamicFieldType(-1) , _sayOrder(NULL) @@ -74,7 +74,7 @@ QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) //main widget QWidget* optionsPageWidget = new QWidget; _dynamicFieldWidget = NULL; - _dynamicFieldLimit = NULL; + _dynamicFieldCondition = NULL; resetFieldType(); //save ref to form, needed for binding dynamic fields in future _form = optionsPageWidget; @@ -224,8 +224,8 @@ void NotifyPluginOptionsPage::addDynamicFieldLayout() labelValueIs->setSizePolicy(labelSizePolicy); _optionsPage->dynamicValueLayout->addWidget(labelValueIs); - _dynamicFieldLimit = new QComboBox(_form); - _optionsPage->dynamicValueLayout->addWidget(_dynamicFieldLimit); + _dynamicFieldCondition = new QComboBox(_form); + _optionsPage->dynamicValueLayout->addWidget(_dynamicFieldCondition); UAVObjectField* field = getObjectFieldFromSelected(); addDynamicField(field); } @@ -245,23 +245,42 @@ void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) return; } - disconnect(_dynamicFieldLimit, SIGNAL(currentIndexChanged(QString)), + disconnect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_changedIndex_rangeValue(QString))); - _dynamicFieldLimit->clear(); + _dynamicFieldCondition->clear(); QStringList rangeValues; + QList rangeCode; if (UAVObjectField::ENUM == objField->getType()) { rangeValues << cStrEqualTo << cStrInRange; - _dynamicFieldLimit->addItems(rangeValues); - _dynamicFieldLimit->setCurrentIndex(rangeValues.indexOf(_selectedNotification->range())); + rangeCode<addItem(value,rangeCode[x]); + if(_selectedNotification->getCondition()==rangeCode[x]) + selected=x; + ++x; + } + qNotifyDebug()<<"setcurrentindex"<setCurrentIndex(selected); } else { rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; - _dynamicFieldLimit->addItems(rangeValues); - connect(_dynamicFieldLimit, SIGNAL(currentIndexChanged(QString)), + rangeCode<addItem(value,rangeCode[x]); + if(_selectedNotification->getCondition()==rangeCode[x]) + selected=x; + ++x; + } + qNotifyDebug()<<"setcurrentindex"<setCurrentIndex(selected); + connect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_changedIndex_rangeValue(QString))); } - addDynamicFieldWidget(objField); } @@ -295,16 +314,16 @@ void NotifyPluginOptionsPage::addDynamicFieldWidget(UAVObjectField* objField) break; default: - Q_ASSERT(_dynamicFieldLimit); - if (_dynamicFieldLimit->currentText() == cStrInRange) { + Q_ASSERT(_dynamicFieldCondition); + if (_dynamicFieldCondition->currentText() == cStrInRange) { _dynamicFieldWidget = new QLineEdit(_form); - (static_cast(_dynamicFieldWidget))->setInputMask("999.99 - 999.99;"); + (static_cast(_dynamicFieldWidget))->setInputMask("#999.99 : #999.99;"); (static_cast(_dynamicFieldWidget))->setText("0000000000"); (static_cast(_dynamicFieldWidget))->setCursorPosition(0); } else { _dynamicFieldWidget = new QDoubleSpinBox(_form); - (dynamic_cast(_dynamicFieldWidget))->setRange(000.00, 999.99); + (dynamic_cast(_dynamicFieldWidget))->setRange(-999.99, 999.99); } break; }; @@ -351,7 +370,8 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio notification->setSound2(_optionsPage->Sound2->currentText()); notification->setSound3(_optionsPage->Sound3->currentText()); notification->setSayOrder(_sayOrder->currentText()); - notification->setRange(_dynamicFieldLimit->currentText()); + notification->setCondition(_dynamicFieldCondition->itemData(_dynamicFieldCondition->currentIndex()).toInt()); + qNotifyDebug()<<"getOptionsPageValues SETRANGE"<<_dynamicFieldCondition->currentIndex()<<_dynamicFieldCondition->itemData(_dynamicFieldCondition->currentIndex()).toInt(); if (QDoubleSpinBox* spinValue = dynamic_cast(_dynamicFieldWidget)) notification->setSingleValue(spinValue->value()); else { @@ -360,7 +380,7 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio else { if (QLineEdit* rangeValue = dynamic_cast(_dynamicFieldWidget)) { QString str = rangeValue->text(); - QStringList range = str.split('-'); + QStringList range = str.split(':'); notification->setSingleValue(range.at(0).toDouble()); notification->setValueRange2(range.at(1).toDouble()); } @@ -435,11 +455,12 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); _optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3())); } - - if (-1 != _dynamicFieldLimit->findText(notification->range())) { - _dynamicFieldLimit->setCurrentIndex(_dynamicFieldLimit->findText(notification->range())); + for(int x=0;x<_dynamicFieldCondition->count();++x) + { + if (_dynamicFieldCondition->itemData(x)==notification->getCondition()) { + _dynamicFieldCondition->setCurrentIndex(x); + } } - if (-1 != _sayOrder->findText(notification->getSayOrder())) { _sayOrder->setCurrentIndex(_sayOrder->findText(notification->getSayOrder())); } @@ -505,6 +526,7 @@ void NotifyPluginOptionsPage::on_changedIndex_soundLanguage(int index) _optionsPage->Sound1->clear(); _optionsPage->Sound2->clear(); _optionsPage->Sound3->clear(); + _optionsPage->Sound1->addItem(""); _optionsPage->Sound1->addItems(listSoundFiles); _optionsPage->Sound2->addItem(""); _optionsPage->Sound2->addItems(listSoundFiles); diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index b270e72a0..317515aaf 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -152,7 +152,7 @@ private: QScopedPointer _optionsPage; //! Widget to convinient selection of condition for field value (equal, lower, greater) - QComboBox* _dynamicFieldLimit; + QComboBox* _dynamicFieldCondition; //! Represents edit widget for dynamic UAVObjectfield, //! can be spinbox - for numerics, combobox - enums, or From b45044b8c35a9bd286dabe9e3425c903b44068de Mon Sep 17 00:00:00 2001 From: zedamota Date: Tue, 6 Dec 2011 09:59:28 +0000 Subject: [PATCH 15/72] Changed conditions base on strings to enums. --- .../src/plugins/notify/NotificationItem.h | 17 ++-- .../src/plugins/notify/notificationitem.cpp | 52 +++++-------- .../src/plugins/notify/notifyplugin.cpp | 26 +++---- .../notify/notifypluginoptionspage.cpp | 78 +++++++------------ .../plugins/notify/notifypluginoptionspage.h | 3 +- .../src/plugins/notify/notifytablemodel.cpp | 4 +- 6 files changed, 74 insertions(+), 106 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h index e64609a53..1475fd64f 100644 --- a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h +++ b/ground/openpilotgcs/src/plugins/notify/NotificationItem.h @@ -49,7 +49,10 @@ class NotificationItem : public QObject public: enum { eDefaultTimeout = 15 }; // in sec - enum {equal,bigger,smaller,inrange}; + enum {never,beforeFirst,beforeSecond,afterSecond}; + enum {repeatOncePerUpdate,repeatOnce,repeatInstantly,repeat10seconds, + repeat30seconds,repeat1minute}; + explicit NotificationItem(QObject *parent = 0); void copyTo(NotificationItem*) const; @@ -64,8 +67,8 @@ public: int getCondition() const { return _condition; } void setCondition(int value) { _condition = value; } - QString getSayOrder() const { return _sayOrder; } - void setSayOrder(QString text) { _sayOrder = text; } + int getSayOrder() const { return _sayOrder; } + void setSayOrder(int text) { _sayOrder = text; } QVariant singleValue() const { return _singleValue; } void setSingleValue(QVariant value) { _singleValue = value; } @@ -88,8 +91,8 @@ public: QStringList getMessageSequence() const { return _messageSequence; } void setMessageSequence(QStringList sequence) { _messageSequence = sequence; } - QString retryString() const { return _repeatString; } - void setRetryString(QString value) { _repeatString = value; } + int retryValue() const { return _repeatValue; } + void setRetryValue(int value) { _repeatValue = value; } int lifetime() const { return _expireTimeout; } void setLifetime(int value) { _expireTimeout = value; } @@ -189,7 +192,7 @@ private: QString _sound3; //! order in what sounds 1-3 will be played - QString _sayOrder; + int _sayOrder; //! one-side range, value(numeric or ENUM type) maybe lower, greater or in range QVariant _singleValue; @@ -199,7 +202,7 @@ private: double _valueRange2; //! how often or what periodicaly notification should be played - QString _repeatString; + int _repeatValue; //! time after event occured till notification became invalid //! and will be removed from list diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 68674bc90..0506840ec 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -40,18 +40,7 @@ #include "notifylogging.h" -static const QString cStrNever("Never"); -static const QString cStrBefore1st("Before first"); -static const QString cStrBefore2nd("Before second"); -static const QString cStrAfter2nd("After second"); -static const QString cStrRetryOncePUpdate("Repeat Once per update"); -static const QString cStrRetryOnce("Repeat Once"); - -static const QString cStrRetryInstantly("Repeat Instantly"); -static const QString cStrRetry10sec("Repeat 10 seconds"); -static const QString cStrRetry30sec("Repeat 30 seconds"); -static const QString cStrRetry1min("Repeat 1 minute"); QStringList NotificationItem::sayOrderValues; @@ -73,26 +62,27 @@ NotificationItem::NotificationItem(QObject *parent) , _sound1("") , _sound2("") , _sound3("") - , _sayOrder(cStrNever) + , _sayOrder(never) , _singleValue(0) , _valueRange2(0) - , _repeatString(cStrRetryInstantly) + , _repeatValue(repeatInstantly) , _expireTimeout(eDefaultTimeout) , _mute(false) { + NotificationItem::sayOrderValues.clear(); - NotificationItem::sayOrderValues.append(cStrNever); - NotificationItem::sayOrderValues.append(cStrBefore1st); - NotificationItem::sayOrderValues.append(cStrBefore2nd); - NotificationItem::sayOrderValues.append(cStrAfter2nd); + NotificationItem::sayOrderValues.insert(never,QString(tr("Never"))); + NotificationItem::sayOrderValues.insert(beforeFirst,QString(tr("Before first"))); + NotificationItem::sayOrderValues.insert(beforeSecond,QString(tr("Before second"))); + NotificationItem::sayOrderValues.insert(afterSecond,QString(tr("After second"))); NotificationItem::retryValues.clear(); - NotificationItem::retryValues.append(cStrRetryOnce); - NotificationItem::retryValues.append(cStrRetryOncePUpdate); - NotificationItem::retryValues.append(cStrRetryInstantly); - NotificationItem::retryValues.append(cStrRetry10sec); - NotificationItem::retryValues.append(cStrRetry30sec); - NotificationItem::retryValues.append(cStrRetry1min); + NotificationItem::retryValues.insert(repeatOnce,QString(tr("Repeat Once"))); + NotificationItem::retryValues.insert(repeatOncePerUpdate,QString(tr("Repeat Once per update"))); + NotificationItem::retryValues.insert(repeatInstantly,QString(tr("Repeat Instantly"))); + NotificationItem::retryValues.insert(repeat10seconds,QString(tr("Repeat 10 seconds"))); + NotificationItem::retryValues.insert(repeat30seconds,QString(tr("Repeat 30 seconds"))); + NotificationItem::retryValues.insert(repeat1minute,QString(tr("Repeat 1 minute"))); } @@ -112,7 +102,7 @@ void NotificationItem::copyTo(NotificationItem* that) const that->_sayOrder = _sayOrder; that->_singleValue = _singleValue; that->_valueRange2 = _valueRange2; - that->_repeatString = _repeatString; + that->_repeatValue = _repeatValue; that->_expireTimeout = _expireTimeout; that->_mute = _mute; @@ -132,7 +122,7 @@ void NotificationItem::saveState(QSettings* settings) const settings->setValue(QLatin1String("Sound2"), getSound2()); settings->setValue(QLatin1String("Sound3"), getSound3()); settings->setValue(QLatin1String("SayOrder"), getSayOrder()); - settings->setValue(QLatin1String("Repeat"), retryString()); + settings->setValue(QLatin1String("Repeat"), retryValue()); settings->setValue(QLatin1String("ExpireTimeout"), lifetime()); settings->setValue(QLatin1String("Mute"), mute()); } @@ -148,11 +138,11 @@ void NotificationItem::restoreState(QSettings* settings) setSound1(settings->value(QLatin1String("Sound1"), tr("")).toString()); setSound2(settings->value(QLatin1String("Sound2"), tr("")).toString()); setSound3(settings->value(QLatin1String("Sound3"), tr("")).toString()); - setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toString()); + setSayOrder(settings->value(QLatin1String("SayOrder"), tr("")).toInt()); QVariant value = settings->value(QLatin1String("Value1"), tr("")); setSingleValue(value); setValueRange2(settings->value(QLatin1String("Value2"), tr("")).toDouble()); - setRetryString(settings->value(QLatin1String("Repeat"), tr("")).toString()); + setRetryValue(settings->value(QLatin1String("Repeat"), tr("")).toInt()); setLifetime(settings->value(QLatin1String("ExpireTimeout"), tr("")).toInt()); setMute(settings->value(QLatin1String("Mute"), tr("")).toInt()); } @@ -171,7 +161,7 @@ void NotificationItem::serialize(QDataStream& stream) stream << this->_sayOrder; stream << this->_singleValue; stream << this->_valueRange2; - stream << this->_repeatString; + stream << this->_repeatValue; stream << this->_expireTimeout; stream << this->_mute; } @@ -189,7 +179,7 @@ void NotificationItem::deserialize(QDataStream& stream) stream >> this->_sayOrder; stream >> this->_singleValue; stream >> this->_valueRange2; - stream >> this->_repeatString; + stream >> this->_repeatValue; stream >> this->_expireTimeout; stream >> this->_mute; } @@ -356,7 +346,7 @@ QString NotificationItem::toString() UAVObjectField* field = getUAVObjectField(); QString value = stringFromValue(singleValue(), field); - int pos = getValuePosition(getSayOrder().trimmed()); + int pos = getSayOrder()-1; QStringList lst; lst.append(getSoundCaption(getSound1())); lst.append(getSoundCaption(getSound2())); @@ -391,7 +381,7 @@ QStringList& NotificationItem::toSoundList() // generate queue of sound files to play _messageSequence.clear(); - int pos = getValuePosition(getSayOrder().trimmed()); + int pos = getSayOrder()-1; QStringList lst; if(!getSound1().isEmpty()) lst.append(getSound1()); diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 601bd157d..9acb4b6f3 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -246,8 +246,8 @@ void SoundNotifyPlugin::on_arrived_Notification(UAVObject *object) // notification can be accepted again; // 2. Once time notifications, they removed immediately after first playing; // 3. Instant notifications(played one by one without interval); - if (ntf->retryString() != "Repeat Instantly" && ntf->retryString() != "Repeat Once per update" && - ntf->retryString() != "Repeat Once" && ntf->_isPlayed) + if (ntf->retryValue() != NotificationItem::repeatInstantly && ntf->retryValue() != NotificationItem::repeatOncePerUpdate && + ntf->retryValue() != NotificationItem::repeatOnce && ntf->_isPlayed) continue; qNotifyDebug() << QString("new notification: | %1 | %2 | val1: %3 | val2: %4") @@ -363,7 +363,7 @@ bool checkRange(QString fieldValue, QString enumValue, QStringList values, int d bool ret = false; switch(direction) { - case NotificationItem::equal: + case NotifyPluginOptionsPage::equal: ret = !QString::compare(enumValue, fieldValue, Qt::CaseInsensitive) ? true : false; break; @@ -377,18 +377,18 @@ bool checkRange(QString fieldValue, QString enumValue, QStringList values, int d bool checkRange(double fieldValue, double min, double max, int direction) { bool ret = false; - Q_ASSERT(min < max); + //Q_ASSERT(min < max); switch(direction) { - case NotificationItem::equal: + case NotifyPluginOptionsPage::equal: ret = (fieldValue == min); break; - case NotificationItem::bigger: + case NotifyPluginOptionsPage::bigger: ret = (fieldValue > min); break; - case NotificationItem::smaller: + case NotifyPluginOptionsPage::smaller: ret = (fieldValue < min); break; @@ -445,7 +445,7 @@ void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UA notification->setCurrentUpdatePlayed(false); return; } - if(notification->retryString() == "Repeat Once per update" && notification->getCurrentUpdatePlayed()) + if(notification->retryValue() == NotificationItem::repeatOncePerUpdate && notification->getCurrentUpdatePlayed()) return; volatile QMutexLocker lock(&_mutex); @@ -484,17 +484,17 @@ bool SoundNotifyPlugin::playNotification(NotificationItem* notification) _nowPlayingNotification = notification; notification->stopExpireTimer(); - if (notification->retryString() == "Repeat Once") { + if (notification->retryValue() == NotificationItem::repeatOnce) { _toRemoveNotifications.append(_notificationList.takeAt(_notificationList.indexOf(notification))); } - else if(notification->retryString() == "Repeat Once per update") + else if(notification->retryValue() == NotificationItem::repeatOncePerUpdate) notification->setCurrentUpdatePlayed(true); else { - if (notification->retryString() != "Repeat Instantly") { + if (notification->retryValue() != NotificationItem::repeatInstantly) { QRegExp rxlen("(\\d+)"); QString value; - int timer_value; - int pos = rxlen.indexIn(notification->retryString()); + int timer_value=0; + int pos = rxlen.indexIn(NotificationItem::retryValues.at(notification->retryValue())); if (pos > -1) { value = rxlen.cap(1); // "189" diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index 5eaf13efa..b7cc977c6 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -47,11 +47,7 @@ #include "notifytablemodel.h" #include "notifylogging.h" -static const char* cStrEqualTo = "Equal to"; -static const char* cStrLargeThan = "Large than"; -static const char* cStrLowerThan = "Lower than"; -static const char* cStrInRange = "In range"; - +QStringList NotifyPluginOptionsPage::conditionValues; NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) : IOptionsPage(parent) @@ -63,7 +59,13 @@ NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) , _sayOrder(NULL) , _form(NULL) , _selectedNotification(NULL) -{} +{ + NotifyPluginOptionsPage::conditionValues.insert(equal,tr("Equal to")); + NotifyPluginOptionsPage::conditionValues.insert(bigger,tr("Large than")); + NotifyPluginOptionsPage::conditionValues.insert(smaller,tr("Lower than")); + NotifyPluginOptionsPage::conditionValues.insert(inrange,tr("In range")); + +} NotifyPluginOptionsPage::~NotifyPluginOptionsPage() {} @@ -246,41 +248,19 @@ void NotifyPluginOptionsPage::addDynamicField(UAVObjectField* objField) } disconnect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_changedIndex_rangeValue(QString))); + this, SLOT(on_changedIndex_rangeValue(QString))); _dynamicFieldCondition->clear(); - QStringList rangeValues; - QList rangeCode; + _dynamicFieldCondition->addItems(NotifyPluginOptionsPage::conditionValues); if (UAVObjectField::ENUM == objField->getType()) { - rangeValues << cStrEqualTo << cStrInRange; - rangeCode<addItem(value,rangeCode[x]); - if(_selectedNotification->getCondition()==rangeCode[x]) - selected=x; - ++x; - } - qNotifyDebug()<<"setcurrentindex"<setCurrentIndex(selected); - - } else { - rangeValues << cStrEqualTo << cStrLargeThan << cStrLowerThan << cStrInRange; - rangeCode<addItem(value,rangeCode[x]); - if(_selectedNotification->getCondition()==rangeCode[x]) - selected=x; - ++x; - } - qNotifyDebug()<<"setcurrentindex"<setCurrentIndex(selected); - connect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)), - this, SLOT(on_changedIndex_rangeValue(QString))); + _dynamicFieldCondition->removeItem(smaller); + _dynamicFieldCondition->removeItem(bigger); } + _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(_selectedNotification->getCondition()))); + + connect(_dynamicFieldCondition, SIGNAL(currentIndexChanged(QString)), + this, SLOT(on_changedIndex_rangeValue(QString))); + addDynamicFieldWidget(objField); } @@ -315,7 +295,7 @@ void NotifyPluginOptionsPage::addDynamicFieldWidget(UAVObjectField* objField) default: Q_ASSERT(_dynamicFieldCondition); - if (_dynamicFieldCondition->currentText() == cStrInRange) { + if (NotifyPluginOptionsPage::conditionValues.indexOf(_dynamicFieldCondition->currentText()) == NotifyPluginOptionsPage::inrange) { _dynamicFieldWidget = new QLineEdit(_form); (static_cast(_dynamicFieldWidget))->setInputMask("#999.99 : #999.99;"); @@ -369,9 +349,8 @@ void NotifyPluginOptionsPage::getOptionsPageValues(NotificationItem* notificatio notification->setSound1(_optionsPage->Sound1->currentText()); notification->setSound2(_optionsPage->Sound2->currentText()); notification->setSound3(_optionsPage->Sound3->currentText()); - notification->setSayOrder(_sayOrder->currentText()); - notification->setCondition(_dynamicFieldCondition->itemData(_dynamicFieldCondition->currentIndex()).toInt()); - qNotifyDebug()<<"getOptionsPageValues SETRANGE"<<_dynamicFieldCondition->currentIndex()<<_dynamicFieldCondition->itemData(_dynamicFieldCondition->currentIndex()).toInt(); + notification->setSayOrder(_sayOrder->currentIndex()); + notification->setCondition(NotifyPluginOptionsPage::conditionValues.indexOf(_dynamicFieldCondition->currentText())); if (QDoubleSpinBox* spinValue = dynamic_cast(_dynamicFieldWidget)) notification->setSingleValue(spinValue->value()); else { @@ -455,15 +434,10 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) _optionsPage->SoundCollectionList->setCurrentIndex(_optionsPage->SoundCollectionList->findText("default")); _optionsPage->Sound3->setCurrentIndex(_optionsPage->Sound3->findText(notification->getSound3())); } - for(int x=0;x<_dynamicFieldCondition->count();++x) - { - if (_dynamicFieldCondition->itemData(x)==notification->getCondition()) { - _dynamicFieldCondition->setCurrentIndex(x); - } - } - if (-1 != _sayOrder->findText(notification->getSayOrder())) { - _sayOrder->setCurrentIndex(_sayOrder->findText(notification->getSayOrder())); - } + + _dynamicFieldCondition->setCurrentIndex(_dynamicFieldCondition->findText(NotifyPluginOptionsPage::conditionValues.at(notification->getCondition()))); + + _sayOrder->setCurrentIndex(notification->getSayOrder()); setDynamicFieldValue(notification); @@ -613,7 +587,7 @@ void NotifyPluginOptionsPage::on_clicked_buttonAddNotification() delete notification; return; } else { - notification->setSayOrder(_sayOrder->currentText()); + notification->setSayOrder(_sayOrder->currentIndex()); } _notifyRulesModel->entryAdded(notification); @@ -638,7 +612,7 @@ void NotifyPluginOptionsPage::on_clicked_buttonModifyNotification() { NotificationItem* notification = new NotificationItem; getOptionsPageValues(notification); - notification->setRetryString(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryString()); + notification->setRetryValue(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->retryValue()); notification->setLifetime(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->lifetime()); notification->setMute(_privListNotifications.at(_notifyRulesSelection->currentIndex().row())->mute()); diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index 317515aaf..fb3c2885d 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -60,7 +60,7 @@ class NotifyPluginOptionsPage : public IOptionsPage Q_OBJECT public: - + enum {equal,bigger,smaller,inrange}; explicit NotifyPluginOptionsPage(QObject *parent = 0); ~NotifyPluginOptionsPage(); QString id() const { return QLatin1String("settings"); } @@ -72,6 +72,7 @@ public: void apply(); void finish(); void restoreFromSettings(); + static QStringList conditionValues; signals: void updateNotifications(QList list); diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index ed4eb0e56..d4913ed97 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -52,7 +52,7 @@ bool NotifyTableModel::setData(const QModelIndex &index, } if (index.isValid() && role == Qt::EditRole) { if (eRepeatValue == index.column()) - _list.at(index.row())->setRetryString(value.toString()); + _list.at(index.row())->setRetryValue(NotificationItem::retryValues.indexOf(value.toString())); else { if (eExpireTimer == index.column()) _list.at(index.row())->setLifetime(value.toInt()); @@ -85,7 +85,7 @@ QVariant NotifyTableModel::data(const QModelIndex &index, int role) const return _list.at(index.row())->toString(); case eRepeatValue: - return _list.at(index.row())->retryString(); + return (NotificationItem::retryValues.at(_list.at(index.row())->retryValue())); case eExpireTimer: return _list.at(index.row())->lifetime(); From f18c980c4ef5b44bb7a44ff6c41aef1600491201 Mon Sep 17 00:00:00 2001 From: zedamota Date: Tue, 6 Dec 2011 13:13:20 +0000 Subject: [PATCH 16/72] Small bug fix. Added minus.wav witch is a copy of magic.was. "minus" file needed. --- .../openpilotgcs/sounds/default/minus.wav | Bin 0 -> 61834 bytes .../src/plugins/notify/notificationitem.cpp | 22 +++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 ground/openpilotgcs/share/openpilotgcs/sounds/default/minus.wav diff --git a/ground/openpilotgcs/share/openpilotgcs/sounds/default/minus.wav b/ground/openpilotgcs/share/openpilotgcs/sounds/default/minus.wav new file mode 100644 index 0000000000000000000000000000000000000000..15bd23b5e977aa266a16650ddea41265a0aa0102 GIT binary patch literal 61834 zcmX6k1z1!~*V~;pw|7~V?pV4(N(2EFL@~ftP%MnsR_yLX><+LM6BS#rP!R+bqy$8| z{^R#Q^UU3eGc%{p%-p+i5uu?=n<$ioz#;v{rOnhyC=?16Qpgz!WmO`TLZe71Q4#Tj zhCq8nbZAUOVB8=A%7Z41)x}I3n?7*jl&Ldy1E)`&G&Xf6B_ephAY14So<4T;%!#wd z>Vl`HrAaL0&Yu8uhfs!@6?~vT51!ugW66N(YmQrS{D_iacLMNJ~+7v=rI|+7#L}+I&b$X-golqb;YcrDf4})3(zN(2mf~ z(2mhg(JsU9DcU(&9_v4GGjU;fiZ$HjFG|^#hB0dkFkWYoUw(mfU%O1%~;IX%UI7i#5l{?%_v|TXFO(X zV_aq&W!!+2&v?oB%6QKxWfU_S;rWyCk?{jk9fQJbWw4oj3_avN290UXR5Hz&uFO!T zJJXk`W7;uom~KoTrZY2!8Ow}jj%SWx&R`}n)0mT)8O-6#xy*UY4b08VIm}bcY~~r} zO6FnaDrOFIEAtZbAoC8hkok~#k6FyT$b7^sfah!GTjnR`7iKfFp4q{yW%5|xnSIO# z_-$eKFgYwe%akQ&kt{RTUna^@v#eOQEDM%1%Z(Myie&X?4Pg1OMzavsI941hgtdq@ zoi&TK1fFwPDXgii;jDG6)vQgd3#@IdYplzx9M&1u0aiBaAe3IRo`px>us$hL( zJ%Cy%lp3I|htOUr?5w`$FWn{BiRn@B=&grI(8;|BYQPFi@k%roSng*&R)r$1+CeTKSR$M_6zn| z_7(P1_G!px+20_2VgF_q!}9~AXY3;OBesB}hyySf1yy3j# zJb>pJ&U;P{=OpJmrkn2 zx11`D6_@1VTsLk%?f`Bi*Nhv_m2y3}YHkuYh&!K~3V9)S40j55I(InN8G1)@H*;rm zS94Euv$*@YC%MZ3q5vT7ap!TLatpb6++yx~Xt~XO$i2h826YY(=e_4@cnw@3kKn0z zC0vr%#^v#vxb0j^o)^!Q7sgBBx$pvc|7uP=36v)AjJ#>QA-o9QdfrUlHeM1hoHrO? zRsrk_-Wc9B-WuLs-WA>nUIA}EZyhg}cbAvRI}W7-yljAY#(T-T46P@57kRgNuX&%K zrGa;g$KsdrwER0f2LC6|hX06%@_+EG`7V47KalUrH}LKFZ1^3@C;1EbTK)tm_2bXx z8~Gsslgb~>cjJ%ePvMW`KjJUqm+)`$FYvGP_wv{APx4pri}{cFm-u)1r};(je9M0c zxt@Onepm3b_|5!>d_+JK2n6l?uY9_IBPiwf^34Qge3d{epbPv3){rL(5(KdVLJ%P! z1u=p)zPrF6m@J4CcnbCl774}*#skzyfm|?K;39|#~UPKXbM0G+NQ7qKlMYf``kS2p&@^hUHu^htDA^a`FgMHfVJ@i7ry{8aQsL=z+8 z22qoU5Wf~#irL~HBBA(`s9p3{)G0#5c4E5NRO~Ib632)qi$_5}Lu@1N6mi8`v6DDT zJVopwUIx#Z;vvxMBu)_b7aPTc#dE|*#J9w3$#HR`_=Px2d|y09dLd&I3UUMlGje-b|zw}~sovm~TsxI`zJ zCt*s&0C!4Ehu;1Yy(Cl;AUPt*l4MH8NTd>biMzyK5+t#c%#m124oEIZj!8B{-*U+< zNh-iiko=JBm8_C{k!+ACrPm~1C7&f9B`+kmB^Lo=7xdnfcuK1!gtP(biP92DgXELM zO!`)0Dn+DR=|br!X^=Ej`dN|&5Mn7QHAuT)#DCIg>0ap)>0{{@=}ze!sLhu8Nry=n zNzW>AU?$_@Y{~gMVru#=tJ~7x)-fM2`mV+#0abhwZTrJL$PL5iv2)MF*fFgZNCF8{3Rshn_K52xf&X#tvZHu~uv-#>XYN z7H@>n9at(h2UB4Su?g5yEF3?D^#F&E!cS6h=<}ncmS@1 z@eP<0uERZWH+(Ms89R*!;rH>y_(b^C;N$RUJO%m;06Q4>#-HJ7_+ET7j>FR(zlhJl zE%E;NIXoVh5w~zQu>+?OXYgZqEIt-b#AWze{4C5=ho8Y`5?}GR_zC z2wwsttcXE`p1_F)oJxGe%kWaX759O*{lrjWH{n9$5E5b_VT76;Q48zbA?6ZmiDF_q zaSvM05RpV7o=OB0$kL>94!SWMKyC;{0=JOHT6ge|d} zP!ScxM1XxrbP;O^59qs3h{*B855VLRQ3~zfh*d-b@s6-0uMsa{{s`hb(M=48b$1et zgplloxisWOn7@vg53_HFS#trV0s0z=UYLzfMv;Ta$1wT>;QbzYy~zqfPSVH_vXGcT zdXtlgZNxC5h`0o}lmmA62{G9XnDr5Z$ut-H5Dn%qguB1NQ->;YP`h)J+| z6yT8y7+b&^9?G1{X6hJ3PxWc z4ncnz(L{Ix212p{=F0_Y??O)=@bCzsChx&ovjN)z;x}-+3@}rZ_laYK5~wO8t`Zjs zJD~dnF%HJ$Le7HOwgcTo0OLts23h>$)F0qa0rZK;JopumbAi@lK`Kmcs+t~0@9C=k=KbWK=UEMj6%L5{z7RN;Q1Z+ zcolkSWEaRk55^rO#*?dH{^NjE5^!rJ(D)6g=!H@r=;i}L47`{PqjEsjcVV_S(B=!A zGbQ9i4B<)4BNBm2ImA!k`!3*I648vWfKm@gI}5Naf*J1vj#|*OWFi6Jv!F!@96bU& z%mSTj!XM$b1PyS_0~ut&x_!h}z@7`z{|dM-gSqb#6G3tl$OnWM=-?%wb2#8|g5ZPR zHG+oOkSbE}KP_4XG+rh&K*c=J0ugxxbonmGejDI@9B`aZcmZZ}fL;x7hDv(C3`H=X zEzDg67##bbzD9r~{s6x-ly`#7y#=ZZi1ENt0r^i? zyZ|DR`~%vy8t7Ajl#77FCqNg50VeO^mr5oAjurT7(9Avmv!F5}lDq_T9fc9ciC%m@ zX!S7|_ivqVu)J4sQQnZ4$`ppY_iH3%v|@{?q&I05KH!`%kKL zpgjs^z7Lk*4Zm{$eh$b`2rESZmEV9f|EMW|-icseDD)K3MVt;Ak??Hxb6D zK(d*j9S;Dy2i9l+`Tf(Ie{)`fwJ*WAfg#cL3)P>9ce*o$uh93M3Au(#t6t=fYDpK(Bhuo038WF|Qd zN=mW-wEhiHln8JX@-X--D}ee9oaqDp{Q(16rL3ww?*fI--vG0tz=403JM4ce`vN69q3vHBcnf1z z!Yco2a{!|T7+(RtNdvrn4|MDTEx!!y|FC!f+S>#c=1EQ@Ey2g+~V1NiC4}<-TBW<8v0G8q(c&kEqdKR!nQ zmm)!0JO9Uv{=juD@fLiD57^>kd@L~%eBWPOL`;Fm+>Bqrl@N^&;V7{ZpN#wAKkz90 zJH7@lg4n+kb_mV59sUub`b~)YL3kdn$1mgap=UQh?7?^7>+nd3_j7Px;smr@!yEAr zcoH51xU=RKP|A|AK#qEhpP%6St;^i>AFIdiMpl32@dJ;$?3FP(~ zEb$&l{|(Ui&&!BG|Ncd3duY`_bR7yj8A~1`&yl;yTVw^vm*tQT$u{yhxfHlsPu?eA z0l)5&VX~EEhOB@*C%Yq?Eju7PD!VCbklm75%LmE2W!bV+`74=G9wwhE-y%#Uu6lhbF$yC-Vm8W z<|(Tq3&`iBAISbbIRPw0OAY~V+6cR!HNc-@%m?;hQv5OYAEw7fU{xrJIbjRY(dYu$ za~7h{5jI+l+=Bh>Sfo(;4LJdO+zp5;Vu`Fr`XM~nMJFJSkvmY!Mp!6;rXWv|d?XNk z22VX|j+$UM(f`mv=q|Jq9gh7%^;jhu2zyEt_rt2NVb~|^JI2I^!M?E-v%{;fNg(-$ zu=lb9uhob%2tJVpe)S4){OJF@c{$j18EDmS(5fErKwiM}3*=6cBWncx?IGP|*0OHW zQnpnVCOaq-%JP8&Gi76-HAm(S+#Uoqo_w>c6nJkg?}E$&-et?JPST(78= zkA{3&v0t%Xk*`>%IH;g1I}{A%K;=5+f65I?KUJa9MDDx~hxdP$fxUTO^|qFOiynL~*y4VTtQUP;`g-I5%M5PI)R z&PzO`Zc6wWNmkV-hM5J)OW%?0GM2&qL(&{VV#$w69?(P$w0 z3B8WSqwi22)`Y%9#c)2jitWSRV(r)ttPMMkeZ(B_W^4rPzprE0Fkjpe?C_tA=Ha{W zRrqz>ieN%)+zII(c%?+Ja$B&M{@_6m!%liLu^09r{~xbsgQuBIt{@MQy`-D02kbx& za=IY94bStki?R?oUv7{um!FnjlshYo3WK6bk)o(n;7YoZt^A<;sMM=`RRdM4Rr6Ie z^;?yR`lx!Y`ilC#TB@0;DbQGI8#Sex1g)jcS{tr~YY*)N%>>Onb*{Qf<)cbd-B6xT zegT;VD>lgw%3Z;Jp2@b!Qo-(~$^6JKXl)J!@-`a~Lv%#a?G=1UdGBI$VPGdOp4Ne)RrOP3&V zNSAam*iSXmhP(jI4@T#qU(l0qrqg2!;FOk(&Onc&=g?&ID>4O@p^wq2Xb80MQ3q@w z*vSVh9nM?puoKu{3;{Xpg%S&Ugqec1wxGYz7Bn5K_6kVM1mJgLdm#V9qTsZKzzJ&| zXw@Rj9(x97!74NcZ1E&o4P$Pg0oZADJ)9OtfaX#0C)jXoD$F_neCQ}{87{@hAC?m&5CKt-5{@% zU@z;H^Odd2$I7*;-5|NCsz}vhl~U~wa%)oCs&$&#>bV-V=8)#N<_^fuQ+rT5N4rTI zt{bCcnaE8D6LXUbx~Dps$sJuSNVG>2sVPwJQJny5{I0N4jFjJ#pOKFNt3E4R4Uw-u zIfHZ{YY7HfLwv$j_+l&yU4fjImP_izw<WauHo*Cu$b15&FT6&mK{!NDucW_LB2r znj}LqU%VOaN5(+T5hqF>h`Yt!aPv_F<%?p9WV)mg?le3>11^B1zes1m34Rcq_7Sue zos4FqdXz+4;oQzfgOFKBtMn^)L^)zao`EHfK}I25GzQ&(I)Md^z-SPy?7;I52T2CN zwLmM{ik^a#J_3F>4eBOvKKI4eV-kpSQiy(Zh=05AaX&I>Z)pz`k^{cJxOD&d7$~N3D{}1P2i^Nnn){Z66(a>q939@k+--&Bo+@9uMi&- z9~N6n!X+LOYpFZjI&GHZO2)&zlnC0ki~Gc-Vzp$Jq*T%a(wQke08!`(+_%g}&w_pJ z!Z_Ff;IK1x3Y~_YLE=FkMq~)c@DJK)-l>?owL^EipwhJPREV*CbqvU3k(@14(bfKh6qM;BzEG5!gN6j{~YfukH_=i zZRCCBo#v(TpTiyb9iA(1J9iV@zt3X3upTmHj8s|Xf01QxH8_ie(TNROJZX2SGiZF;ZCX6NongnC$C<((CA5^}BOfqt*dgSS+u+n; z3p>03EE=l;D~v}{kkOzW(~uOn@p^=>Btm5eapsZ_c$eSjnu?AWygaVlmPDmDyY~A2Vz7H|8l8 zIhG5oP@AK+%k3iU+Z}E>j&Q!>oa`cWdE#=&h3?wq{N6du`IOTsr!`LJoW?t+yT%${ zxl_HOyv5%8J&IhKY@29z+kNThQa__h>l0XZ*yN%%pOvd8+(c-yi5gq#7wde&VEw}0oZ00@<%KdR&dK$7iiIa8@txD zvs&z%M%MqR*;=iuk=1=~$Y?Qkr_i@?eT4!k8{Ln1ODcpZ{H5F@oFsNRJA!kBlg)Dx zOcouK+(JD_LU~EO*kq5Xomqmp(89vvp7|WJE2c|LiqveyWqhcFAy~tH%XDMVnb%lc z-W1_-$$FFy5;{uI@iZ(1>4m#>Triy{;2wpyYz3?|)&-6=k0LrOIgM^3e=28bN0{C* zUu5lJzt_pfb*!<>IMLPLIl(^A`nB19)5j(o^(wPk%X+&s=d*5Y9$N1r?;l>Mr-l1= z*Pl)*hi^7tEpMAK4f9Pun9edEWVzp}(8^%_$J*Q)v-)IJWP8==qT3~JX28~v386*7 z_r2@wXK5dZn7wti^(78(D_@^}t$C;VGVbT{rud$ttXl#{R7_F`F2WMdVqc_9>U+^O zzJuTOp@%}b#pvX)h1rrl_%ww=`_Rze_K!<}S99Q~ej`GwL-2q?j~Ncf3`Rw^bTAKR zL{N(;RrL4l*`feES(&Sys?Ro=rQyq2hz+ll@~2(c^t!gUdRWcNns+r{YNs{)Z5i6Z z?#ZRJF)Vovq8ika+%Bt8^~E%u;TGcr~$8g_|z2yk;}O zw#xdmMT*`>ok)(6>V?a=bJ@q48yTPIYzD$w$-Ir{>_dk~y&6ywF+6Cw zk!HG2$m@Lb{m~oq!kq=f3)Ih@KcQ8e7BhM+pN*Wtl882BhnOi?%i>WjdP+Ki+9tFQ z>Doe_z!6H`5apVeW^p!5N40US=L(r}V+RrmQm*?Yv*_PmIjk*Ett8hYdxa@H3P;5L zz#7Mi<6jmRB75-*5IeTX*zz9ImpBUd?d4c9F@&52=f|Nk9+{11Nc)R@L_5SK5=*p> z=ujv$UAiih4wFEW$(kl*6NzBwq#D@k+?Ni+4$G3%LHc_0CsyBWsJ3ft23oze&>0w} z)AUl)?*}<`PW*Sd=F8BQz;2oS3vMSU&tkwU$^FdvV(5W@xTheon zJ5z3rxocXu>)qTcP3K_lJbaJplFCEjMh=sR*adw(9h{cjrn!H9v^?*g#4<;G)n(>) z>{6T(Tvcvg+y=WXb6f0|XGEN**i11vs8Fm}u#Fu?ze5dV8U-VfmvS?c2=lKNTg{)E zu#|C#lKZ1~QOkw8n5ySL8NZg+Sv8k*xzZ!K-lFl6Nby|JBK~UDSL&m_H9g_o(w@M+ zTuLdGV0>Vfvpadmg|*W6c!_MIVxV$?;*i{2=1&aArXvSpYXWwoA|4=1szJ> zls{Mer#!3JENj7LNC;sK*c6p57(I)a zA%~^ckkMElo=1L>rz`E$63uOGwn>ZL!7$fsCiu@g=0nXV8$Re$Og5W1o1E8&nu#ox zwp#l~j(c5V-MZXAc+|Sf-Sp1e?4DZ27@nBS)RyYzm`cqZtj9Uj8BwnpzV*JVy=EHC zoLanp|v;_=^;Yp#foOt36(){loa8kv2t7?pRdGJ8r5Ui!JtYX@|pCCXui-< z_)~a9+>U%Bij~iFjb_U%tSr3EPMcmgnW$B(kEg`Ny-&?&i+o1E)+|iye9b~n@(aUY5$1Qg&w^2@o z*3&FaZ7l82IO#o21LDG;#|RTQBw*1pf01pEB&_+&$LDu-7z`V;t>lx^$%yZ_0!}i8cGG-u+rq|LO0V-c5X_!rm;)_N4PEkB8pdyq&yc?zXN^ zotD_oupFc#6|Lw3!3W0E-UVGldgzQefjxdq6Kc-3>9$#6`BZm_$l=ZHt!Ua?^`M;n zP4K<&*WAWq?U|I7oRz{Il0#xtw4P_hxYlLelGwQE_ppXZf3n(RdKWTdd5)r45;No} zDki$fXNsNbS}oIbfMKoPN4r3=1`m@g5X|6h;_Vi8NG}m>iY!fs?up3*O|jx5MiHwx z)%2@Gr5zQGYS-$GN=gCQXes8bcQ+lNFQrqjKCMBmw7HaNix5~Q8v`rSp z(YBwdFRWTz`L&kSiZjx%CWEtcj!!{wMp#1_HS|(&T0psXiQ8gFuEh=2UgQ$za$iJ8 zVe9<1+nrvts{$XgO{Xz8wYqCD&}0{RSulV)@b7?{-xVFD`K2j8cGL#{b?NnH)4|)| zXfP5jO5tu~a%ht%)4S7Ja(+&`$Iv^=*e}_?3G^ ze2EyKayPkX)(xkWyB0Ie?aeS#QukerC{?l~dRhOBlYr@7mk`zGz<8iuO)sy%FcjKbb7E zSZ{U2+(P>qo54x#_Gv1v9QduhbXd8ul2>Q^yQDjiIahcdZ6mYf>GCxEqo9V?(DC%| zx&~Ig+iy;DR%abmz?Fy{us5=K%8ziq8m4woPfG23ZIG4nC(H7qx? zvRq?5#^Jb2y2o#y-GSSK?*zvN2Kf#1{^il`w%&P{Q;>6_tA|^T+Y+~*o^F24fxHl9 z$g>dtP)gX$u<>CF`Xz_Xjq-_c9iR!?;P^y2m{w4+@vg@)=UswrU$)QPD?hsZdSNlM zb-2i2a@nrd^^}XLkK`gXCjW1pc1hF z;WRTHSX;SsMR3EZ9%afiA86>%#wwk#$-*K|7ORET$&C_Hq_go{S*+4l6{;j;3$X;r z6aFgp0M-EZZSEv-9==iOs@re+&ERZWuNkErEc*-ZFV+x7nTMiLc~ZSX9jAJv*dYre z;^5xG5u+1?JV5nQyIwCg%Q91&_n0M_*P6S7EW~!FoVtuZyw(PEhP)4_Md54!7% zdQw~qoy(o0UFUkf@g3=}4-5~s4!Iim)i>GmtDDNW(}m*d?$+oN815RMmCPSIcwF`f z`-l+BL$vS3*YXtmE4OxTa@cZk=k+7*SC709*2FSrk#=Ujwok0;wQup;yry2e4zJF_ z?g|QpJx&s=IAP$~=elk1^$8ggAs_H5nvDJ#PWaopjxel8me8ZyihnoM+^$>kr>0BG zu9f~(=9;zGl-XEXjnF?J83G!mx_MGIrQg?9ziK?)zL=`xTosf__9GT>ZZ|`c z#B^ad*Mx;L#?dBF&USlt9_cXaKHVdtbkIedJxnDvliI=%bM^>qB-zqzgoDfz9bsRf zB~lkKsGMU$3>&3xuXK}r#Q4&Y0v^wX`+@&UxKC=pV-%M(gG?$-zL;d_ zuBn#FyNJcuWV8(;|3i3_*dN~VT*7bQ6X4yFHyI@VtURRIsDER)Z02paW0I(0DH3IJ z@|#SnD$zZ+@NlSgd*Qn!Wz|qj60pT{`&l}Xf|oP-DN@VO5yx*DO*lM%Q zpjSI$m4fjc2ljs6cF93mn&~CG4r74VQ15*n43`4yuewr_BDUmRjAwDXr-9EC0{?>U9)78e}63dKu$5v~`p&)i}C)giGSe=*vMbU4L61R{avb zplCX!ZA<^&Z*T02W?zKYiOKqYR$g`|terFq@wdIF@ks6ah6hc}zrFXM}1lYLrX zK+MpX`9X7?Z|eDyFWt0;!?i8HzqMau72&3)ckJhT-txEb8|s>4@l&x-aI7z;t)_W& zOG4)xN(1MhQXEx+I@ELwlB6Et)Heym5%4yvuNxS!j*)t;geI0zh`7XEM?HcL6hPq#%zo53ZCiL z&zI|;8+9M8JS@X8O&l~kMoZhL;ckp*fw;C(|$`N-Cs-606Y)RPHEk8Id zgSdkfO1r&*J7T9KT^g}+6gv9uDAy4i6S0^RfrU<1y89w|x3pnOb#L|KhA~~?-0kEr zL#7?>WNm-JVuZ3)u(9h=^_&Az|>1Cmvcck8C-(3#+Rs>B6q`pl^clC93b*ivAYSycckolux>2!F1_!p~| zH)!n5nymZVZ?cy;I=IAol=vBz*UqtZw z&Gb3vc*#(#EXPlXrgJB=yE$`3M~SammH7wQ(KtDaT}L<%a_qHmt zswghoQSqu)-BHV(t{^OvT`E1KUP8A;4)$ia@~reFZv}fE+rYmkeXn2{d~9kQFBm_& zXSmNc5{{>>ewy;MXOz$6W(rK1raGdQoAep>Sy?$ubb0FW*-sf#6Lu#GizDLS56p~l z8SpvmN{~9}Y(K{V8xwY>+@5?ZqjlE%Iac#1^O$p8G6fm@VI2<7X@NyS#|CVgx9aSQ zrWMoHv~B%!DEm6Qh*|lk@kR6dhE0`~J}Sy@xIR07bD`g-FZCPfEvmKdTL&&4 zeSGq|48zRAndfHsPs^HEFoG2`!_U*cOmhNzDSat9i<&ChP4-%K+YfYFX}8^ALJVhm zH}Cpp`D*{Ych}r6jlEoZqv*k%SDhua>Wj@5UG%oxA9LRveSGaM^ZMB9-wWJ6_|{D6 zSs>g>+G>)_BW;^)BsOpDe4Vejo;OAqKRCBLWZAv7>1VkRPRG@Hf!TNq#3tA=$+goM z?fS&wwMB$lBgv;ZwJrFqtj(#*Y+Bteq@LmrLd|6^sz`N=YM-KB_6FX3^$>FTeART_ zX#GRDmpWz$GELT(n6&9!_45p4Er#3V+S8mVMmM)C<15!QP6>8yR-th36KYjvQ)GY8 zb%2jaztWhGi8;wvM^uf98vS<^Z**`^Ed$?tJGXrD$ zed;$Qz}oGlxgM{h=xXPGc=s^%#`D~(7XmKzT_1Rl`n>ji&WGP`sqYl;;-4z6H=fNu zjh)TPb-#1wwM*rxUI`v$h_-#;Z0=d+P4iywvDn?obFJ4bZ>IMjk0ZwA#u~R{u2kpS z5I>`gwZ>&`p>A-G>Zq{HRd18(8I^4X4UB5EDzaw6AD8YY%wNl_D9CTTOi%&N`wo@+mE z|J-4-evI7_xCPnzMS7C8rG52_m6z6j-gW$Jej(@Q^cJ)=rG8WC@8_?sw;praQ?PZ@ z=7U>$_U^dY^}@3@o0n}dz#H%96crVJJmJaEdn0D2wx^nm@f_1JV#Od{q$uc^_hhdO zKVHA2=tqMalXfKcCb`9~3z%dpL-w?0mQ+2yaV_hD*ZG}!{qqkzv3{p1dG#gYecem) zal(zNQ%Tw8JGXBAu)Xhq<%Qu-A5|~o95i7%J@F{=p6wIksW#4cQrqX-4|G}YcF?06 zq&X$@K!3)-W3jZj>9I)6hDe*>D6cw)@n#-!hG0q`r=_iq^~^c>)I)7{QE%CX5d*(S;Mv*Q@I zi$1G^-iC_8x`IRfFi(3IN81gSIbctHF7f^R2PY;6j%*k)aKz z<<8W-Ga@pb=dPN2V)p$Bd;6`_3~Fw@e=)mmYx9=&J>$<^e{kvT>x#v{8yhv%!Jp zzd)YB8FZortmNx4yTqYp<%m=l$TE17#gtlztS_o;EU$JE!I zCYjx&k9$Akc*w>BD^ISd%<@{hdb4)d*(0}Zl)T^Fw2qgq9&Y{DX0LuP%3*eNlyxPF zvMmdOni40C<4vA7;mF9+Sj&*DKAFC;A#0-}5=)b5+tJ;OFZnP1ic==S5-xl4rUJgs_PgSC2(T79^iY zS{}c2@V(^HRL>^QaKZMNdl*XLh9mVBA@ zb4cydA4KugC(o~zoVs?{e}Cj|+TO53#pk+j=RKEvR@QB$oJV>MD~ullYN7@WnVqB< z${TEm7KM%W-|JECI>K{#a7j$v@b%-Lr*%xL&v=ur8EX>9@buN#v&x&gex#Lol=YP7 zRL-i7sjm4^QrhxS@N(nb{g-y0+LBG(X177KVZ>(Eu2V;Bu3mWxA41h%ZQa~eM48EH zkk}H_<#e^y^o@C?RgWFbwb#p{pD}jqP|nDR)a~PGV7awpsiOpmUi}NaGi~o{2Vhe~ zh>#}ol0@R;6urvja(lc_aWwLiY^kZrmJ+jMdFk4ycZlchHr z0$StiOTNx|KIPi()2j{_?}^#|X4|+O4ZD}*M4VyY*!ZTg`d4?Wz*;lH=AQ9t06*M6 z(m9Gb;7PcB;AoF`&c|I=_*jR@246{;HDyf(edhTY&!_f`e>;@hZ=2l&Vj6?m{_4-3 zhK0Wm)GKNi{u)v-z4*+_lE;cW!!Md24Lh)IPx$VGdtwiKJt8_^b+h!L{qsF`<~!BtRZ>x$ek=3i~Nnj{|;zftf)g0&n>b57-n?=vU#>=7)#+#>`DxHTLo3A!)+& zPwBSlVFxQ=dN29BT#g7k4tDNee;WkY$MU;AO$gHpm*LV8Q z7)@}Bl>%>b&h)tc;8h+~tVh(XS`k&stuRT-W5!ylZxM?=AFN#-&$z zC$Erq{GKl>dE0oJd0W$D(_w%QI zul=>5GNvly_p*)TY^O%=oUq{7k3-8x4;f!O zd2ITYbo(ivCgo09m8MF&HKjByZt9w8su}88!)865k)3`p+GS4L!&+E9FbNl0i2?aKHBCk)$lU+D> z?)X`|^Tn61Kk#`wxt!LR+$-nrMftM3@a1WzoT5Ih*Vvu%koDUV<1mDp*qpE=Vg2Cf z_>Tj#Vx8mG$7RNw#ea?sj&YB`gLZkmw!dsBP&JVhJRNtF%~uJvx3&9Kn~71Pw~U1D z%D>FUz4gz2E1JJ{45cyoi!h-&$aJXLE<=jGPBRd`2wb5d^ksG@1MbEgODZ4rD)mT8 zL2`ZqcgWO)RY~hcdW|2P_A;Yl*0ed~+~0G$=e)=~m@y!Q8~)BZM&#OsHfGmtY`H)! zV7qf$nep9Q{=`&&E?M<5`{952_s_pQy6xbUee8Wf*@q7wI6CHZR^GN7@9&vBzgmn} zo%_47o20*GJ2T5DzLcWA?|lPUr?3iBQ2PX0)w-v(ucMptf;U6vV0Oxp<+NJuU37%q4Br(Q8*LZ2BL2VFtf(&`ZhlWZj=3yy^sv9<;N$Yf$TwEO`SyjyeT@#M zi4r*H>0#7u)L@1?@1RsJ>#y0X&(LSUTL8Z72et<{%8FI}4HxZa8B2Wmk+uWR#9d7I zn>cH*Sz_aG-tf7@qDF5?bxSp$@NtSFee<-=>5r#vpRhjZSwB15X560rmD))=!Fs}f zEpe0ja43}GZoDFI$ zSX{ccYE7fKy`-z7Yh}AwL zz>8r+qaMUAOjwhQr{+%_o<42b{EVFR7b&?>3S+eT0PhrYG4HO#LasNRZBb@8r1MkR z5nd86PH#tIP0rVvmx1>m++J``T5zT?|J8>#VJ}NwUVDA+by3l=FS!*5D*ycY`D^LV zqvf~C0!ufQl~w$zI{91NQBU2+ua{BGgm!ut+`Z2j?+|L)r7e-A!T0jxWG7Txv{~?V z##Wt|Izj#sz6$Y>k0S`|f|x7davAKCjLo#b-lOfan-A3e{gqT*T_5qMyuCjKh5z&i zFw!V^*TEKx=Hrbw8n!j@{?6|B*&D!Y=eM9+WWN-slBu+oHR6G|HSt>ZNX5`6o3Si! zS$(vMwO(WGU~6Sx>GaL@oO_hlM4wKd{yti-F83oY2@Vr&?pgF29-GcFGq-$X^TMIe z+0XdYINUhf<-CKVjoe~@*<{mX!&A%qc7L6gyD5A|2Tlz+*Y9M%n9v*H?P0lLfstm> z3t}$~zM7Pk{B7jTQF$X($ze&(@z=w%{j%Nc>>Laiw0)X$+QYhbT`_!-xFjXb#FennczW|O649(hrQE7mFB zst=eT1}pP0OUx?8y1?4ZdZ3lUa;y0~!&H5{$vVB%aL}UCT4CSfl;t|!Smx^QvfJsm z{UqCKR@*J&EpAy&w(+$8ePC&?Oof4mccFS|7JD+ZXDfU z-IUe*vn8hOMdzZP*dK2Pxl++Td4aEd4SR=BMj%Ej^) zajO($^V;@X+sIMkGyZQ73eix+AC|U>V?_%z*W1K5@^1TfXNueC&T+;#Hd-&p`>pG2 za~wOJBV6&$9Q!@nbL&*=SzDg{FULSy3>uYe|f40Ou=q#NAFbIVtd3wzCOXyfOBMHphbXX*{z z^(8~JezblU{04TwCxFn8(GSp%Fmy0%GT4m04a*Jn^}DsN)eBTrl)*}e>V~>N+h4CY zMjA5>eL=>zHA==b!(~H?;i+z?_N(S^_$}mVU3$qd+E`-fXY6ALh34Rbp}oP!XfSRw zr0E0obF~VcQddQHRp-z@(vO8-z-%}ML>lTrTig;_@7u;cP)s{NQ9;;wWvYoW?_D|>&!|W^UlkKtgiS~)M zg|-dW_159m)=WBCy}A*H>y|ad+-5K!{1}A%C35?v_TL0 zLs?$E4rfUVG^F;P<}sWuj-h38^ji#R2EFMVNR~qL9AXvufEopIEflm_IP;Q`SO(nF zM5xuriG4-01ckb|UHl-d6c3C2r0LQ~`Jg<-+QK&9cH73;Ses=1CO5zs*dcU+s`onI zRLB-~i2sQzFg6;Bjlk_Z=6mq|d?M8Fdq63?5DemH!B?#OKlS^2F-2M~ZGvtmTz)0L zv39dD_TBc+_TTn6$3VwC`x?93-ooD1Hq3U*S_fM9%hDtK+#}*K(MRehU6Kx<-OtM= zc`-Pk<${|pX4ULeW+pht%XA$^4K+T+-D8Ka7eHX`pdNyKI!0C`pO(!Y;Gb5&+Gssd zpI8sw@jCMcI3}#eQ(12wXDI?la0fI=InyD-N4-hU>g+nTZkFyk#?uL%Q?~{#Axdqr zdZOB_+ON!2^i^C|Tv04h{#2GKL(~^kUbPYKD|&S~^-$GjRXNpp)l`)LKb1G?E>L}U z)T;Csbxz}6;~`U#NoAplSm@+$gBQ}^eH5CVP(O##OPN7Xv-#pl9z#p~D;($7b8Fcw zM$L?7&M+c7m<L3t{yNu0IL#js7$Hm8CD_Dhv7hJ<&fquSQTPm==QsaB zcq~eCv0N9m{$1+^tJZ3;zLF*DS^2$OQ@$(@1BI|eJ}l|w_mUv{$nB*E;=ke&@uQf9 zXPzrQ087$W{3!ebzJwJv3#Wy4;CuRu?LlSj6ml?Xb9e@GRwqFrSU{evkZQ?Gtgoy? zt(o#qX|&WHfA>0nioeM<;}uY=4+5*u41C0H&_N7e!0Ol%5NOM(C~_VY{+aN9NVde{ zX1Um0VD1jDik7A{V{KzYP$cR4qx$~vFIj~)X{zghHfe&@qA~nau4@b6-IA!iq0wl6 zY1e2yT23=m-CUEX*{2THWT?+-nrH`U^R?S`voJTwhDrvL!4JB!4)|%&`VaaFhBihY zV@p$AQ&+RjGS^(kTpc5kGxs!YFby?5G!8MnH7RjNzM6PQx~R$YSh@z7`WkDw;iCx5zqD49+l}ZM=yu4XX zvQC$i<%ZHsFjF6dRd}L1#6RLAsjak3iU4^vPE14VnuP?cP%3^9+H@eekNy~+M=+Y6 zfYgc+#tAEgDDkm)P|A_+OBJNYVuVPE%Y;Grb3(i5l4u8nO+& z;jQwYaTrLIMeuNWYfJ{8qBeK83;;8KQrIr+Pj)3& zhnox9!^`EfJXorE+-t59U&vPyW(#YCEy5nq6km9MVJ#>cnvVm+a}77Kqw$2dVeWY( zTEt2iRThk{GIioy! zc4xkG7QQ$4oasyrVXE^hg?#QSTb>=y?&tcW0_no5(Po4BWx^yrmJ4IoF$Y+hr@0x7 zfEB3^XwDS65mlee2ZHMlRnn0jy$EkQ(DHEM~qTXsOnCo{~Avyws#J z_XK-2&vFZt&mGGg(2{YeI(nGbV-?8+8`Q>BXgXwE3|gxVJY|aE>oU}u$F_fILFug+B!LgmF)we76!nZ2sr*IG*|5GsLw8)l7g zJ#uw)EVlYe9npfbgw=uxtNa^`yhzExk77nrHq_m(837ck60Z=9`6drN`D~eRt6BeP-})!PpO{h|5iE$t|taKCDfzK$k(HEFX}oqjUp&N$^_P21W8$g z>&5P2a_L0S^^=&k%r~YyT0mx|F!eBUvcQqm2ZJ>VjtZ6FE<#fM$PUyjIKY_5lVHyp z0((lKuAwF}!bPGjT1v-k1?^nsQSy;Y2Lb9pP0cVgS{j+(G8x_x7Mp`+%3tp)P_$fG(8M#@O^3q-r-U_jTzuq>VZoS z2a&!JO3(!M02{|8aTEw#C7-}e!iqJYu`yG?$@Kv_+#0l8nJdREDw*+eYdBx}7FaJQ zHG)!+yFuSxBhNA2c)PHRzs;$*uTTZg6&eXDUdeanR|%2gN^!FoApH>usUK#u0iszv zDa_$%td4^*X6Ip6oQV2mC}`GXaM~fL-Y>8>*{N(z)CKpUDe48Mge7?2_2Hx;g9j_~ zSg6CS2RB}g{f})575{B`DvZQekHMR!1Dq9FvESG)Ao^nPj@EFKxvJcBeBVRnD~SH@ za3&~*hrwI;)1-mj^rx0F_pe90aCy4>;gSmYra?tK;88;2E?F-a&Ry zzcb;y6GkbicjyHVz=roh-6+A!U@5hgeh1Hs2h=h!@nwDvQ{lYu|2_kU;r}s>8b?iq zeyt8xoY82fN+4FB5K8hWF^Mhm{^Ie<;oi)c{oX1&S zf}*@@sSLjEtNE1qjd?d_>06e6;AljGX6*+uzl1)ISA7F|{tlkPRFK~9uxDKepNM^M z!ziO4-_aZKC&Sosc(&b{3QSM9s!YRpI8L>p6x93w^`dKJeaZ@|=q*0QBCz5=K(rR2 z*Orm_6WLAdYIZT#1Qh{;8MvuXNpK0VLM~q&b^3hF#%`=lgm@i)KA3;bHRl$BfNcp@ zzlf!|Vs;{^`}=rzOW}s$!z@8>G|>G(`ZWM&KLfv}QytJIc8shtFM^{~TTs%Y;B1ln zKNpLK@Ea-f3K39EHDg<0{=JJ1scsB>?H05dj{O{XD$d8>={&B-MH7_ z+ut&o%y7_KwJ;vf|IfQ575)W}z-?Qpboeq|B0E!|@Iu&%J&r#dZLIJeSj0Xer<$5r z4l|!QEB(ciMI9AKSZzWYoEwJW)oO9SIDtFK4d%|VcQB)bGvDY`CWD;_Li;0Ei(kn% z5t{IKQO}03UXb@+naA*aIg0+W3@W)%m|;vY*>x#(Z@i-Z2aR=Nj`1E>72}d+=sig7FplKVK0Z zuhA0Z`71ovp{$mD19y!3jE-eN)HKH__C7X&djajnTI}W%K<*D^&ttAA&kTc`PA&L7 z-2;ES1in%t^$auI9PESB;h``Z?Th)1?1x#qj0T;HYI-in(q-5q&xB)E09xN4UOK*@ zsgJ-RsmyPv%m?W|@bUsP4HeFJ<{tYu`;OhkN+7K7Vh>a{f0w|8Bmll69pJCiw#+?= zc?YkNO7vSQ8asz0WFz<|Ji-hcLHB_ZR&V^uCTD`v-wKwyA{gN^kBl2s5*>xtJ__%e zu~>?u=uP+xZ{Rc10#|@txfYy-&@;|r4$Gv|;kz|}T8x={GP4=| zs3p|KdoYH+vK!eJc+IoS1B{*WsEU@d@z5j}F+C7)dA1BJ$af)!}}>uU8QPa4Xg#ywg+1LKBHkb zG6&F(ub6V!pM~OAId(E$`xRE=nrtt$|4)X+IOfo=gV|otqKmYJUV<5}7c~~2GY#W( zG3JgR=r0Di8R#&Fx4}DGg1NglX5TVDuNm+MDRYh5f|*8wV~8F;A$RGAsKf>I@_5vH zw{S{Slj{LLiuZJZ$xk)1R9#%l@2#|yRJ z&LUe5zt1vD2X&Dh$O*Rwb@t9 z5%i7~lRlR6DL6pZTa)h3TIyRQO#BfYgaPlSHP6v4&^*)+wnS2|nHbTF-Bt@*Cx_m8kY1qaAaN z;U}>i*PHGP_rdgMO}|ZF-7L$rm(c+6BA|^cUMDSaBxL?ie6+fxsD~1|D%_?)X_9woSk171~`eiLHpmpfoct#~<;`B%+mbidW|~`g6|I&9*Y6 zP1qO5J9sM`6Ngxruov~)N-zCx=QD}z7kj5#w@NAQRsMrBH5p^G&iSn6;-bA3Vk-Yg zIU1tY{+%o2+$}iotI$58g`Q7ur_)r~W+sy;gQ>zd`n%)tWaMSmTXH=XW;4 z{kcchcmJhgyYQpY&7wz#&Jv%&=W(3ArZ4&DsN#gBJAY3ycuq!rj@lQrl$uiXJKgx+ zn$=LZEw-rH_%`;Mho$A8{V#sJe*M=}kGrAVaeZTRNI&J3AEVNie|qct!g?o?ic$w( z!%alf;N#H^Lxat(+|3`D4`S{wONF?+dL_-y)~}qL$FI+6d+XXspIc9VO^&d15(aka z8C9jaHsnR))4JpBQyT^DNE+DgSQ9Y3Z<_sS)0Ld_4PM4-0;;C=;s=Ix*cf&;x8|L7 zSO0q+lh@Pq!2KZhe#-OeaW(cPCdp@tt3Q5z{@ue&pV;VzEn0P)T5qd!Zi)CIvUcO(=VeUqubv!G1hq1fzRY08ImjJhAxV3@nQs~~q z5wTj^I&*=aoP8zljCq~y8UG)3li*FC3BlURvomCMOP8b-UD!Os5_Q-RYwZeuM%16i- z6c@9brblJ1Gfj8ziJV;FM2*TZO^B&JZ?kWtAN?YiHsiGkeH#pG`mFjWck1sS5BuI) z^~N5!GiFfJ_08!@yKOD~t7Lxo+&jCux}GN?@mSK*_|)i;)(47Rzg~R{`MSMij+h<& zCAm(yglN5#tnCmm-S>ELQ1PdLHgw~dwsq_^_2G{U`?L1G`S-)_lIc{J;GiUP@{zDh zu3>U@B1fO5zvJKN*S7ri>b>kVPfXI=3JpUhX&iYcGs(YBcls-^mg zKE|?wDn<2^D*A<`#2#_qHM}mK_Iu7B$v9e?CMgVBp8=%>noPQ!?VG!?YZceexYECA z-ogA*;}+Mokkdgo?Nx-s(r0h8=<(i`=Ay!PKVRpJ_vfu=6EYI2I@M;Iak11f_I8DN zkesv#Dj`l%R;%oY*SC zNnB3A>s&JTS>P>er{wE3o+jDE+J22Q!`_pb9rYu_>Q>v-WP9Bk!E*wXnf*Q+vL~x- z?%d?X^&T+NCB(e3EcpVgjLep|!;S8&(blbiLfwjk&l z`M6~2OUn(~f;v=~SXPU%rpp|$aLdi|TB zw`YFYY`7aSrP}+t=Bl?N3b^aq^Qw8;KwZ-SYyOt}M9ms|-`H0bv=x#gX>ODmrL~8$Uws}ehe6}zq!Zyf$(G~ zHXW8o=YF|>$ki@WPVg)C>t^p-9O+9|1NfUl`oanMf709 zd`q%a-=lv%%lT6BfNB-rsR7yIMBU7=dn#pS#;aM+|NRzixD>)9E0W@ZS zwJX4{bh0{D7#wl5oF-Cbas3|i@$&mBxsT|z752CJ(z!u{qtdGHA~#Nx$D)PgV`G4jaS$B7U3ZE1)tsu zFVent^8apGfIWY@&>=Lwl7Hh}&30F;%f{slf1Up#I%B+_$X>IXr8-QmpbyVT9FyER zroMByxs~#9X;}X2!g(4nVnN@6mdIA>9&Tlx>3Gv?HpIHpG0$<5OEp~453=}}6x!MP zFuJzwySusLZzk088xCUWdIEO@g{A=UgEQE6ky>Pqg-29|WjvRIbM^(yVbjRKfYOfv zzw}l3-BFQMo>uM{(^ty=<9hq^;nsKWN<)Iy)U&s3-#{0UuAiPiH?wKx@n35K4#>|F znM$cKE1ZSw75!=djKXoh%ayjWOb$z}_Nms>*tPVTl9=z6zJwO^qb`OuN_HhDMdS)p z;HvL~J}oY2OP`M));z!KwU+AO$C(RHIM(&reHxO#S=v6`<8bS(o<+n#XLkJv~kbZxJy9r>l`@stH+T1 zYj%r7hSUvT%&aTyn)yEOvu9DZHhDE#Dx5v#8zk@XK-yZq~~4#SoKGQensr_ z`Wx!Mi_0U%|N8giw2Xd#5_vxUVl}?P80UXV*RM}`wbX~C$=(C5Ce(06Bjp!!j`-QT zKjK>O7yhm>O?ldHx+;&m@44-1FRe5CD|EiA0u`2CwmadW@%GqDp;N7KmJZ}8ACn$)Cg?cH`T6EgEQ&HT zb_76W6%w%}%lYS{C=h(} zbboVWokP4;gX0{7S&D2;M^jxaKbSmwN9Q@Vv-YlUJD<18(NsHk^~j7UYv?39&vY=9 zS7svN=0jkVVJ&NSnZkO7?+==9{UYq(N=^2_{-xi1`>2wbwcdph2i^0yu@s0$i`IP8 z;zMV$3D&ia`eG%6J+Nxv9?c2jz4+alXmv5p7(emU+Wb?kJU z)4Zm~lg~|Obj!43j9*xz=TVG0p?&yU@we_&(e+F@YlXtKoO{`o|5PRXLl;%3 zRclU_%rJ^P;N$sK`qP>B+0!j`uE6t8Lv&HGHk&?-#jNBujD%HUQ?bfSKr+h0QwRA)!C;K4z8j^Wnj!rw%9^{)V%YB|x&5f^nmsZM;T$4R~qtXbTx$XEH9 zZx)$do~>9l=|}h^>mF@L!Ngxvd_I%CL;I%GtX`$^{kUbWWmG5lNQ4@~*(vT%(a#g5 zxD-z_^P|$dqLqrN^iHQC>|8`Z$Vj=S`DmcYXR>b_mBCn-=`GK3gxK0r4U|mrio7eo zi9cbgYeYF~scWu7WDhFF=T-PwA?r~d=wsD!s=0NrgO~p%jLQC{n@bxg_nFXF_5XwWv3=+IVT^qa`&^pCDMCAv{`8Sa(%ybbUJ3@**3AQav3uASi*EEzn=o%P$H*9*)2I)A}k$B65 zOAgnE;KSi}!rOSZi8n3bh7j{;At9u3;>1c0I8aRw-{#cXDme#xkA>uWGrVI$-i0s3 z_x5Jo8XvzCehW2Obct(r?A1!oD%Xks&oz+T5%3_t(og%33BP*zKG$qEPBafQ)iZuK zWr3FVn3t;d`_3=gm3QTrP_zkIQ-Ob?|Mc{2q*$W~HO;|I& zouKpX3_CB|m~ECr<}@;aTVkyTCQKdN#5=$}+y0;Y7;1s%!X;r3znj~~-hUzp63caecZl6hk)hWZmL6y;oFyW-{ z8ZkgGD<$8$KAwPa+FxY0u-W=mc8aeV8}%>I#q!3K4fRo~A;TO+tz&O<|L`?=Kit7z z5pCirUc=^4D~Sn&k-EsF^OvPo*4x%GQVll2(plR;X;x@8lT8`iTKnmsV$WR1DSiN< z)_qq-D*_cglsT%)+ABtXasz7?AL8b=i1nc-Sd7MaZEw|7`HkI^&GktS7zcA`4Yj!$t%MXl|zU{wSBQOwxiM>u0A!%yb=DAg5@xoN*AyNxDOOq z}!KuSf+A1EA)V8ONFn6t> zn%*9sr_S-V!}3O)DDH+rX}qI@)9i|H^PUus-otyupw-^oki%iE!ykl=4V@KoJj5sL zbwtJ3l}Xc67NmSlvPXY%EHSPtT=dQK`PTQW(nZYqh|(%A>o2TVv%)3!FKtHd{`V`N zetYbC9sR}e%jo-2SBV_T?i6N<@EJ3#@{cT-l{wZKJi~7AA__K2zOPS*vyJmB#lj;m$)UiRzzq}Eo(FG89COHWT{B4;05~-Ps6aY5%G}? z!zKm&<@hMnr!E+8XnUxKs+($4jAu;4ppn^R>S??L_tp_m4V*U}G)C!zHT?t6_#N_T z#X|LyH@98PCImG{yK>*Fy7N;SAX5SJl5uV2LVC-;B7+G!asv zj_5CNd^enOpZMQgu}vSVYoa}BxMq3CLL1x~z9VN2sSm$z4bUb$O^ zg2aiDrLG0s594I@e~P}!JncGw`nOW*^=+*newa zAC&@rpr!gThGlw(zMlbVDt)0gNc~F@fEM24+s?P8Zx6pg0p(TOb!#pAnQ`!0+b+iP zsnh|}IPFw;jZRVht1X2KPYGL3JZR0ck8xIUZFYJcakjDIUalAIBBO~pWEyRO_1bFt z5$9vqIoD@rLq|{B8z=z%gjXDgTg2YDN%{f(#VF=BvxVsfKXwz{!n{fwt(fF@#`leX zW?*0S1^pZNNmtR=Ro?OQ@i|#suCPVn^I{*LyS{;ejRQwPi(C_Wu>-0lN~gl4V35n# zOVwY$*L;wkz?-CWVK;Y#o=UwSGpPp*A*4yw?5VEPK|_P~c>fA+9CF(G%@ghpcQpLZzDE;QU zL%Xm53YHaO7`(~O+CJNo>`wb_yVZH!*}{_;ygBq-gnx`RZd7cqaFwGzIa}GWn9u!_ zMdXe08DZRKoe|b2c0^pu$V;xn6zBgc`}(KYH+^2LedSHx_TyzyceRZ^FYUKYlP9q! z^f!HDe~AER`c#r07@%K8oMoHvRpF*Sp5Mm~L(ah;Iu$B|$5>Y?e1Ztm zn#&*~GsVzGwIbjp`pY|2d;J8n?KfBN2Ke>Nequ#Hf z#5QXL`rvISUTd8}dWwg&V$?&VaskQ637zqM5>Rf>M2j14br8z<|JBF?+aZVY_%p>IL27Y1=+q7yD4#cXX;^&Z(B_G zd@TGo=0JgWfX%a9hud8nW#_<80apUkl-xa%8% zSjGdT_x#=|=IS`}Z{i_kftu(foZ*Kd>8qD%H~c4e;%0gaRZ8DxzN;x~6$r zc_jB|#}`|9*;n$1Yj-`_WzThndTM&-d24uk!TYPDbG0MSegn$!s*W|N4sKaD%kA*J z0nnB`kaycYJNmkoxdu3I+BMc#aTfHp4&kVH5kKdNbFsU5@YJwZky$aV68@A^SH47yWIlIZ{?E-uZooU~P<~0d0||){BRt9061t(Gruu=3(i%)} zm`2WT5vLN@RQz3eU4{NJGhGd+Qe|vO>hCeX7Zerx{i|(2wS^DVSI^X-2d-f2J7$P! zxOx@tE^^A>lZ`4Vu1BZoo|nxIi@_Gl*?Yg@|rkVVLv z@L{{-X8t{S-&COf>Oba>s(4S)qd!`|%Zj7=CWK5^CSRI|8)Nm=G-DKh1tj?I2zV0M zK(S5nR++DzY=RyQdK;FD$KB#1>Ka_h^rk=1-8D0>A#}`R;jMLr{gmUAy{r9&ZLjT? z?UnVAd;!kwbA;9W3ocfuBR#N=cARh;+$HXTt{ILLa71$jhF{IqVW&W$ae!G5cll@} zEL@b=*rve!-6T!mlbBWHzZf4;WI1?aUKNutV>P$6vM!Y$NbjLBJz%|V?}Rn-zI%#i zuQw`WQ~22E$q6MXTDW6%t+76SndI?r`R(7=pWdjylL6;!Un~6AMMr5z^`(gZ- zciaDV%(XX^GT4t~O|u9`@;jy>mLudbXa$bImz`%xL2Db~ejoZds&`yg?5F7U;mw0b zJF}(l%uP#g;}2t3%Sd{KIKt%)Z4mt{_I0c_YLFKf*>r!sN%__9uJ3&Rp9+QkhNT;K zSsIUePi0>&>KUDRwS-VlTD<*~+{DRn-^sNBo4PVts2f>sNjgbMkmG1$4r!+aYkKvZ~g{INx%Yp3Z(| z+m)%NaDPWz&O^=F&HUBUm-4cw`6PLWW0?D%XSk=-baOVi=`y;l?gy?%&b646W=ZdbGyE|)#PmfiUC!Fow!nVEPCK62S=(m$z1UG` z&fEF@yaY|`V(Ez76}!o$?p5B-p?AX1MEb{Ej2oEry~4683o3dePLOQT%k->gm0pOS z_my1b{!UJATB~hf(~OFv+!Hi2e;#-_@ZRNHo$uy9eezNH>qOuw_Ib#}xb1O6!uQ+N zrVT|Q8RcKre&l*uJ}ot?o8K_=B3a|T7?vB-+OykUNvy+kBG*9KeHSSMcT6yZBAT;5 zv82)!~9rq;r1?dj=p4?=5Yp7=|GJj1 zmta|{Wp1e0Qd&^dsif4$S2D* zP+g0iB_AR$vQ4%=5jN8c%)fMrntQ5^s@t0Wx-G_?mVs0g?uO739<-6J87_-!C2E{^ za7hb+W9>LHja*KDW+#aG@)Y|r)ST_z!`#uX@%9n&M1BGDjI2b|LgwM$#3WR+YaW@9Fb)nzMg zA`5vO?n#EK8|tfB22elfR!DkEhR$ykHISHU8gBGAIP}|*WO~oA*nEg8;0$uSy@?~% z(ZW_i8p_TgX-jQ0Ni=|pr#hT<56P!&L+sb>LH32XwRj}P2+#R1+-+#iir7<}iXYEk z6>_06G0Qr6l-xtEBoCFEiDUSMQ185fN^dc=cL`A9H5D_Yt=2&7#7;N{*%NJTvFfjc zqB>Rjjy>8ZhvZ)1y%J&we;fWf{8hy5$jZ^a@rRT5RH|4dHhHq=kjYk3_2;~AZ?Z@D zj3?5A&s7YoGq}d`q*BikYLj0^R_%|y-wuCW?w#}VlC1dRO{#CqZpS_MamN$kwdt#0 z+%LZ`sqfO?u1&xCV^?u6)f!6`VF;+BZ*m9BN!O@)WD?Pa*iY6*BI72i9enX03pMRS zJ)c9WL{5rMi%yPe8U8Uu8QjYg?L2D>leAn3RFk8a0lWbxPnOWv@UX8Pkr&+5@rBE< z zDcTF~?|yV8;-cxHzED%3`Jy?Yt8eIOvg5QrhqqzuDUm8s)e&S%k!@lPz8bfY?Fw$8 zDtDF-6V0;6*3BN^{Li(_z1ZE+744{pbuEP&V)=^H8zu3c>c*uDm!uJLIXOydDBR%+ znXwdYF&UreUTF4cDBU*w1~|%NUjp4+Cvu%Bz@X6T)e*{UMO_uExu#!l%rO=loXDRT zfc|qschJxq>7_+xk0l;0e75#E_mhT@=Ne5OC>@)0gd-}_9c{V|E~axMY>HRkSca@1yrVg@zwcT zP;)ZeelSmEnNJ=lA`{s+NGHlbPmMzSdOzuhsF3~$N)Thmp!=^NZIRx9f1>Tb9kQ!| zyQSy6XK2t1@7R#bp<&@YBc4ZXjO(0qq}CB_wjYydgBkjS-<*cocb{3L+^}J zxhCHMT4+i^>HmM(X+*_M z2jBJBTyge3vPC3O%U>1xU_UX)G0lC`TQ$TIa>m=oC0SKmzGb<-hUT4evrJA>9#(lg4~| zGdpJ`q)I|ETMy|>SI9ZkLb@)yi&G%gX^t=u%GV;c6;i))$ngYYc>r#%BG^J-V}d!3 zFi}RR@^$P8Xyu<<-Wo0XP<6I~K+gFLMLBg7?Q|naY^F<)eYb*4w5&50>Rg&F%1g@q zssydSzBUpp4D>#B4%)n`u!^6=^p_yf#Tn97)K&{w;eQD^GP{BsA{-RA$zNo% zwVKsp?JCDghp`^kg#NZCRLwzLCsgb`QBAo}vG?};aSNVN?xpTU9<6t5up?}3#OxS# z;+5o~38CRrY#)dy)xAGg3gQdf`L-|x*@r}IgPVWLNRM}=!01*MTYk>^eEP$IblsPj zpKQ@$RSp>?<=Qvehe$6-mAa_tzbqDRluy4GcMu4T7ulcp-+n4E^^{<~dhi z`iz}$^Pv4fuiY=~k)na#WLl}ctc*Zb{BR|&8KC!=uahkq4VTYpS(#Q@D(geku>p1b zINuQe?7(7mUqdX>hJL`zXa6A4;W&|KX=Z+Hjz_xF7i4K6MTykY_ZgZ`7k)^+QDFqz z7J+1YB*Exe7=&E0?`#vUCbZ<&g=6AyX^gD2Znajoj+RGAH-ukYHgkqPLslSqA{%%D zS%O1fWB3c$m&}B&HWZrnyKD?!MVul}vu1#VEdm9Y$0xB{ zDJNc!wKO5NQVZZ0a2RLj8rwJPK{-NtA~fTbTqttIYJo_J;r8*H#gW!r`zoAEXL?@1 z1w6>x!W-``@Lml*7FsK!TU37J@8AvcJJY4W=+f;_ob^=ONR?x7ge`7c^cn94d5C4Y zVoFhQR@m3DFPAc=|Fjka`JL2lU<$2OopbFq_*W)B#rmSc?3&-#d~2U|wqSR_1;Zbv zSnlWQ<;irfarBh;aTh7Ar6<_1@1~W+AtpkcY)f;gyiG!KLVkse4XGZS5mev(*zwxB zSz0OV<<>y~@8x#zRmDm22%EoSjpK>K-(j`R5N6W~_;}yYNNSzRM;)tqp(`=ewB(X% zHVG?i1pTjNJ8}m8!dd5f-}Anm0!FG%XoJmT$V{+H1ge{_Yzkdqsb%VC$ktcZzcq|B zH6T9Hm-*w8#}?}t=cwkmVS6tR7x(cKz{(5(PY{e5vYIdhtftmB9^~;0Td*}tS|NCm zDl&%JN_Hm<;B`c#Q(k7~vWJkv)tXIa+S31!1o0j8-4bI3oV`UD`Wi+WS)`?PLeKgL z#ri3tF^KWA<}={!{Ph~mVP#Jw#wc|S^!JSuEtjY}IQyIm;%pa)kr{?KZ5wsIdc3Z- zaj?Zgb!Vf*Vb(kFeZS3R;+1Y$+~#e@wWj%&Yvg(+7*5#f!WA)9Y9s9suYfk(2^D`i zW-Ij%_^Ln<(f2VoJP}NiXgw!~TZ<(NK2O8!C2i_h$XVeJ`X1y zzwM`OS?GP=Ksy{@XY-9E%J#3bwR>?;VDOjV_Mr#EKSlkBQzXmfrz9*5eIf{&Y57CG ztG>O={pA0E84xliIll7IN}-9@gFcfn0af!tzD`g3_qFnE$B#RImMhIQ^pU;>)sE;L z{?MgoE-U)~zK~J!etMeivrqQa(iggG+--ZeAW!f!?;-bY`&A)}ZfZ$2Y}YZmxBBU3 zhM}YsCmY-={7aNG`gY`|u)pDa660uX^%FTxVE%!N^lBmvy6pNAV}Ic89yG+e&$Hc` zC514(OzYKo0k3=y_{RH3E5>W5nA+0g`2Nyjsf!rH?IK$nISq-lhUikC(rLaO0$XbC zm{Mq`uvwZRFO^pF$;`h*Yokm57f!i9X)79DnlDnXx!ZCLhmR}89p&2L(As7qXCVtW zZ5Eu`^`hT1etcK)h0NRY>}86XJX@+9F1FyZu@_)1-%Va~Gs`EU?f*^}=A$M$i}TY^ zuyJDvuVtTUGaLhU=-cZX=^q##7`vHo5We&xD0!yQQOJ@iGRdZ3V?W~^V;%D+3rSuj zFM(luNOwo7mV<8&+BcEA$F!zns0gH^FC)W2%SG|)g!@Q#C?{1F+Y4TPCs)GGLpJ9f zB-n1i-l99m#X(#R{waJGV)!Xs4Cd|H^ivQ{FDxf42}o7nOB^Mtft@=}+Hh+bg(Spr}vvp1G#VsbejamX)(Q-p}57|a(*c8tu*{@_Au6@`XKAdBLhjGBXAbZGk(wq!BQlGb=uGTLBiuma3MPI4O7qtXBh)% zl{Bor26ivg8@r=gAhky0>y7csv#GjZ4}HK$T)_KnjjYr|_)HZ+tc)XPkxz*{oTks9 zQowR;1`&6dssti&4p_rkxX+8Aw}L4;j`nN^y67RYS!I0JI}lV2=nK>;st&wjE`m5J z^D>zU!pT8rf<*ZbKdmkDCf_h;L0JZ~BJ+sahNp5JJIW(eS$cUAxSwG50M?p!AX>`K zYnEY`T9(>dkv;@cClo7ZIb@~|VZv}*Tpqkmne&Pt5*06#@2Sz~8yB%k1vCA@#-$?9 zuMHK0CsvjmT=w@Hg21yPP4*(VxqHaK)-!2%3P;dSjv`I-AoYpz!lyw5K^G2E;yFqXJqLabr^pc`O&tI$RST>d4^Ac-blWBnkg52YpQvK$AFxPA;Fr)74BH0q zahpJ<)CED<7rl1}-2zn1GQ8fuWIcSgdW;4ssS9!DcMq?%6=}KuP{W}tS&9VSZAiu) z3!dpOY7-R+j?aMSQI>{%fj)+>cLKv)k^DlIqxyrhGSSV=XEc=*k&4Z#M%sMc3sXb- zqWDg(B3vO$um?BcY|~E}7}!SX(X})tT8@(YSkcMd4CXmkA<6H zcMqU7`=ZSbq853@MhOF?o7Q-T31>*9?z-+U&t_M=ql1`5Eit9)7HC&!R~QBmgZciB zHbGUr4?HNwq+zttq*W*QrQMExI}>Fl$L)(X-9p(Xt4PmT^H$3RU27BG`P$a6;Evo1rPv%+z%>Of&@%zSL#90OK?X%N%kRQBAF?aX6+ye77lHpwI8R5)|&#IEQ&h_y5@ z!&}g&vT)}=71iiqjzI!s9CQNnk*@cUI!+9My95t@`?jScsL-*Xd{ znoBgbh&T-^HP$xGH^&q2sOiiC@Jds-f7z|zI(LvaFn=jQ);VyizXdsQt#Mx53asxr zt|5P(Ys~#&Z!rVtgP4oW==pzWE#8HjzX@k4H_}SaVvlncnaJP3@&(fbT|!+0K~@22 z+WRod?%`})%=U~7dMa%nMZ6TuT$OWYjij8dU~cVs_FkQJ1#*beh?M;FR-pb z#0uOmR08j~k^NuSN$=c$(TLcfJ|P`q|+Y!O2%j{qs|13YMDMl z4kCT19pJRIIQg!E%+45u9d&1aBIj5{<<5g%>w)y(dq~}GjoyC<>&QXSXy-AD-2;>M z6VH7aR@hwJiIs7YzWD!e%w=gv2-VXoumN0x$@d<$l} z4O5EGv>c=TFS0Jkx#4tuCZ090Uzx+qWXyhdF{Vxt?{$||YgB4|cjIPL43W%S6JKH1 zRf!BU+6-BS<;ae^qG+!E&*;P{{c-9Rb3*K9>t<65^{8f+C8i!m%FtIg+wg(dz@3-2 zSjXWuaV&P+x2;d%&N`jh%WOj*XiJB(S9xFbani8|yK%RDICkx)`RD9tMu`*d47Thn zWf<3izlqb`?P7hT$xf9{ip%-8tPa`mX>>2l`dzs^Ay{s0yJmmvG`i0OP4Er~-54Go zmSI0<98)^2Kv!75^dH4K;~K#y>}c}Ua@C@uo%`5H=J}e-rRTC=ejArL=-1`a=IV3i zD?&nWmFR9!K|vv0o@S=c`TU<*9e#vmmlRY`3?YV#)ty~~Y6f@qK6a_B*$iXuu1yP^ z>>m}7t6pkYz(m{1I7)$n~55xC=oUmN1ggT{&UQ4txuGY$`Es7b+yQmD=BK72fLQQrh*~PLE zej;DZmB~%?dhVgP$x7J=quSM5tx{z{U@uW5c@2r(DO4cMBDYz=U&pOXU#L=c3NC&l zyO>@@Ub9H3bk>`zB4OB%N~ITo zbVW|g!pGqqv>c!0D(K^xs0l{U@97>`-w$G5m_z-*=q^XM$4)v8Ggc2&7A=_+JOzo_ zkC7Y(e+Zdn*lDO2is7VC2X$E)ef;zPS~?53sPF&r-w}5l*Ps4e0CoUk%ocU2g0(OJ zb!7oM7Y68@+iYB^SaZ`^sQWGqz*yO?+-&DI3uEe3M68+r=lg#D2ai*@``qXAe!t$Y zPI46bptrR$2BW#HLsRgf1s#Til%QukK#RG8wl|tN-zkx*`wHzLQltX;+8wRsF#25q zT3Cg)gsNpR-@FZ+Y6To}Ds}f=^e*~Hs>yp(i@TInCD1J(pZZ-Nx?C}NBWv- zDp+tzJ);K67uX7KTMt)A1~&Ee?%Hh5XDa!7ZnTIUoL7i-O+}mBPhS8p-I?aI??Tq( zWsfV_)miNwy@0z;BfG4M)lR1OMKS9bOpWs#G~XR~Ssrq~AQi#0(FmJkJxpZ(o%B+D zCNsrn0{68%L+Jd~bnXbz`N2um{ttRCXEL9<;S%<-SFK4bW1f}+UgV<>PJ!>Qk4Uz) zT(=EqMT589kt36}1nQM1kzFF{{=1-6o>P}asIvr2-a(IxJkE3;-$(_1g=nK$bOf3L z6i)DOZ+!!j_6GP7!}E@Cw-oLXWF42Wcow6-FU5ylN{&T2n!luGq9YpmbSnHGa7He$ zIS2d4Po&O=o}8thpd!5w(7z0>XP}7=<*#C-dcO z?lwlM`GDw9PHQxJ_GxtoT0=SbFr7;G-P*g_cx@tA_0{OMv=qy1CH!bKddnWp z`UIz6$xBp%=RgO^+HmbMRq36uN$&su=cdqeq6$na19}#A?d7*|SU9O*(0#D75&Lb= zN*|&Rjn-1xO&L1(HSTqt9J{gfKsl|hKsVpZI`-1{p$%H>6>U`nZuw9f{0b}#fnS&5 zJWKUy^n==^HPjZuMGmR^pxL(EvlvTZ4H(*oot6TRuF%SGPP#j584cb|MAv9wj3IYv zGLQ(NK~~TWq!Aq#rqj8inEk$?XAz-UX6#`V9<1+OK+zAMJd1VKh?AWT?#`uhKN+kL zv{y+7fCJcW)0kww3L2<@Uarv3AjnCH-==dW$!H*xIK52WsXedV!@{}3sXXLVQo+wG zUfY3KC9-`zTxcgzzf`C+3SKK|OQ6y?bd@+`J3Oum_+3Xmx~E;&?r;*F zfyHX>KS29I>!uIVdT2v|a4NLd708@M!ldaFwfC`+-=jChI8N{&m}JoddZM-g?e%@+ z+$%^l!M7X21x^5=D-j44!UIyl&~{L17F4>2P71$6!}sA}`f#y}b636LBv7B%3 zU^jCjeETH#9|@ffCc`>a%LeNTz#u=ni9+5^)!V{3rb8tK(8(C6I0)a(0$b*CLX&~P zJx;V0R{SX7QjXr74Ml9{>ICThG^<+)f3)(+Y4Azl?E-D9Iu3fN!rJc(uWKLaaq+S) z@!laYARGSE8puD11x#$6l})CHMJPgxrQEl*o^14@Z`wBQKTNAfre1Gkh0yXJr~~Me zu^Whqt~XBlUpCNJA|G~gWjS~p1yxic8IqxZYM?Zg-;0rj_4)o3);J%Cm#Q7`M+}Dw z6R|lC>AL>8c0%2V)zC(Ds7utNYJH$8I%Uk|xheWoaBKs-HwD}e0ms6K_!n`}5o+%!76Xul(ESth#>6-$gOMlrZ4Gj0FfiEN= z;E0$0O+HRE4Qb?~qseJF(O&$D@%lCPO((kujh_PYJ9w4C6B@!VmO>v5(JZ#X9ZvFz z@JbZ`rE<+l+|h?^`x6ws32pbV>e8>m6Tu)Y18h0Sv)a>V=bF-#9X+aj59fJTp9)v3 z05ez76K8nj9!S{=P6Jgq%^ zx+`3y5$9SGfmBczcgbN-O|&hlO`D|3d~-X}rV>t7z_W6BZYEUeL05J2&2*r>8eTI1 zn5041E8)eb;gQ0E-pMNqxwSmPm)vlNY2aKx{RevSy(_>MzQM8;JB+iW;p zBi2#H8cu_ILB6#f3~z_dAh=`#o@uN8fIRcF>NdKuHNwN&9T^aXv~R>oci~Cv&>|XS8F;jQX6xNi7A4mvOgrsOu9oUi(0Ga<7cYd9(u`9M9#wYuM_H=ka4Q(0go=blr3p_ppUQmVP5A%C2-wFZI7TWvhd1*+H(de0@;OWJ1 z$4c&f0x8*>`J|HP+VAb#FO)%;3JK;2u|j+-TN#3T;ZzPddBvpfNe&NnPNwSAmb{ zMkeHMLPT~7c(jG9E@R*HO+zw@vlcpWTd;R!1OgeX-3jGQWJf7zvZv9TPa#Dng2$EU zRHr!m?!1wA^Vw-G>lCuIoYU*V-uD5!9b8ky)dhU&1!5LXrfWo(@55bl!P=eh zu6vqakJFRrHe3|x#CIP|6&6Ph-znz3E$nkCGQ_EmgX3>fAHb^)qKDShOzo&TlG7Br zK_ypAf**!hv+#pQgY5!SuB#1!z$mD5HduNRxg&JAHk|f-b~74&PyrQhgmQXlziIQ( zf`&j-S2_0*FtM8bFq=<}f?7ljd>Kz!p}F*jaHH+uLkjy@fkqV2Hml3{s{5A z^_+r_j^Ubp?BxHv?bD&e4QdFD8l12ZtM=&GK%{`DCW588VD(XivgZz{Mq4lh~H(cS3h(r^f#uBb*j}5&#Qo)qPv&zu;)6qf0@QxLH+XwUoH@l9O zv4Nc};9R4j!yQPi4EB8ne4C1Ftw4u9!)G1fvj=&v010&sTn%wn4Rq1%IhX4MUtZ7W zU0B;x);$&uQI5`?ge^M_TUvM`Ho%P!(dq1(;sZiL{vX5Qn~0tz;u-S=B`7zPLRM16 zs|%F8lzX^1?Q%Hd3^-T~IvLhrt>fT0*?fW{4xP%4-Z7mgr$gg~tfQemU3(50<3Ja# zg2uzhxoxboEmqS~B;-JS1K4yH+1C|(FIC&2(=Ue?73v?N9sCEro&X!@mZ~;T7pp(0 z!#RU7=rw)m=C}jeEYx;_nK2P-cOR0Vmwo`vZyDde1O^J4Yzqv8E^w9eUj_}F0(XSe z+5xW{8SyJ5=z^2xqD5D$bC9E1oK`C&PA^`wu(;QP6GEacXJ>byk3K|#Tu|g%ts3mh zV-+4VkZ5bL#XKq5otS@DTDV32TFi&YZ_~=(KV&=wX}D?BMx$XC%dJBzhWiFnd((_gd~a#>*STu!+wdoRbn z&yV<72XlfW>Gipe@8q%DH<8D};-AVnc7m7whEL)*V(PPzco}fXC{9#RLJ9aZ9SN6@ z92HiU@X_u=QtSmc*7Njkd@ii8)9~DU{VVPi;DqXfNA>kHz>=Qhx6cWZY+Z1S|MDmE4Xk3 zDHwysF^;P?LjSv1MFlt82-pbER~IOu4>()F z^%Y>f6{?Tsp1ai)uxBW`%U1k1Yk@l+2z(%d%XS4ac}S03Emb%4AEEOF?0rLIzgO60 z3HUIYr?duUR-Pp|*)H}ba8zjg!W$uS+^WHD(Xker0q7in0|{?iDLAz<0`nAbPgop< z++%)(?sIs5EO)Z#d*K>F>huLKQ=v&AVM|%lAy!k3Ow59}jn?l2z1CVsVuq_Y@$v{w z3O+d*><@x_Bf-HCSIy@>XOTi_JgJQP435Yv;Smwqs2eHzkhKd;sbn={Sk(!h-v@a# z3LY>NoEpY1gl_GFhQt{ig}8tCcVC#1z{qtzqWG*R45^b{SV zmuS7PModmY(A`1cvyBxC>$elQ&P;bC=t=ZRVV?-SsT>$jg}&D#>mDGZg(p||hQ~m& z0xEet^<$th016P2Lul>7))L;`tL&;Z-xBzJfTsyN^A&9myBGzACL$rmKy5DYXgQdZ z&3BgbtTNzQ#Y!6>SA|EvFEGvluKn@n2w9jXq%LrA>Ozwd*iyz?Is@+^e7l5|mOw8# z?7jmsE+0$~u}ljb%?h_V07jlsGl5|u=iZf1@#k_nWAFtDU2zU4EKa%+SL8%^*GaKQ z;3X_p4>-I$vd+TDDO5l)g~+b9KvP)e_gRZeFGm&}L9@Mq6*nycU*Q?4tKWc<1V26v ztcu`Bd8}91%%X#`73eJo*XMzkr-1q~_{4GWYI$Tm!h1TFtMb|13Qjl$FT-h`CUh|I zt!bP^5l=nH(ogw+px{^tu#aBYXyHv<~`hJf#0|GV77p)e+vX6-*LXD|oty z6zxOSw<7-08_a0~Mm*r@LY@juxi!4^9z5Hjzlq0GbWsiI$WtC@aqf8e@S&e}|xpw9@+l z`7F-!u2u@Pf72U*&w?xGvVK!QX3W#6j9tXJ7 zJf1%mZ|#rl;UG9s%(-2HvR&Y%z~P~2YYnh926Oj)VDx>y735jv5sRubn2`-EeP}|v z*zGiMXb$p1c&YDc1z^Hd=qZcSP1f_^PyN}?H12Q@UL*M7X{i4pYZ2DLs0g3L65^>l zIImNji?EWeac&mQQuta$yks9Mak7KX=*E{dyuj?M7(5Za7Xi_+tfMM|OTy0Y2Zrv3 z_K%=@=IZNtRw26-8kL~!UF@P=e zB3`zPGkM5q?Bcy~y#9|W+M@3z=)&r{!hJg-DVGDWZmg~z*^Alo7%se(IsF+hhQX^I9H)l3h#)BsP^Og zZ|cv2;ZDwNG`vXUq_yD`+v)Lmy9_jk72stwJ6^!Lv)G65#a3~bQm|NPI#ZyxGR{vx zK+teYQ6&yW)d&6}|7tsDcaPonhMuyps}gyI`TagmvgkwDc`>Wm$9|V0m0EGyqrk<{ zoZ3|OC2ZJv5g8~vpF*>#hMKOUa~*0ydE6O22%a!Z{}&DM zcd+*W_ecTuceG7#t210DbiYbgAf)p{*4Y+rc@K&dk+y;81mX-^>erD18-UkIsH&x2 z#mY@AtADv}68yLVJW0eac%5%t#gE`ZNU;@1ssGQ7r_V4@FYCD`s;ccbS?0IF7zZU z0C8;)UL<-=SFp=%Jnwh><_&>tG4v|9+Zo>R=@XG7OSxkv&np7LW7)TmxmWpCMnvOi z!#;!uOz;n(O$w?g1S;vg+lbX)Wo;**72%;2^0|~{m7G0@ZxTADry z4ziBbtdC&LaV-ftOW-7gzh@+#E8*u_#y%c$)h>9U4^Po9R(J?{@Ik4i5!rDH?4GH8 zj=b!E49@4;hkQpwC9{Bt(CqrLrs=#AA~O8}>)fS1p%2g>$KI|FZ(axXrl9wA0JAnh zw_ZH}q?|~aCD^_Lv2>QO?^8gt1c-}sSk65sf=6qBg23P^o;Vd~HNxiTrwK2_6y9qM zY`bv&74X(o@Ec)$ok8Ojzo+2^Zig%oQm!?77V&?vGI74!ftxtFQ$S`Kv@P__q0ov6 zCIs}c(4_Equ0%7ja-HBe2RYkNL}#w#Y7tZD3ct+dr-Z9R(5Jw~1IRmpyTbcbgk@9C zuBUQ#q9=PXFc`yX=0c}i;n0`C_)@eUKYowKa9uz2BO;SRVtCN#vh*pec@EDJw&gx> zVjFi_4{T0y22bf{kiieZ^9SrltXfDJ3(slC&kC-e#;Udh9ibzoa!wZg1lNt`CC+dN zs|kS}A`UFH(_N2BDj8E6MA$?DSzukeq@GqxwnvI~L zDG>>}fOoA(mE~ADsXR-_xA_tL*~Z=Sfaw8tz5xCztd?nLq?3{FgV@;N`=Cbrd@{fy9@?1EWu>X@;^$DIYyp@BrKh(8Q;M&N3#_{w5ES?9%%I3mzh5>t# zL9&bUCbybhFMv192OH1|{*#pgf7&e-SY6|T{U_=SnBYa}Q zn=zVC#c7H4Rp4!IkMH0a?OE+~n~h-4I)p3BumNT827g(&V*h7U7?Z=K*=gwzloGvN!WREL4@CD36BdrRY9H&rM1 z3b7Xv%ia%^vm!LG5*P}fuE-7h9jPaDvM`VvhR2``t5tB|_Uxe>?=IkP58sdC-qEZo z9I-HFP&?5ND9#1O!p|n;d0Vc@U_XVtD|CGw!{`dyl>ZaCim=qnX zsjm0jcZBU9(}8V-v%Pnxyx%AeFG*Td<4)2K)FFLpURRINQJ_Kmptw=-!<|*$v+`ae zGhBxbB-wRp)IOTjK0ywoX|MZdxI0pt*44ez`@U3D9bro0my^D!*`sFfr0np~z<&B* zjP#%KTzAiRukcQg{A!5&)0*MMiR%;Fkd67J>Cy8Qm-MQCw*P|vHTi&gUw_fO#muu0 zsZ~xf_GtIyosvtAk-sGCHHwV#SwvjBXz#f#4_n?ieEr{he?}EM{*X=>bHWp9uCCR! zc7C19b>6R49XRRFc6E11&NH4@Xkb4!;pe0pwZEuel`=FnJLSEGarGP5K9*REJWVl= zLB!X$FoDHSedox;p^1~j6O?JO<8D`1cE0%6xvuBeTwZxI6!nI$Rw%XhfRxInb(?l= zxIeL-vLWu+!~1s~cgEc5dB1biXO52~IcTr>YrW{?>f{9tGwa??%+?2cm&B*UwY8s$ zD{}Sr@6)#=RMolOAU|bU>X6j88#bu3Fno%(rOkaUZ#6TsrH>z<*x6%8&~XT z=4|A>DP7ZkHXDZ;c8pE}wQ(_=OTGszAv z2>)x2G!`4jnd;!z*D?_$MD#M7EX%QKUwVx!F)G3FGVNb|tbRqkMPB70|$Pa+W&RQM|L z2XaU5Hcstj)THkDXL3@1G{@=d)D(T0k)qC|iZPu`qZ!I^{b=BCb28cy*1K|7IwTKJ zZ^%c?A;@hU==f;M2tja zC~hU6-KwXN)x8Q%BRI|uyrv!So8Dv!SG+u2Ixd~zS`-n@ujn zWh|dk!F7mJQ-i0p#iD!M$T6Nbn+KZ&KQ;FmH>t1s&e-ZxW1fEyvUatvc3tt!(kl`= z)Vxr0WI}JIm3(A2R;`{naas0pwl#4txTBP(0%c?&FHcxh!(OvN;^VU=SKrZ3m|cTSsJ_3FaGyz%KLz?4$=IWhn-BCA>TP+o{GyzuhUoS8L|{hXchfN1 zp=VpjW*$zZ*<$}apVQyVUrWhWt@?-5%-YDtAEJ%(eCAl<=;&VLAE6A2rCN|RSv4(np*I2)56|j$$V=}ZOjbimfVf%uReNJB+A|f{idz{J$tDg*kjCv zKmDPMRfH^UNe07aqtIAn+@*@lVO+!Vi!yHMqrsm(R3J>JqAf$K)E&%&s>d{>E7;=| zS~j_J`&A2CoACIj6J6T~y>2l&Gs|u;QLXRE&&j}Rwu<<5BQz#4`$*`iB}{4MQN;isA_YyC=ho_ktf|1!`2+#fst za6jXZmxpnJ|6_LJ8`R*YGxPGBz(iv$RkEv`PL)L@ylOsAwbU$fnf^A4)Qf&iJ}*u6{^V@xe$IbQwFl;fy$KRsi)Z2W zbLlgbqjC=>*nTcOrkvF763uC)y)K*n52SqUES-$+q4}5Uoi$y#>3>Qdt5DOl_n$Hk(}$tAdDQ5p zPg5R|zm@N+>BbAjeC$hfMSZFHC_Mn;z}(ABWm|4Mr#IC)t96yb)C+A;TY}@yGTk!P ztOi^B=kU4Ri=x2pDE7{V@4x z>G0vo$|d|&33#KVBU2U-MvrlMgPmD&>BaX+C7_7`QFnyWua7lIe5wVKKtr-MvCE2Q4GK>bPS#+<=5 zT7U9X3YqZrpOLNaCr>b%cYD$yG6DRr0CSd7pEZVjss>=_9sEG`@uW>-dR{)<@-kNW zU@AI$(Whsm*}}*{i^fJ~)>y!d4NRtLyrb$yyKcw5I?;(`1i0`U^uCn*m=Y|>BCKB`~yiYLrb z=nFq7yXAkB4087!@Knt_1-uRtuWJmc8qgt6}A~vV~|zee-o= zG&|g=Hj!7W%d~aI4QBJcW-g`EN0M?*y-VkXvw@eGSUHHkzWL}DA~$EYUZ^Fri~IU# zWUz|d(+bX`1Zgc%UvpUgS!u1UH_p?!wn^}JW03xdTF6Yr3(VD4uua2y3fkjf!=UTZ z59C;ut38y*WSi0jKUf*LGU?#kPP*ob+KrL=IU*X@>9Dv10sGR~scw4yd3!T3unMB^Ba#JDMq@~5i58?OaQLUn@l|3!MV zFrT3lL_aK>CY<_@^l)rPonf+GpnXO*`7vq?UNsw-@%kQFkqUiJ`0mKP@oBau6MY@r z?j-cuMysXlq3cgaC4tFxBDb_$KgRjZrN%iGd$|IO>AWne2y|m9)siQTt(r}FK~7S) zX?v+k647uG?Ruc!0VW~+09lH2!IdDARb@)&8oiM=419D!b@hzr=ts9!dz7_4BCk@a zRgvkoi`P##L%`4q@#Ie^r*=lDgI< zcnFuWniTZ~tc=ad0p)XWHyvM0z<9!3LKo)d=3eUc9^%uzuFg?EP!g#jx=P2t-}t<@ zSt}4QUuN20C7$C|Wa5Xh3PqH^oIKeyw8DAXW&L&dof7C|#v7^hN_vz!%i+`*ZJ@^J zjB4uD`ir`(e}qphMXjYYV}|S3%sGBV5gAY`)f!+TeSqj`ovjT)M_h~CaMH=7T#08+ zb4z-8NoYPhv?a!$=6U9${$kG6=PNU%@0oFZ!5^y%A3gaQ>TtC3tJ*B6ah;x~-eDg4 z9{+9WCM)?^i9^QRP@ggO1U{kK_YR#)rl_wfe@HEv_Uls~S3GJyvCBb7kjwNB(an}r zR{c$9rG~}>dKxP7dGu{jALyiBYdijxj(`{!!2jStMe z)VS4BugQbtUD9WAr8*Qo(pGy9+3l3RqXWS_bt`h9QeTdCC8D?Mh~my=hU^XLTR95e zln#z|z&~su3#cJHuO$`CW$Js%EAk`A-9k?14fugh#oshef0z6sU0%wdF;UHZ0ABY% z|I^4Yh=HQDCMu6mQ(mYJpbJbRc<1wQ-6-hx4Y=Wiz|+B=!S^}4kLXPnZzR)iWdkx~ z6BAxb)YfpBnxTWtj?NGN5g2S_s=rCK{dr7EUhD5EKg1H-9Lfl<4EK!GVP1v9zfZU0 z&i;D7hrT1yi_pV%{ad(8Z16m~YI9=)-uk9=mZ&eiAblit#}4_8NyhKfvFKlHjuwWP zu^Yu*&NAozEY{F4Y>#AOIPW5tL*&q9lCv;PYeGNAR?O-C2AyFF7MaM46q%iZe;*)w z{4kwf*7_>FlYGsQg!sJmM|24xk^t|d2@chh5MuG$T5K&_ea z0h2hNM!r91l;B=-cm<>(J3@T5k{6U_AP z4o?%=#n-SaMP@`Y@~%Q#puA2$wWsBA%4%fNC+c?PQ{}W$2Bj|yt_p1oI?bu-+wvlM ztv6)8WGBCh_E(^q<|B0MKW1bS{}=Y{S!DKfCcHoHuc8CUBXW^aqM62b=B3D_yr&4 z4cN$CmFCJ&HA{cPtfr6L$3ZnPR}WG5P9J?_%t7oO{Ezy3=B!|R*cL7ct~cED!TCpC zt=vS5dQbjD>8iHY9RW``F=1Zl5_W47DCtvp`6u!XcGI4G_51WV+#Gl#@VVL6n1a^* zn>0ZB0S?`RE+)Iwty&j&bUid*V(V%h$aT%cLtH@3Yaery8DgrnM^7he zM<%23E1eVf(C29fTzok)`#80(Tc{d11wLINPS7w?A9qD>i;t!&6@@8ACw;mq=6jDr z2Dc&>NtOq;WCoQW0d%xXy$$hy5lI-R=NcD`F6iNf;Mi{bY_FgJoK+I>B8Sino}-7? zMe{f4u23sfzLI~I7D;c>;kY|>9fLFrQ?fIe?(8*Q*9TyeenQ6)39U32jx!rSx` zVG;Jm1mgjgbY~-l>%=vOsaGyW_xg&ChPBZ!#B68L-{pBM!j@DfSHb5B$hIg$E=|&h z7;l;H2K;oKuT4FCXQCWgKF zA9dmjmF3!H;}@{;Uo7>OaITNwn1hHM98hfZS-BuxkW}oL0;ui|ewDxQu3SN1+{rmN zMWWXMqc{!qvN@m{?Gv*#6l=A5sOMpyWe8`W&UEe2q<*()6M<*di7JKBU11-ePioMP31q7 zR{9U7HI$l=mC!EyD?XvQR5>(N=c6ggOjK^B%+~fBIl(_d?ZU6n%VCfqy!lP>W6hNQ zkecJ|Xb(TVXV_T5SLg;#Is%HEP9J%ssZ44qx{O6*^x0slyfb2G1)FXcc_IyRR zp;ln8=>Bp_?M^O@$V^QmrnFvPWCZD|_91qo&FpN>(z{|QRZs(xjJ-Y;+r1Jheh%s0 z7s-~Ozhq<^f0D;`1>0aJRpO`dWu%kmx*v#5#!@~Vk=y?$@pwso!ERZ@yyLE#k1ia~ zAgwn7@xP4A=CHuTz!9?zeI+gUrJ~ekcs`z#r^|~JCpou@d71g#m*LJLswyJP#2TsQ zbBn$%Xz`QqK>tg|@l({yoMZxe8ZgYK+IA<`&P9UGAO`R>n&f-RX89NCZGLL=)}M!N-HQ*YKmQr6P2K;W2A7 zxjL24Rka=3*f8qsqri~6;PoQ3m>-~hQ6sz^A7ces(1q#+ykIq$jC~DxA*!3g=)pm4 zJQLgBQ)bY?hz?13EoxJb*XZbbhCHjL<&4ebojDBg~)3>RC_N0<1 zx0b%4=h-9DEwsGp+E@A+-Dd10J13EN*-fQLc1v&hTS+qfx-D6n#lTi{OggCk53Q%A zuZ(#X1Em}ILxyNO^xOI>?AWt((ECLi?7!pN=ljZ6>U&H&D$iF(F*W=Hvllvhq1Ipd z-T$gT!>{`L(97Tz#e%M6GY7&gZeyXMchcivq4d3cMwao*UDIZfd$$!Xn~g`Z2UOOC zR}Id(7=3RI8nT!wpQ-+d)*Ya4%UoUG{eJ|BD^i7$3+| z;`qco@qG1z&YCIB=pXZjuaEzxbQ8$7(Nnd<%1fNpX3nxmehW-!Lg&s{r53#Byi^OT zVi;bqI?{3fZKnIYDE%eg0J%`ots@zfjSNcc#0-t_9b9mB#*kSnv zrA&DN3AGCODC%ujE6+&F>0vh9)6jd>`?~+8@;!brDR`6aWA7TGCd#U+id}l(>+S1I zH;upjZ_(FwmhnhnJU+2a!5;LEG>md>zVbLdHy(K1zKQ-=xw|?9Kli7Bp4{hV#7FfR zR=k%fMIT9xY#Wx6pHT3!HNl=PoK1mtaeUjF$RFtr#tO2HNBdY)(-( zp91}KLc&bK$`d`84xtrK06Wh!(eMR%7qWR0JsrM+`$z*~wTA53Ql^ z(N05M*gV)@PnjRkfoK7}HOJC7scGN}zNr4{Ehz0#^<909`33R9Rl&MJnNI@1HxrNb z82u!=l&HtpivIL9KHC^N0{;?tmI>-}`1S&2xH23au?(5Agt_s5;`6$Nj`1?~?Gh?o zO?0H$M7fiR}y!4JV0{UsEY|=g?wlX7d8w>nj zti8U(g$`4DlSv)zG{vDDlAGX_yvLLQW{P98EWy$i6;;*5hPn|WSVr{iJMAs44n2~- zrq838kRoa!MV3WNJRVEHhV8n@i)x6RUazG7;r=DW(V9WaM5aA{h19IW-Ad9i=<|=x_Z`NG;&97v%P8Kwock4Ez=N)-=sgdXYL# zc~PD~97UJv!>gD1drD2!iTX?Q(0wx`1v{GqsUc5MAEN`#vsk&iKWx?-#BOTPAE+_h_#1ef4G)ayEtretf12)bWq9mTks)75 zb)_!8OZ36sM61pcsXT>ex2b&3znDo=eSCMZ@JFz&G`{DCW~s}?M$@D|@W{5l zfxg!MW4@5$=G$BSi+n4Y$aBim&-=G`sDG2x41M`9QO6kd1L=WxtS80u ziMy{S-&@bu#y?*ANY28}?8X^CD=&nHO`$9DSWhe8Ori!e(CiwiCG=ZJS1wDpeTTeX zd24(B^X~U8_P^}k?`z>3$~p%7Wm&_gRU3WoGiiy>>n-#Q^)6>}$G84b$b|>KU;In4 zi7!e0WCtC$Ch#*{o+Z_#x6nlY+y1To_vzi!6I!n&*JaX)={KZb>Dj$e@!|LV2Oj^3 z{D<@gJor^SB00(vN;NQMYrT@%3*bqc9zV? z9rQj3>iNJ{RD{#9h;vYh8Z1<(cEq~7ZGIE@6CYeXuv6qNAJdN;xADr~fyZ^?C42&V zp@Tu_Woxk0zhpkyH-XQC*Mm*zhW(^j-zcQEIT6p?26UnA_%{DGW9S?l9ZI8TT{rM? zJ{_07fHOQG<8>TZlBz8wHvD6tBOS1k!%gT9u7-+&PX=z7F0|APEO)PQ5shRGR6Gmc zxFe7stb?aQXwPNgp$S#tt>M3ds{`wdzZ&YFZognkhH#0MwNNvI6p2>y)k zqLulfF~mG;?g_fWzJx0YgA&&!PD!kr=udn%VQlyu{*ue))8>EZ?MDN(f=2^Kg5#Jh z;7J&j*edDUq}EB35{`tP5AH^Xev{af5!euTJ-9uTlh7-%b&{>d?4*l{;l%afGoi+z z9zlEXC-~GKfjYstp@rce5*{SXNjMpv9_|{>31^4ThSE8K>zu^K;9H@q!B0ckq5k3W z&}k-vO${Fi=OsAlwr>sRhV0>&!;gpOgl2?p1`h-;23G_(hl)Z6LL)-kLYvv;>Co8l ziSUt70v+>{LN!9eL;0cDP=4?cp8qpZ;se1&A$Q0gIvlVEA4B$S2rk59S51fg#PCkO zc|ANNWDqf*1;=~}KVt1bZ19C(ztFgF?}UVHaawKh3sR(&XT#SJKIM_LozY=QnbI;_~S({q(Uk*sgZ}bih8F3>JH@=-ppZW4a zFqQ~_*hOU|m+Jw3#W`ef^h29UBkSS__wn)EsZ_Ym#s?a}2R(+U{57sQt3<=+O60rp zeEBD3rz&io@`u%e1`Y;<5v`Qq9W_R71Z1ssf;(19+96KD~Ky( z0-Y!=0S!>}C%TUpeZ77W`&C0Ld6^9TQuNbn?C=%z$wPQvOzpbn#2da2%jR424dN34 zvpHQ7L|>+4bjZm>x3ZC)JBhZgBg$468NU>baxmWOR&?>`gXT2_-CAVGO(WvjAO3Ox z3s3aIZ4FmNa|1V~;>R7!s(w;#;CWQ&tJeejPE@??B?`L5+>Fn~2G^`)S5(R)8}pSq z^u^6rMQ30WyZ;%pwMq9{G{AghBQaGV>B3SMxjfW-!L!TBELw?fIu!{>?1+dk?@x0nbZH7Iat)0@JFec+gY=sVa z2iP7pQi=3Xr$Dc?Ts#!ToKYWkMMjMADZbCQ1B;keum!t#2cD@$WDNGe8os5h$9ijp zz4|u*I(LX@L#8-=Y}d2wY@r%fkI(}{RI}a3+cyO7 zUR&r6I}V&&1s=s9D;KCfw4aSiccq9kNk!8=sF~C_EP-A{Wz0(TI+3OJP(*vqC70Zl zVfYziBD+lG3`HejGSPnzvRCA8i=GD?@pQ&w-ycz?qHz>L2RD=g?CaxL?tKiyn5GA` z^Xe4v{*c_9D|gHPk(qZvj$sWC(Xx=|>_k)}7UB!3p-n-L>dyp=SMYt+lAn}F20$+x zfZxFaFzSlfah{c-uiO zR2C_@%3nPDEqT0BiVtWnk-Q9g+>35qc~D;$w1NjfRaR{BVku6t;eQ=M%xIwApOt>D zwuVzp2Kz;Rr^x1Q4ShaP|6x~gbRzCZ9JmxZ6jfpe(H*Dbw-aa5g_C}niAue+PgM`x z<~rCes>rXQ9fqN!R(L%B!yh-({0m&1&FSsOJCzHk6P)KCWrs?ZH@Fg{>u@Eu$uX*3 z{v*4-H=Y79eQzH6&pve=R3YlRvsspG#|kK@A^4Z2ZxgmWJq}kYk7ECfr_=TaXman9A@sQ- z>hQ|IE0GQEB9l6U=-+PnC$d2DfOP>r!jAZMRpqQa0>9gvc#lQ)b2~V;=xFc6_7ej>LR2?jEhjG7gdE`?)kE}EdLA6g zM9UE|C{gJ_%mLDyxQBgh+8*MZgf1Ui~?%+=iq{v1ho1#}iK0jsD zkiMf|!?W`M4k;|*`grr`FalQ=9VdF=lbH@o-qqU}Zxfps5$Mb;@Mr1N`?TDHNY-Ii zYlRC%aj*Ws_>fB77jv}c>y^+^5$h2Z1FxthWHPR%&-kzO8UH~lR9;bq-`YytU-b5F zho`QM`ZM}@9=ylPUWVh9=&Gpd3D(yD8A`=6rfxc6do1`62Vj zy%D*Pg}hRr9#Q)`FQRRi;-|l&zDM29aBVUjS;j!^Q^0Xi`9yvh_DU_KS`mF3M6JX_ z#uCAMg9f+U_#1OFY$IpFsu6qBl+CqwCHWe)g}1)N3Skqqq+98+|lIt26@tJT1}F|@Lab!MxtKuc-x zg*oauDr8nsv9=4o^ALNvE%zt^A3GrRW1RFCJsWi!=&J0n_2BltinXK@Oc&A}pX#EScaneEk0?Cnu(-%ZLi&V3&| z-vvi)ty?4BjgIsht|0v^k?yOX6P-AR&2Wd7=4S4 z_y-Z+5kPpe(n?*dw&UqFwZGIYSSXwLD_;ARGkiulEkBfXynSnx&+xPLVHY*jR_YV* zo^qugIG@A4nO%$oe+|l92p*l0`^&|0OL>)?FOO2*g>JHxHAvEV%0y+P`XAk2M{s7D z@R16lX=|j7{)he;DF@&AKKT0sxWFhR(^RD)l=T%H@(FUZ{*xEW|493#@ltn5lA@*B znRdmfgX!8vo3 zr~pB! z;eXcujjxOUBmY$Y75^^3Bw3}QQl9iK{+ECKamS`@iu2?SJ4u;s49;m)-$pXXuhV18>T2-pRhfzKOncUkWpsOy7CmufE6qM}2NG zhNt@r{Qdl`@kiwP9`|kV?)Ap_u6x5w#(c~BiMP4;u(!7FzOSP{!QTfD{XqXC{%`$7 z{vm#=|1Y1*x8K{<8}GgBS?amw(Y?=l=X)K#ZFoga`fE!k{cHSV{OSI6z88I4y;kpE zo~fRHJS#n)d$xGadk*6#+34Nx&G6;>{`M97^O=IJ`M>l{@m=!H_PV@VJiRj&2)*H%}o`)T+0?t|{up65LCJTq8*iD#Tg@+5g~x~tqd?l# zQ{R%^R(C^Q%eXSx73Vtayy`sRY~i}-Z01s3!(7dnEI88D(jDu*#p*1~t)Jyebsch! zbbjJo=lqrlhRLor+`EBm1V3-NmUI2@uEnl_u2x(X>$>HaMYskstdiA?Jp@0{iw=$znu*V)b4!uhPTowF+br}*XZN8*2smz-Ul?VUrM zlbx?P$2x~Q^PKgZ=i-avN5?OSUmX8u{MPtC;&;Vwj-ScZ%i=G_Z;C$=e~@W=vNPU! zp6{=S?-AcBJ{14J5sXibuNR*Xf81eZPG`ILQSp=be1H6w_|M{}$G;z+8$U2U5dUm^ z3$AGq-zENKK3@~RFTON>a{Q<9+3`K&z3~?uyBy_?BFATr_Z@p2*Br|n-#QlX+gZmg zhbO*fyepo{o%k;u#g18y{tn%7H}3DazvAK@%^Y1EUpr!}~Sj%T`G2Oj4S7bVBaGyBG@wn=^b#W8o-iezQcPdVG zv~VFPJ7T+P+hIFv+hm(-TWTw`O|*SzE3*C1_L1!q+k3VW+hktv*aq7A+A?j; zY;9~ITUXn2w&AwdY!htbZ3}D#wn?^^YZ6KqwnX*Rbl z)s|puU~6J)WUImFR@<)FA7Vd^eJ6HF>_q;3C$=bdcI=|qDconkx3HjYh?O^$srwtei={FTG|J!8AZX7XO=*c!3c*h?{IVot}L;@@*I z$6_wT?1=d@=12biE#^qfmdNkl$NUoWWz5Ey@i9fbM#PMXnG!QPW>n0Z{9X{#E9Qlm zr(zzDX%f>e#vfBBrfE#=nDm&sF{v>vV}daaV`{}TifPXONil(#yV3rb|Dtb3S4ICF z{cm(d^wH>((Z5EYWqRmEUPq$0L~o7W7F`~_B>Kzf_o5d>PmCTPJvDk#^pxnr=z{3C zqKEL48$B?3MD)n$7o&5cdqj7OZXDe(n(=(mG0|6}EYT9bo6$+p-e@J-h;~KSh_><0 z-Keusm!tlP`a9}$)Q+g1qe`PTM|}~smH)qs+RbYlzpaS+g!hv9=8I9stuIE+i)s@k zM-@ixi<%!bHtK_@qNt~%x<%EBa`PI%PexRysHdWoC{L6lDn9D2H7TkYpSYr`tp8cB zS-?Wak4zuQ3 zhge^>4z>2P4zzZ+W?CP$cCfa!wy?IgHn%plHn1jJYgxnAfE7_`jkVgWb}OUkt+y;U zER~jvmcK10E&DCMTXtK1wtQ#VYT3Zgddn)y=awaw&n$~A^DOf%?^|YB-my%#jI$J2 zMp^RtdD$|+(wCo}mTr~|O9#u7mPagYER8LxmSjs!OD&6G30OQ9zr|*WwOB3x4^@nE ANdN!< literal 0 HcmV?d00001 diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 0506840ec..264ffed09 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -271,14 +271,16 @@ QString NotificationItem::checkSoundExists(QString fileName) QStringList valueToSoundList(QString value) { - + qNotifyDebug()<<"notificationItem valueToSoundList input param"< Date: Thu, 15 Dec 2011 23:49:01 +0100 Subject: [PATCH 17/72] GCS:Scope: Backward Compatibility: Set Interpolation to minimum (1) when not set in config file --- .../openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp index 6337be38f..3228497f3 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetconfiguration.cpp @@ -66,6 +66,7 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* q plotCurveConf->color = color; plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt(); plotCurveConf->yInterpolationSamples = qSettings->value("yInterpolationSamples").toInt(); + if (!plotCurveConf->yInterpolationSamples) plotCurveConf->yInterpolationSamples = 1; // fallback for backward compatibility with earlier versions plotCurveConf->yMinimum = qSettings->value("yMinimum").toDouble(); plotCurveConf->yMaximum = qSettings->value("yMaximum").toDouble(); From 6c38114cfc7676ea4b7f3e0cdef3ee8c507cf75b Mon Sep 17 00:00:00 2001 From: naiiawah Date: Wed, 4 Jan 2012 21:39:23 -0700 Subject: [PATCH 18/72] Fixed borkage in the rules file where the if test was malformed. Added a change to force an error if the passed in ENV var is not defined. If that had been there, the borkage wouldn't have been undetected. Changed to only put the main FW in the firmware dir, instead of BL and FW. --- package/Makefile.linux | 2 +- package/linux/deb_common/rules | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) mode change 100755 => 100644 package/linux/deb_common/rules diff --git a/package/Makefile.linux b/package/Makefile.linux index fba2ef3ff..78e902d71 100644 --- a/package/Makefile.linux +++ b/package/Makefile.linux @@ -49,7 +49,7 @@ linux_deb_package: deb_build gcs deb_build: | $(DEB_BUILD_DIR) $(ALL_DEB_FILES) $(BUILD_DIR)/build @echo $@ starting - $(V1)$(shell echo $(PACKAGE_DIR) > $(BUILD_DIR)/package_dir) + $(V1)$(shell echo $(FW_DIR) > $(BUILD_DIR)/package_dir) $(V1)sed -i -e "$(SED_SCRIPT)" $(DEB_BUILD_DIR)/changelog $(BUILD_DIR)/build: package_flight diff --git a/package/linux/deb_common/rules b/package/linux/deb_common/rules old mode 100755 new mode 100644 index c4a7d9bd9..ba22c1e9c --- a/package/linux/deb_common/rules +++ b/package/linux/deb_common/rules @@ -43,8 +43,10 @@ install: cp -arp package/linux/openpilot_menu.png debian/openpilot/usr/share/pixmaps cp -arp package/linux/openpilot_menu.menu debian/openpilot/etc/xdg/menus/applications-merged cp -arp package/linux/openpilot_menu.directory debian/openpilot/usr/share/desktop-directories -ifdef $(PACKAGE_DIR) - cp -ar $(PACKAGE_DIR)/* debian/openpilot/usr/local/OpenPilot/firmware/ +ifdef PACKAGE_DIR + cp -a $(PACKAGE_DIR)/*.opfw debian/openpilot/usr/local/OpenPilot/firmware/ +else + $(error PACKAGE_DIR not defined! $(PACKAGE_DIR)) endif ln -s /usr/local/OpenPilot/bin/openpilotgcs.bin `pwd`/debian/openpilot/usr/bin/openpilot-gcs rm -rf debian/openpilot/usr/local/OpenPilot/share/openpilotgcs/sounds/sounds From 0ce95839ca1b1ccb8f48466aee1f0e335db64964 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 7 Jan 2012 17:28:00 -0500 Subject: [PATCH 19/72] stm32flash: Upgrade to revision 61 to support STM32F4 CPU --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 438f697a4..72adb05be 100644 --- a/Makefile +++ b/Makefile @@ -235,7 +235,7 @@ STM32FLASH_DIR := $(TOOLS_DIR)/stm32flash .PHONY: stm32flash_install stm32flash_install: STM32FLASH_URL := http://stm32flash.googlecode.com/svn/trunk -stm32flash_install: STM32FLASH_REV := 52 +stm32flash_install: STM32FLASH_REV := 61 stm32flash_install: stm32flash_clean # download the source $(V0) @echo " DOWNLOAD $(STM32FLASH_URL) @ r$(STM32FLASH_REV)" From 9f2b71a3518d1e848e0f556a3e1914a2d0968656 Mon Sep 17 00:00:00 2001 From: zedamota Date: Mon, 9 Jan 2012 14:06:27 +0000 Subject: [PATCH 20/72] Convert filename to lowercase --- .../src/plugins/notify/{NotificationItem.h => notificationitem.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ground/openpilotgcs/src/plugins/notify/{NotificationItem.h => notificationitem.h} (100%) diff --git a/ground/openpilotgcs/src/plugins/notify/NotificationItem.h b/ground/openpilotgcs/src/plugins/notify/notificationitem.h similarity index 100% rename from ground/openpilotgcs/src/plugins/notify/NotificationItem.h rename to ground/openpilotgcs/src/plugins/notify/notificationitem.h From 38392ee6389c19cf83acc11341b5fe52f8e080be Mon Sep 17 00:00:00 2001 From: zedamota Date: Mon, 9 Jan 2012 16:09:50 +0000 Subject: [PATCH 21/72] several fixes to the notify plugin --- .../openpilotgcs/src/plugins/notify/notificationitem.cpp | 2 ++ ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp | 9 ++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp index 264ffed09..a54e7ff89 100644 --- a/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notificationitem.cpp @@ -333,6 +333,8 @@ QStringList valueToSoundList(QString value) QString stringFromValue(QVariant value, UAVObjectField* field) { + if(field==NULL) + return ""; Q_ASSERT(field); Q_ASSERT(!value.isNull()); QString str; diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 9acb4b6f3..6f74ec018 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -256,13 +256,6 @@ void SoundNotifyPlugin::on_arrived_Notification(UAVObject *object) .arg(ntf->singleValue().toString()) .arg(ntf->valueRange2()); - QString fieldName = ntf->getObjectField(); - UAVObjectField* field = object->getField(fieldName); - - qNotifyDebug() << QString("UAV object: %1 | value: %2") - .arg(object->getName()) - .arg(field->getValue().toString()); - checkNotificationRule(ntf, object); } connect(object, SIGNAL(objectUpdated(UAVObject*)), @@ -402,6 +395,8 @@ bool checkRange(double fieldValue, double min, double max, int direction) void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) { + if(notification->getDataObject()!=object->getName() | object->getField(notification->getObjectField())==NULL) + return; bool condition=false; if (notification->mute()) From 00cb66ae79ae8842b003f6067542d0371433da63 Mon Sep 17 00:00:00 2001 From: zedamota Date: Mon, 9 Jan 2012 16:35:35 +0000 Subject: [PATCH 22/72] OpenPilot OP-602 Please add a Help button on the Firmware page --- .../src/plugins/uploader/uploader.ui | 46 ++++++++++++++----- .../plugins/uploader/uploadergadgetwidget.cpp | 6 +++ .../plugins/uploader/uploadergadgetwidget.h | 2 + 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader.ui b/ground/openpilotgcs/src/plugins/uploader/uploader.ui index b0dffd4a0..540d69302 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploader.ui +++ b/ground/openpilotgcs/src/plugins/uploader/uploader.ui @@ -6,7 +6,7 @@ 0 0 - 580 + 583 350 @@ -144,6 +144,26 @@ halting a running board. + + + + + + + + :/core/images/helpicon.svg:/core/images/helpicon.svg + + + + 30 + 30 + + + + true + + + @@ -166,14 +186,14 @@ halting a running board. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To upgrade the firmware in your boards, proceed as follows:</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Connect telemetry</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Once telemetry is running, press &quot;Halt&quot; above</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- You will get a list of devices.</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- You can then upload/download to/from each board as you wish</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- You can resume operations by pressing &quot;Boot&quot;</p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">To upgrade the firmware in your boards, proceed as follows:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">- Connect telemetry</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">- Once telemetry is running, press &quot;Halt&quot; above</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">- You will get a list of devices.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">- You can then upload/download to/from each board as you wish</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:11pt;">- You can resume operations by pressing &quot;Boot&quot;</span></p></body></html> @@ -188,14 +208,16 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;"></p></body></html> - + + + diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 182753b24..851334c86 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -64,6 +64,7 @@ UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent) connect(m_config->refreshPorts, SIGNAL(clicked()), this, SLOT(getSerialPorts())); + connect(m_config->pbHelp,SIGNAL(clicked()),this,SLOT(openHelp())); // And check whether by any chance we are not already connected if (telMngr->isConnected()) { @@ -650,3 +651,8 @@ void UploaderGadgetWidget::versionMatchCheck() QString(tr("FW Versions: ")) + boardDescription.gitTag+":"+boardDescription.buildDate); } } +void UploaderGadgetWidget::openHelp() +{ + + QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Uploader+Plugin", QUrl::StrictMode) ); +} diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index 998166d69..2c6814827 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -55,6 +55,7 @@ #include "devicedescriptorstruct.h" #include #include +#include using namespace OP_DFU; @@ -74,6 +75,7 @@ public slots: void onAutopilotConnect(); void onAutopilotDisconnect(); void populate(); + void openHelp(); private: Ui_UploaderWidget *m_config; DFUObject *dfu; From dbd9fcda281974cdbe5392da5c18d078a1a49fb4 Mon Sep 17 00:00:00 2001 From: zedamota Date: Mon, 9 Jan 2012 16:53:59 +0000 Subject: [PATCH 23/72] OpenPilot OP-611 disable Flash button during operation --- ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp index 9e57a4225..cf4315596 100644 --- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp @@ -358,8 +358,10 @@ void deviceWidget::loadFirmware() */ void deviceWidget::uploadFirmware() { + myDevice->updateButton->setEnabled(false); if (!m_dfu->devices[deviceID].Writable) { status("Device not writable!", STATUSICON_FAIL); + myDevice->updateButton->setEnabled(true); return; } @@ -378,6 +380,7 @@ void deviceWidget::uploadFirmware() int firmwareBoard = ((desc.at(12)&0xff)<<8) + (desc.at(13)&0xff); if (firmwareBoard != board) { status("Error: firmware does not match board", STATUSICON_FAIL); + myDevice->updateButton->setEnabled(true); return; } // Check the firmware embedded in the file: @@ -385,6 +388,7 @@ void deviceWidget::uploadFirmware() QByteArray fileHash = QCryptographicHash::hash(loadedFW.left(loadedFW.length()-100), QCryptographicHash::Sha1); if (firmwareHash != fileHash) { status("Error: firmware file corrupt", STATUSICON_FAIL); + myDevice->updateButton->setEnabled(true); return; } } else { @@ -400,6 +404,7 @@ void deviceWidget::uploadFirmware() if(!m_dfu->enterDFU(deviceID)) { status("Error:Could not enter DFU mode", STATUSICON_FAIL); + myDevice->updateButton->setEnabled(true); return; } OP_DFU::Status ret=m_dfu->StatusRequest(); @@ -412,6 +417,7 @@ void deviceWidget::uploadFirmware() bool retstatus = m_dfu->UploadFirmware(filename,verify, deviceID); if(!retstatus ) { status("Could not start upload", STATUSICON_FAIL); + myDevice->updateButton->setEnabled(true); return; } status("Uploading, please wait...", STATUSICON_RUNNING); @@ -465,6 +471,7 @@ void deviceWidget::downloadFinished() */ void deviceWidget::uploadFinished(OP_DFU::Status retstatus) { + myDevice->updateButton->setEnabled(true); disconnect(m_dfu, SIGNAL(uploadFinished(OP_DFU::Status)), this, SLOT(uploadFinished(OP_DFU::Status))); disconnect(m_dfu, SIGNAL(progressUpdated(int)), this, SLOT(setProgress(int))); disconnect(m_dfu, SIGNAL(operationProgress(QString)), this, SLOT(dfuStatus(QString))); From 63bb2874d732654180ca9126b6b3c53b17aa88fb Mon Sep 17 00:00:00 2001 From: zedamota Date: Tue, 10 Jan 2012 17:03:58 +0000 Subject: [PATCH 24/72] OP-608 Camera Stabilization settings not being read from CC board into GCS if CC is started first. Created connection callback only to be called after all plugins are loaded. --- .../src/libs/extensionsystem/pluginmanager.cpp | 4 +++- .../src/libs/extensionsystem/pluginmanager.h | 4 +++- .../plugins/coreplugin/connectionmanager.cpp | 17 +++++++++++++++++ .../src/plugins/coreplugin/connectionmanager.h | 3 ++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.cpp b/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.cpp index edd65d3ce..d8e637802 100644 --- a/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.cpp +++ b/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.cpp @@ -177,7 +177,7 @@ PluginManager *PluginManager::instance() Create a plugin manager. Should be done only once per application. */ PluginManager::PluginManager() - : d(new PluginManagerPrivate(this)) + : d(new PluginManagerPrivate(this)),m_allPluginsLoaded(false) { m_instance = this; } @@ -586,6 +586,8 @@ void PluginManagerPrivate::loadPlugins() loadPlugin(it.previous(), PluginSpec::Running); } emit q->pluginsChanged(); + q->m_allPluginsLoaded=true; + emit q->pluginsLoadEnded(); } /*! diff --git a/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.h b/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.h index 6182b388e..49bcd5c55 100644 --- a/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.h +++ b/ground/openpilotgcs/src/libs/extensionsystem/pluginmanager.h @@ -56,7 +56,7 @@ class EXTENSIONSYSTEM_EXPORT PluginManager : public QObject public: static PluginManager *instance(); - + bool allPluginsLoaded(){return m_allPluginsLoaded;} PluginManager(); virtual ~PluginManager(); @@ -115,6 +115,7 @@ signals: void aboutToRemoveObject(QObject *obj); void pluginsChanged(); + void pluginsLoadEnded(); private slots: void startTests(); @@ -122,6 +123,7 @@ private: Internal::PluginManagerPrivate *d; static PluginManager *m_instance; mutable QReadWriteLock m_lock; + bool m_allPluginsLoaded; friend class Internal::PluginManagerPrivate; }; diff --git a/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.cpp b/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.cpp index 9dfa46518..f49d98c0e 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace Core { @@ -333,6 +334,12 @@ void ConnectionManager::registerDevice(IConnection *conn, const QString &devN, c */ void ConnectionManager::devChanged(IConnection *connection) { + if(!ExtensionSystem::PluginManager::instance()->allPluginsLoaded()) + { + connectionBackup.append(connection); + connect(ExtensionSystem::PluginManager::instance(),SIGNAL(pluginsLoadEnded()),this,SLOT(connectionsCallBack()),Qt::UniqueConnection); + return; + } //clear device list combobox m_availableDevList->clear(); @@ -381,4 +388,14 @@ void ConnectionManager::devChanged(IConnection *connection) m_connectBtn->setEnabled(false); } +} + +void Core::ConnectionManager::connectionsCallBack() +{ + foreach(IConnection * con,connectionBackup) + { + devChanged(con); + } + connectionBackup.clear(); + disconnect(ExtensionSystem::PluginManager::instance(),SIGNAL(pluginsLoadEnded()),this,SLOT(connectionsCallBack())); } //namespace Core diff --git a/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.h b/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.h index beb809915..289e65590 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.h +++ b/ground/openpilotgcs/src/plugins/coreplugin/connectionmanager.h @@ -98,7 +98,7 @@ private slots: // void onConnectionClosed(QObject *obj); void onConnectionDestroyed(QObject *obj); - + void connectionsCallBack(); //used to call devChange after all the plugins are loaded protected: QComboBox *m_availableDevList; QPushButton *m_connectBtn; @@ -114,6 +114,7 @@ protected: private: bool connectDevice(); Internal::MainWindow *m_mainWindow; + QList connectionBackup; }; From 1b314ee256eb584db81865b332b5277ce440bddb Mon Sep 17 00:00:00 2001 From: Michael Rumpler Date: Wed, 11 Jan 2012 22:16:26 +0100 Subject: [PATCH 25/72] * cleaned up notifyplugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cause: /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp:104:6: warning: unused parameter ‘configInfo’ [-Wunused-parameter] /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp:353:6: warning: unused parameter ‘values’ [-Wunused-parameter] /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp:73:10: warning: unused parameter ‘parent’ [-Wunused-parameter] /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp:451:6: warning: unused parameter ‘rangeStr’ [-Wunused-parameter] /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp:512:7: warning: unused parameter ‘oldstate’ [-Wunused-parameter] /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp:527:6: warning: unused parameter ‘deselected’ [-Wunused-parameter] implemented solution: fixed all of them (commented out var name) * fixed bug in check code cause: /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp: In member function ‘void SoundNotifyPlugin::checkNotificationRule(NotificationItem*, UAVObject*)’: /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp:398:109: warning: suggest parentheses around comparison in operand of ‘|’ [-Wparentheses] implemented solution: this is an obvious bug that is syntactically correct but leads to a warning with a good compiler so this bug can be found. fixed that to use logical or instead of bitwise or. * fixed bug in include file (error in compilation under Linux) cause: In file included from /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp:47:0: /projects/OpenPilot/git/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h:86:39: error: reference ‘_list’ cannot be declared ‘mutable’ [-fpermissive] implemented solution: removed the mutable flag, as this is wrongly used on a reference (and therefore correctly causing a compile-time error --- ground/openpilotgcs/src/plugins/notify/notifylogging.h | 2 +- ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp | 6 +++--- .../src/plugins/notify/notifypluginoptionspage.cpp | 8 ++++---- ground/openpilotgcs/src/plugins/notify/notifytablemodel.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/notifylogging.h b/ground/openpilotgcs/src/plugins/notify/notifylogging.h index ea7ea331c..43e54f3b7 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifylogging.h +++ b/ground/openpilotgcs/src/plugins/notify/notifylogging.h @@ -29,7 +29,7 @@ #ifndef NOTIFYLOGGING_H #define NOTIFYLOGGING_H -#include "QDebug.h" +#include "qdebug.h" #define DEBUG_NOTIFIES_ENABLE diff --git a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp index 6f74ec018..5c7d27e75 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifyplugin.cpp @@ -101,7 +101,7 @@ void SoundNotifyPlugin::saveConfig( QSettings* settings, UAVConfigInfo *configIn } -void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo *configInfo) +void SoundNotifyPlugin::readConfig( QSettings* settings, UAVConfigInfo * /* configInfo */) { // Just for migration to the new format. //Q_ASSERT(configInfo->version() == UAVConfigVersion()); @@ -350,7 +350,7 @@ void SoundNotifyPlugin::stateChanged(Phonon::State newstate, Phonon::State oldst } } -bool checkRange(QString fieldValue, QString enumValue, QStringList values, int direction) +bool checkRange(QString fieldValue, QString enumValue, QStringList /* values */, int direction) { bool ret = false; @@ -395,7 +395,7 @@ bool checkRange(double fieldValue, double min, double max, int direction) void SoundNotifyPlugin::checkNotificationRule(NotificationItem* notification, UAVObject* object) { - if(notification->getDataObject()!=object->getName() | object->getField(notification->getObjectField())==NULL) + if(notification->getDataObject()!=object->getName() || object->getField(notification->getObjectField())==NULL) return; bool condition=false; diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp index b7cc977c6..fa8ff053f 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.cpp @@ -70,7 +70,7 @@ NotifyPluginOptionsPage::NotifyPluginOptionsPage(QObject *parent) NotifyPluginOptionsPage::~NotifyPluginOptionsPage() {} -QWidget *NotifyPluginOptionsPage::createPage(QWidget *parent) +QWidget *NotifyPluginOptionsPage::createPage(QWidget * /* parent */) { _optionsPage.reset(new Ui::NotifyPluginOptionsPage()); //main widget @@ -448,7 +448,7 @@ void NotifyPluginOptionsPage::updateConfigView(NotificationItem* notification) } -void NotifyPluginOptionsPage::on_changedIndex_rangeValue(QString rangeStr) +void NotifyPluginOptionsPage::on_changedIndex_rangeValue(QString /* rangeStr */) { Q_ASSERT(_dynamicFieldWidget); UAVObjectField* field = getObjectFieldFromSelected(); @@ -509,7 +509,7 @@ void NotifyPluginOptionsPage::on_changedIndex_soundLanguage(int index) } -void NotifyPluginOptionsPage::on_changed_playButtonText(Phonon::State newstate, Phonon::State oldstate) +void NotifyPluginOptionsPage::on_changed_playButtonText(Phonon::State newstate, Phonon::State /* oldstate */) { //Q_ASSERT(Phonon::ErrorState != newstate); @@ -524,7 +524,7 @@ void NotifyPluginOptionsPage::on_changed_playButtonText(Phonon::State newstate, } } -void NotifyPluginOptionsPage::on_changedSelection_notifyTable(const QItemSelection & selected, const QItemSelection & deselected ) +void NotifyPluginOptionsPage::on_changedSelection_notifyTable(const QItemSelection & selected, const QItemSelection & /* deselected */ ) { bool select = false; _testSound->stop(); diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h index 28eb8cc68..dd2e765bd 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.h @@ -83,7 +83,7 @@ private slots: void dropRows(int position, int count) const; private: - mutable QList& _list; + QList& _list; QStringList _headerStrings; }; From 2d27c54d4805a62e51321d390998978090ec2e68 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Thu, 12 Jan 2012 19:53:52 -0500 Subject: [PATCH 26/72] com_msg: Create new message based COM layer for bootloaders The main purpose of this new COM implementation is that it is much simpler, and requires less code space. This takes a bit of the pressure off of the CC bootloader which was right at the limit of available code space in the bootloader partition. This is not intended to ever be used by the application. This driver also formalizes the assumptions in the bootloader's usage of the COM layer. All messages are assumed to arrive in atomic chunks from the HID layer. --- flight/Bootloaders/CopterControl/Makefile | 2 +- .../CopterControl/inc/pios_config.h | 2 +- flight/Bootloaders/CopterControl/main.c | 5 +- flight/Bootloaders/CopterControl/op_dfu.c | 5 +- flight/Bootloaders/CopterControl/pios_board.c | 20 +- flight/Bootloaders/OpenPilot/Makefile | 1 + .../Bootloaders/OpenPilot/inc/pios_config.h | 1 + flight/Bootloaders/OpenPilot/main.c | 5 +- flight/Bootloaders/OpenPilot/op_dfu.c | 9 +- flight/Bootloaders/OpenPilot/pios_board.c | 24 +-- flight/Bootloaders/PipXtreme/Makefile | 2 +- .../Bootloaders/PipXtreme/inc/pios_config.h | 2 +- flight/Bootloaders/PipXtreme/main.c | 5 +- flight/Bootloaders/PipXtreme/op_dfu.c | 30 +-- flight/Bootloaders/PipXtreme/pios_board.c | 25 +-- flight/PiOS/Common/pios_com_msg.c | 185 ++++++++++++++++++ flight/PiOS/STM32F10x/pios_usb_hid.c | 18 +- flight/PiOS/inc/pios_com.h | 4 +- flight/PiOS/inc/pios_com_msg.h | 45 +++++ flight/PiOS/inc/pios_com_msg_priv.h | 44 +++++ flight/PiOS/inc/pios_com_priv.h | 2 + 21 files changed, 345 insertions(+), 91 deletions(-) create mode 100644 flight/PiOS/Common/pios_com_msg.c create mode 100644 flight/PiOS/inc/pios_com_msg.h create mode 100644 flight/PiOS/inc/pios_com_msg_priv.h diff --git a/flight/Bootloaders/CopterControl/Makefile b/flight/Bootloaders/CopterControl/Makefile index 1257ed579..a5effde9c 100644 --- a/flight/Bootloaders/CopterControl/Makefile +++ b/flight/Bootloaders/CopterControl/Makefile @@ -116,7 +116,7 @@ SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_board_info.c -SRC += $(PIOSCOMMON)/pios_com.c +SRC += $(PIOSCOMMON)/pios_com_msg.c SRC += $(PIOSCOMMON)/pios_bl_helper.c SRC += $(PIOSCOMMON)/pios_iap.c SRC += $(PIOSCOMMON)/printf-stdarg.c diff --git a/flight/Bootloaders/CopterControl/inc/pios_config.h b/flight/Bootloaders/CopterControl/inc/pios_config.h index 081ed1b0f..864ed4665 100644 --- a/flight/Bootloaders/CopterControl/inc/pios_config.h +++ b/flight/Bootloaders/CopterControl/inc/pios_config.h @@ -39,7 +39,7 @@ #define PIOS_INCLUDE_SYS #define PIOS_INCLUDE_USB #define PIOS_INCLUDE_USB_HID -#define PIOS_INCLUDE_COM +#define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO #define PIOS_NO_GPS diff --git a/flight/Bootloaders/CopterControl/main.c b/flight/Bootloaders/CopterControl/main.c index c1def4a46..7a61ae9e9 100644 --- a/flight/Bootloaders/CopterControl/main.c +++ b/flight/Bootloaders/CopterControl/main.c @@ -32,6 +32,7 @@ #include "usb_lib.h" #include "pios_iap.h" #include "fifo_buffer.h" +#include "pios_com_msg.h" /* Prototype of PIOS_Board_Init() function */ extern void PIOS_Board_Init(void); extern void FLASH_Download(); @@ -62,7 +63,7 @@ uint8_t JumpToApp = FALSE; uint8_t GO_dfu = FALSE; uint8_t USB_connected = FALSE; uint8_t User_DFU_request = FALSE; -static uint8_t mReceive_Buffer[64]; +static uint8_t mReceive_Buffer[63]; /* Private function prototypes -----------------------------------------------*/ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count); uint8_t processRX(); @@ -198,7 +199,7 @@ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count) { } uint8_t processRX() { - if (PIOS_COM_ReceiveBuffer(PIOS_COM_TELEM_USB, mReceive_Buffer, 63, 0) == 63) { + if (PIOS_COM_MSG_Receive(PIOS_COM_TELEM_USB, mReceive_Buffer, sizeof(mReceive_Buffer))) { processComand(mReceive_Buffer); } return TRUE; diff --git a/flight/Bootloaders/CopterControl/op_dfu.c b/flight/Bootloaders/CopterControl/op_dfu.c index ae85160c2..9f98d3394 100644 --- a/flight/Bootloaders/CopterControl/op_dfu.c +++ b/flight/Bootloaders/CopterControl/op_dfu.c @@ -30,6 +30,7 @@ #include "pios.h" #include "op_dfu.h" #include "pios_bl_helper.h" +#include "pios_com_msg.h" #include //programmable devices Device devicesTable[10]; @@ -446,9 +447,7 @@ uint32_t CalcFirmCRC() { } void sendData(uint8_t * buf, uint16_t size) { - PIOS_COM_SendBuffer(PIOS_COM_TELEM_USB, buf, size); - if (DeviceState == downloading) - PIOS_DELAY_WaitmS(20);//this is an hack, we should check wtf is wrong with hid + PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB, buf, size); } bool flash_read(uint8_t * buffer, uint32_t adr, DFUProgType type) { diff --git a/flight/Bootloaders/CopterControl/pios_board.c b/flight/Bootloaders/CopterControl/pios_board.c index 1b3c54af3..972a85be0 100644 --- a/flight/Bootloaders/CopterControl/pios_board.c +++ b/flight/Bootloaders/CopterControl/pios_board.c @@ -27,17 +27,11 @@ // *********************************************************************************** -#if defined(PIOS_INCLUDE_COM) +#if defined(PIOS_INCLUDE_COM_MSG) -#include +#include -#define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 -#define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 - -static uint8_t pios_com_telem_usb_rx_buffer[PIOS_COM_TELEM_USB_RX_BUF_LEN]; -static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN]; - -#endif /* PIOS_INCLUDE_COM */ +#endif /* PIOS_INCLUDE_COM_MSG */ // *********************************************************************************** @@ -97,17 +91,15 @@ void PIOS_Board_Init(void) { if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); } -#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) +#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM_MSG) uint32_t pios_usb_hid_id; if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { PIOS_Assert(0); } - if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, - pios_com_telem_usb_rx_buffer, sizeof(pios_com_telem_usb_rx_buffer), - pios_com_telem_usb_tx_buffer, sizeof(pios_com_telem_usb_tx_buffer))) { + if (PIOS_COM_MSG_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id)) { PIOS_Assert(0); } -#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */ +#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM_MSG */ #endif /* PIOS_INCLUDE_USB */ diff --git a/flight/Bootloaders/OpenPilot/Makefile b/flight/Bootloaders/OpenPilot/Makefile index e9b55e134..6c3888797 100644 --- a/flight/Bootloaders/OpenPilot/Makefile +++ b/flight/Bootloaders/OpenPilot/Makefile @@ -119,6 +119,7 @@ SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_board_info.c +SRC += $(PIOSCOMMON)/pios_com_msg.c SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_opahrs_v0.c SRC += $(PIOSCOMMON)/pios_bl_helper.c diff --git a/flight/Bootloaders/OpenPilot/inc/pios_config.h b/flight/Bootloaders/OpenPilot/inc/pios_config.h index 024bcae9a..cf8981339 100644 --- a/flight/Bootloaders/OpenPilot/inc/pios_config.h +++ b/flight/Bootloaders/OpenPilot/inc/pios_config.h @@ -42,6 +42,7 @@ #define PIOS_INCLUDE_USB_HID #define PIOS_INCLUDE_OPAHRS #define PIOS_INCLUDE_COM +#define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO //#define DEBUG_SSP diff --git a/flight/Bootloaders/OpenPilot/main.c b/flight/Bootloaders/OpenPilot/main.c index 48056cff6..8a9e554ef 100644 --- a/flight/Bootloaders/OpenPilot/main.c +++ b/flight/Bootloaders/OpenPilot/main.c @@ -35,6 +35,7 @@ #include "pios_iap.h" #include "ssp.h" #include "fifo_buffer.h" +#include "pios_com_msg.h" /* Prototype of PIOS_Board_Init() function */ extern void PIOS_Board_Init(void); extern void FLASH_Download(); @@ -90,7 +91,7 @@ uint8_t JumpToApp = FALSE; uint8_t GO_dfu = FALSE; uint8_t USB_connected = FALSE; uint8_t User_DFU_request = FALSE; -static uint8_t mReceive_Buffer[64]; +static uint8_t mReceive_Buffer[63]; /* Private function prototypes -----------------------------------------------*/ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count); uint8_t processRX(); @@ -249,7 +250,7 @@ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count) { uint8_t processRX() { if (ProgPort == Usb) { - if (PIOS_COM_ReceiveBuffer(PIOS_COM_TELEM_USB, mReceive_Buffer, 63, 0) == 63) { + if (PIOS_COM_MSG_Receive(PIOS_COM_TELEM_USB, mReceive_Buffer, sizeof(mReceive_Buffer))) { processComand(mReceive_Buffer); } } else if (ProgPort == Serial) { diff --git a/flight/Bootloaders/OpenPilot/op_dfu.c b/flight/Bootloaders/OpenPilot/op_dfu.c index bc62fff6c..ad5836ad7 100644 --- a/flight/Bootloaders/OpenPilot/op_dfu.c +++ b/flight/Bootloaders/OpenPilot/op_dfu.c @@ -30,6 +30,7 @@ #include "pios.h" #include "op_dfu.h" #include "pios_bl_helper.h" +#include "pios_com_msg.h" #include #include "pios_opahrs.h" #include "ssp.h" @@ -299,7 +300,6 @@ void processComand(uint8_t *xReceive_Buffer) { ++Next_Packet; } else { - DeviceState = wrong_packet_received; Aditionals = Count; } @@ -508,6 +508,7 @@ uint32_t baseOfAdressType(DFUTransfer type) { return currentDevice.startOfUserCode + currentDevice.sizeOfCode; break; default: + return 0; } } @@ -550,11 +551,7 @@ uint32_t CalcFirmCRC() { } void sendData(uint8_t * buf, uint16_t size) { if (ProgPort == Usb) { - - PIOS_COM_SendBuffer(PIOS_COM_TELEM_USB, buf, size); - if (DeviceState == downloading) - PIOS_DELAY_WaitmS(10); - + PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB, buf, size); } else if (ProgPort == Serial) { ssp_SendData(&ssp_port, buf, size); } diff --git a/flight/Bootloaders/OpenPilot/pios_board.c b/flight/Bootloaders/OpenPilot/pios_board.c index a2630815a..707600b4d 100644 --- a/flight/Bootloaders/OpenPilot/pios_board.c +++ b/flight/Bootloaders/OpenPilot/pios_board.c @@ -184,12 +184,6 @@ const struct pios_usart_cfg pios_usart_telem_cfg = { #include "pios_com_priv.h" -#define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 -#define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 - -static uint8_t pios_com_telem_usb_rx_buffer[PIOS_COM_TELEM_USB_RX_BUF_LEN]; -static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN]; - #define PIOS_COM_TELEM_RF_RX_BUF_LEN 192 #define PIOS_COM_TELEM_RF_TX_BUF_LEN 192 @@ -198,6 +192,16 @@ static uint8_t pios_com_telem_rf_tx_buffer[PIOS_COM_TELEM_RF_TX_BUF_LEN]; #endif /* PIOS_INCLUDE_COM */ +// *********************************************************************************** + +#if defined(PIOS_INCLUDE_COM_MSG) + +#include + +#endif /* PIOS_INCLUDE_COM_MSG */ + +// *********************************************************************************** + #if defined(PIOS_INCLUDE_USB) #include "pios_usb_priv.h" @@ -270,17 +274,15 @@ void PIOS_Board_Init(void) { if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); } -#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) +#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM_MSG) uint32_t pios_usb_hid_id; if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { PIOS_Assert(0); } - if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, - pios_com_telem_usb_rx_buffer, sizeof(pios_com_telem_usb_rx_buffer), - pios_com_telem_usb_tx_buffer, sizeof(pios_com_telem_usb_tx_buffer))) { + if (PIOS_COM_MSG_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id)) { PIOS_Assert(0); } -#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */ +#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM_MSG */ #endif /* PIOS_INCLUDE_USB */ diff --git a/flight/Bootloaders/PipXtreme/Makefile b/flight/Bootloaders/PipXtreme/Makefile index af6469ae0..9bad695f7 100644 --- a/flight/Bootloaders/PipXtreme/Makefile +++ b/flight/Bootloaders/PipXtreme/Makefile @@ -115,7 +115,7 @@ SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_board_info.c -SRC += $(PIOSCOMMON)/pios_com.c +SRC += $(PIOSCOMMON)/pios_com_msg.c SRC += $(PIOSCOMMON)/pios_bl_helper.c SRC += $(PIOSCOMMON)/pios_iap.c SRC += $(PIOSCOMMON)/printf-stdarg.c diff --git a/flight/Bootloaders/PipXtreme/inc/pios_config.h b/flight/Bootloaders/PipXtreme/inc/pios_config.h index 0c2cc7877..8084f9c0a 100644 --- a/flight/Bootloaders/PipXtreme/inc/pios_config.h +++ b/flight/Bootloaders/PipXtreme/inc/pios_config.h @@ -38,7 +38,7 @@ #define PIOS_INCLUDE_SYS #define PIOS_INCLUDE_USB #define PIOS_INCLUDE_USB_HID -#define PIOS_INCLUDE_COM +#define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO //#define DEBUG_SSP diff --git a/flight/Bootloaders/PipXtreme/main.c b/flight/Bootloaders/PipXtreme/main.c index f09881d42..4923f8fc1 100644 --- a/flight/Bootloaders/PipXtreme/main.c +++ b/flight/Bootloaders/PipXtreme/main.c @@ -32,6 +32,7 @@ #include "usb_lib.h" #include "pios_iap.h" #include "fifo_buffer.h" +#include "pios_com_msg.h" /* Prototype of PIOS_Board_Init() function */ extern void PIOS_Board_Init(void); extern void FLASH_Download(); @@ -62,7 +63,7 @@ uint8_t JumpToApp = FALSE; uint8_t GO_dfu = FALSE; uint8_t USB_connected = FALSE; uint8_t User_DFU_request = FALSE; -static uint8_t mReceive_Buffer[64]; +static uint8_t mReceive_Buffer[63]; /* Private function prototypes -----------------------------------------------*/ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count); uint8_t processRX(); @@ -204,7 +205,7 @@ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count) { } uint8_t processRX() { - if (PIOS_COM_ReceiveBuffer(PIOS_COM_TELEM_USB, mReceive_Buffer, 63, 0) == 63) { + if (PIOS_COM_MSG_Receive(PIOS_COM_TELEM_USB, mReceive_Buffer, sizeof(mReceive_Buffer))) { processComand(mReceive_Buffer); } return TRUE; diff --git a/flight/Bootloaders/PipXtreme/op_dfu.c b/flight/Bootloaders/PipXtreme/op_dfu.c index 770ce8237..cdc2d82b8 100644 --- a/flight/Bootloaders/PipXtreme/op_dfu.c +++ b/flight/Bootloaders/PipXtreme/op_dfu.c @@ -30,6 +30,7 @@ #include "pios.h" #include "op_dfu.h" #include "pios_bl_helper.h" +#include "pios_com_msg.h" #include /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ @@ -102,33 +103,9 @@ void DataDownload(DownloadAction action) { currentProgrammingDestination)) { DeviceState = Last_operation_failed; } - /* - switch (currentProgrammingDestination) { - case Remote_flash_via_spi: - if (downType == Descript) { - SendBuffer[6 + (x * 4)] - = spi_dev_desc[(uint8_t) partoffset]; - SendBuffer[7 + (x * 4)] = spi_dev_desc[(uint8_t) partoffset - + 1]; - SendBuffer[8 + (x * 4)] = spi_dev_desc[(uint8_t) partoffset - + 2]; - SendBuffer[9 + (x * 4)] = spi_dev_desc[(uint8_t) partoffset - + 3]; - } - break; - case Self_flash: - SendBuffer[6 + (x * 4)] = *PIOS_BL_HELPER_FLASH_If_Read(offset); - SendBuffer[7 + (x * 4)] = *PIOS_BL_HELPER_FLASH_If_Read(offset + 1); - SendBuffer[8 + (x * 4)] = *PIOS_BL_HELPER_FLASH_If_Read(offset + 2); - SendBuffer[9 + (x * 4)] = *PIOS_BL_HELPER_FLASH_If_Read(offset + 3); - break; - } - */ } - //PIOS USB_SIL_Write(EP1_IN, (uint8_t*) SendBuffer, 64); downPacketCurrent = downPacketCurrent + 1; if (downPacketCurrent > downPacketTotal - 1) { - // STM_EVAL_LEDOn(LED2); DeviceState = Last_operation_Success; Aditionals = (uint32_t) Download; } @@ -322,7 +299,6 @@ void processComand(uint8_t *xReceive_Buffer) { Buffer[15] = devicesTable[Data0 - 1].devID; } sendData(Buffer + 1, 63); - //PIOS_COM_SendBuffer(PIOS_COM_TELEM_USB, Buffer + 1, 63);//FIX+1 break; case JumpFW: FLASH_Lock(); @@ -474,9 +450,7 @@ uint32_t CalcFirmCRC() { } void sendData(uint8_t * buf, uint16_t size) { - PIOS_COM_SendBuffer(PIOS_COM_TELEM_USB, buf, size); - if (DeviceState == downloading) - PIOS_DELAY_WaitmS(10); + PIOS_COM_MSG_Send(PIOS_COM_TELEM_USB, buf, size); } bool flash_read(uint8_t * buffer, uint32_t adr, DFUProgType type) { diff --git a/flight/Bootloaders/PipXtreme/pios_board.c b/flight/Bootloaders/PipXtreme/pios_board.c index abf079340..3c06d820b 100644 --- a/flight/Bootloaders/PipXtreme/pios_board.c +++ b/flight/Bootloaders/PipXtreme/pios_board.c @@ -27,17 +27,11 @@ // *********************************************************************************** -#if defined(PIOS_INCLUDE_COM) +#if defined(PIOS_INCLUDE_COM_MSG) -#include +#include -#define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 -#define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 - -static uint8_t pios_com_telem_usb_rx_buffer[PIOS_COM_TELEM_USB_RX_BUF_LEN]; -static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN]; - -#endif /* PIOS_INCLUDE_COM */ +#endif /* PIOS_INCLUDE_COM_MSG */ // *********************************************************************************** @@ -98,17 +92,16 @@ void PIOS_Board_Init(void) { if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); } -#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) - uint32_t pios_usb_com_id; - if (PIOS_USB_HID_Init(&pios_usb_com_id, &pios_usb_hid_cfg, pios_usb_id)) { +#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM_MSG) + uint32_t pios_usb_hid_id; + if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { PIOS_Assert(0); } - if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_com_id, - pios_com_telem_usb_rx_buffer, sizeof(pios_com_telem_usb_rx_buffer), - pios_com_telem_usb_tx_buffer, sizeof(pios_com_telem_usb_tx_buffer))) { + if (PIOS_COM_MSG_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id)) { PIOS_Assert(0); } -#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */ +#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM_MSG */ + #endif /* PIOS_INCLUDE_USB */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);//TODO Tirar diff --git a/flight/PiOS/Common/pios_com_msg.c b/flight/PiOS/Common/pios_com_msg.c new file mode 100644 index 000000000..c1cebe1d9 --- /dev/null +++ b/flight/PiOS/Common/pios_com_msg.c @@ -0,0 +1,185 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_COM COM MSG layer functions + * @brief Hardware communication layer + * @{ + * + * @file pios_com_msg.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief COM MSG layer functions + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Project Includes */ +#include "pios.h" + +#if defined(PIOS_INCLUDE_COM_MSG) + +#include "pios_com.h" + +#define PIOS_COM_MSG_MAX_LEN 63 + +struct pios_com_msg_dev { + uint32_t lower_id; + const struct pios_com_driver * driver; + + uint8_t rx_msg_buffer[PIOS_COM_MSG_MAX_LEN]; + volatile bool rx_msg_full; + + uint8_t tx_msg_buffer[PIOS_COM_MSG_MAX_LEN]; + volatile bool tx_msg_full; +}; + +static struct pios_com_msg_dev com_msg_dev; + +static uint16_t PIOS_COM_MSG_TxOutCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield); +static uint16_t PIOS_COM_MSG_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield); + +int32_t PIOS_COM_MSG_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id) +{ + PIOS_Assert(com_id); + PIOS_Assert(driver); + + PIOS_Assert(driver->bind_tx_cb); + PIOS_Assert(driver->bind_rx_cb); + + struct pios_com_msg_dev * com_dev = &com_msg_dev; + + com_dev->driver = driver; + com_dev->lower_id = lower_id; + + com_dev->rx_msg_full = false; + (com_dev->driver->bind_rx_cb)(lower_id, PIOS_COM_MSG_RxInCallback, (uint32_t)com_dev); + (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer)); + + com_dev->tx_msg_full = false; + (com_dev->driver->bind_tx_cb)(lower_id, PIOS_COM_MSG_TxOutCallback, (uint32_t)com_dev); + + *com_id = (uint32_t)com_dev; + return(0); +} + +static uint16_t PIOS_COM_MSG_TxOutCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield) +{ + struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)context; + + PIOS_Assert(buf); + PIOS_Assert(buf_len); + + uint16_t bytes_from_fifo = 0; + + if (com_dev->tx_msg_full && (buf_len >= sizeof(com_dev->tx_msg_buffer))) { + /* Room for an entire message, send it */ + memcpy(buf, com_dev->tx_msg_buffer, sizeof(com_dev->tx_msg_buffer)); + bytes_from_fifo = sizeof(com_dev->tx_msg_buffer); + com_dev->tx_msg_full = false; + } + + if (headroom) { + if (com_dev->tx_msg_full) { + *headroom = sizeof(com_dev->tx_msg_buffer); + } else { + *headroom = 0; + } + } + + return (bytes_from_fifo); +} + +static uint16_t PIOS_COM_MSG_RxInCallback(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield) +{ + struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)context; + + uint16_t bytes_into_fifo = 0; + + if (!com_dev->rx_msg_full && (buf_len >= sizeof(com_dev->rx_msg_buffer))) { + memcpy(com_dev->rx_msg_buffer, buf, sizeof(com_dev->rx_msg_buffer)); + bytes_into_fifo = sizeof(com_dev->rx_msg_buffer); + com_dev->rx_msg_full = true; + } + + if (headroom) { + if (!com_dev->rx_msg_full) { + *headroom = sizeof(com_dev->rx_msg_buffer); + } else { + *headroom = 0; + } + } + + return (bytes_into_fifo); +} + +int32_t PIOS_COM_MSG_Send(uint32_t com_id, const uint8_t *msg, uint16_t msg_len) +{ + PIOS_Assert(msg); + PIOS_Assert(msg_len); + + struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)com_id; + + PIOS_Assert(msg_len == sizeof(com_dev->tx_msg_buffer)); + + /* Wait forever for room in the tx buffer */ + while (com_dev->tx_msg_full) { + /* Kick the transmitter while we wait */ + if (com_dev->driver->tx_start) { + (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer)); + } + } + + memcpy((void *) com_dev->tx_msg_buffer, msg, msg_len); + com_dev->tx_msg_full = true; + + /* Kick the transmitter now that we've queued our message */ + if (com_dev->driver->tx_start) { + (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer)); + } + + return 0; +} + +uint16_t PIOS_COM_MSG_Receive(uint32_t com_id, uint8_t * msg, uint16_t msg_len) +{ + PIOS_Assert(msg); + PIOS_Assert(msg_len); + + struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)com_id; + + PIOS_Assert(msg_len == sizeof(com_dev->rx_msg_buffer)); + + if (!com_dev->rx_msg_full) { + /* There's room in our buffer, kick the receiver */ + (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer)); + } else { + memcpy(msg, com_dev->rx_msg_buffer, msg_len); + com_dev->rx_msg_full = false; + + return msg_len; + } + + return 0; +} + +#endif /* PIOS_INCLUDE_COM_MSG */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/STM32F10x/pios_usb_hid.c b/flight/PiOS/STM32F10x/pios_usb_hid.c index 11eb988c1..e70c93046 100644 --- a/flight/PiOS/STM32F10x/pios_usb_hid.c +++ b/flight/PiOS/STM32F10x/pios_usb_hid.c @@ -207,9 +207,15 @@ static void PIOS_USB_HID_RxStart(uint32_t usbhid_id, uint16_t rx_bytes_avail) { } // If endpoint was stalled and there is now space make it valid +#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE + uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1; +#else + uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2; +#endif + PIOS_IRQ_Disable(); if ((GetEPRxStatus(usb_hid_dev->cfg->data_rx_ep) != EP_RX_VALID) && - (rx_bytes_avail >= PIOS_USB_BOARD_HID_DATA_LENGTH)) { + (rx_bytes_avail >= max_payload_length)) { SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_VALID); } PIOS_IRQ_Enable(); @@ -328,7 +334,15 @@ static void PIOS_USB_HID_EP_OUT_Callback(void) &headroom, &need_yield); #endif - if (headroom >= PIOS_USB_BOARD_HID_DATA_LENGTH) { + +#ifdef PIOS_USB_BOARD_BL_HID_HAS_NO_LENGTH_BYTE + uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 1; +#else + uint16_t max_payload_length = PIOS_USB_BOARD_HID_DATA_LENGTH - 2; +#endif + + if (headroom >= max_payload_length) { + /* We have room for a maximum length message */ SetEPRxStatus(usb_hid_dev->cfg->data_rx_ep, EP_RX_VALID); } else { diff --git a/flight/PiOS/inc/pios_com.h b/flight/PiOS/inc/pios_com.h index 19abb2f27..10591f116 100644 --- a/flight/PiOS/inc/pios_com.h +++ b/flight/PiOS/inc/pios_com.h @@ -31,6 +31,9 @@ #ifndef PIOS_COM_H #define PIOS_COM_H +#include /* uint*_t */ +#include /* bool */ + typedef uint16_t (*pios_com_callback)(uint32_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * task_woken); struct pios_com_driver { @@ -43,7 +46,6 @@ struct pios_com_driver { }; /* Public Functions */ -extern int32_t PIOS_COM_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t * rx_buffer, uint16_t rx_buffer_len, uint8_t * tx_buffer, uint16_t tx_buffer_len); extern int32_t PIOS_COM_ChangeBaud(uint32_t com_id, uint32_t baud); extern int32_t PIOS_COM_SendCharNonBlocking(uint32_t com_id, char c); extern int32_t PIOS_COM_SendChar(uint32_t com_id, char c); diff --git a/flight/PiOS/inc/pios_com_msg.h b/flight/PiOS/inc/pios_com_msg.h new file mode 100644 index 000000000..1caaeabeb --- /dev/null +++ b/flight/PiOS/inc/pios_com_msg.h @@ -0,0 +1,45 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_COM COM MSG layer functions + * @brief Hardware communication layer + * @{ + * + * @file pios_com_msg.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief COM MSG layer functions header + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_COM_MSG_H +#define PIOS_COM_MSG_H + +#include /* uint*_t */ + +/* Public Functions */ +extern int32_t PIOS_COM_MSG_Send(uint32_t com_id, const uint8_t *msg, uint16_t msg_len); +extern uint16_t PIOS_COM_MSG_Receive(uint32_t com_id, uint8_t * buf, uint16_t buf_len); + +#endif /* PIOS_COM_MSG_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_com_msg_priv.h b/flight/PiOS/inc/pios_com_msg_priv.h new file mode 100644 index 000000000..20992de47 --- /dev/null +++ b/flight/PiOS/inc/pios_com_msg_priv.h @@ -0,0 +1,44 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_COM COM MSG layer functions + * @brief Hardware communication layer + * @{ + * + * @file pios_com_msg_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief COM MSG private definitions. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_COM_MSG_PRIV_H +#define PIOS_COM_MSG_PRIV_H + +#include /* uint*_t */ +#include "pios_com_priv.h" /* struct pios_com_driver */ + +extern int32_t PIOS_COM_MSG_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id); + +#endif /* PIOS_COM_MSG_PRIV_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_com_priv.h b/flight/PiOS/inc/pios_com_priv.h index 7bd9a9be0..c39522f79 100644 --- a/flight/PiOS/inc/pios_com_priv.h +++ b/flight/PiOS/inc/pios_com_priv.h @@ -31,6 +31,8 @@ #ifndef PIOS_COM_PRIV_H #define PIOS_COM_PRIV_H +extern int32_t PIOS_COM_Init(uint32_t * com_id, const struct pios_com_driver * driver, uint32_t lower_id, uint8_t * rx_buffer, uint16_t rx_buffer_len, uint8_t * tx_buffer, uint16_t tx_buffer_len); + #endif /* PIOS_COM_PRIV_H */ /** From 1d14ab00e1c6d0229466720cc6459606bbd02672 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 14 Jan 2012 14:28:11 -0500 Subject: [PATCH 27/72] safeboot: add safe boot support to OP and PIPX bootloaders Application support for OP and PIPX will show up in future commits. --- flight/Bootloaders/OpenPilot/op_dfu.c | 8 ++++++++ flight/Bootloaders/PipXtreme/op_dfu.c | 4 ++++ make/boards/openpilot/board-info.mk | 2 +- make/boards/pipxtreme/board-info.mk | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/flight/Bootloaders/OpenPilot/op_dfu.c b/flight/Bootloaders/OpenPilot/op_dfu.c index ad5836ad7..40ef6fbda 100644 --- a/flight/Bootloaders/OpenPilot/op_dfu.c +++ b/flight/Bootloaders/OpenPilot/op_dfu.c @@ -353,10 +353,18 @@ void processComand(uint8_t *xReceive_Buffer) { DeviceState = failed_jump; break; } else { + if (Data == 0x5AFE) { + /* Force board into safe mode */ + PIOS_IAP_WriteBootCount(0xFFFF); + } FLASH_Lock(); JumpToApp = 1; } } else { + if (Data == 0x5AFE) { + /* Force board into safe mode */ + PIOS_IAP_WriteBootCount(0xFFFF); + } FLASH_Lock(); JumpToApp = 1; } diff --git a/flight/Bootloaders/PipXtreme/op_dfu.c b/flight/Bootloaders/PipXtreme/op_dfu.c index cdc2d82b8..0d5da248f 100644 --- a/flight/Bootloaders/PipXtreme/op_dfu.c +++ b/flight/Bootloaders/PipXtreme/op_dfu.c @@ -301,6 +301,10 @@ void processComand(uint8_t *xReceive_Buffer) { sendData(Buffer + 1, 63); break; case JumpFW: + if (Data == 0x5AFE) { + /* Force board into safe mode */ + PIOS_IAP_WriteBootCount(0xFFFF); + } FLASH_Lock(); JumpToApp = 1; break; diff --git a/make/boards/openpilot/board-info.mk b/make/boards/openpilot/board-info.mk index d9cff166d..e98ac4480 100644 --- a/make/boards/openpilot/board-info.mk +++ b/make/boards/openpilot/board-info.mk @@ -1,6 +1,6 @@ BOARD_TYPE := 0x01 BOARD_REVISION := 0x01 -BOOTLOADER_VERSION := 0x00 +BOOTLOADER_VERSION := 0x01 HW_TYPE := 0x00 MCU := cortex-m3 diff --git a/make/boards/pipxtreme/board-info.mk b/make/boards/pipxtreme/board-info.mk index f9635109e..dbcb314df 100644 --- a/make/boards/pipxtreme/board-info.mk +++ b/make/boards/pipxtreme/board-info.mk @@ -1,6 +1,6 @@ BOARD_TYPE := 0x03 BOARD_REVISION := 0x01 -BOOTLOADER_VERSION := 0x00 +BOOTLOADER_VERSION := 0x01 HW_TYPE := 0x01 MCU := cortex-m3 From a51bf72bc76d2036fc4f58d61d9b14de8a4c53ec Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 14 Jan 2012 14:17:06 -0500 Subject: [PATCH 28/72] usb: allow runtime selection of USB descriptors via hwsettings --- flight/Bootloaders/CopterControl/Makefile | 1 - .../CopterControl/inc/pios_usb_board_data.h | 27 --- flight/Bootloaders/CopterControl/pios_board.c | 10 + .../CopterControl/pios_usb_board_data.c | 77 ++++++- flight/Bootloaders/OpenPilot/Makefile | 2 +- .../OpenPilot/inc/pios_usb_board_data.h | 27 --- flight/Bootloaders/OpenPilot/main.c | 5 - flight/Bootloaders/OpenPilot/op_dfu.c | 7 +- flight/Bootloaders/OpenPilot/pios_board.c | 12 +- .../OpenPilot/pios_usb_board_data.c | 78 ++++++- flight/Bootloaders/PipXtreme/Makefile | 2 +- .../Bootloaders/PipXtreme/inc/pios_config.h | 1 - .../PipXtreme/inc/pios_usb_board_data.h | 27 --- flight/Bootloaders/PipXtreme/main.c | 5 - flight/Bootloaders/PipXtreme/op_dfu.c | 11 +- flight/Bootloaders/PipXtreme/pios_board.c | 9 + .../PipXtreme/pios_usb_board_data.c | 77 ++++++- flight/CopterControl/Makefile | 1 + .../System/inc/pios_usb_board_data.h | 39 +--- flight/CopterControl/System/pios_board.c | 49 ++++- .../System/pios_usb_board_data.c | 77 ++++++- flight/OpenPilot/Makefile | 2 + flight/OpenPilot/System/inc/pios_config.h | 1 + .../System/inc/pios_usb_board_data.h | 37 ---- flight/OpenPilot/System/pios_board.c | 193 +++++++++++++++--- flight/OpenPilot/System/pios_usb_board_data.c | 79 ++++++- flight/PiOS/Common/pios_usb_desc_hid_cdc.c | 183 ++++++++--------- flight/PiOS/Common/pios_usb_desc_hid_only.c | 173 +++++++--------- .../STM32_USB-FS-Device_Driver/inc/usb_core.h | 19 +- .../STM32_USB-FS-Device_Driver/inc/usb_mem.h | 2 +- .../STM32_USB-FS-Device_Driver/src/usb_core.c | 20 +- .../STM32_USB-FS-Device_Driver/src/usb_mem.c | 2 +- flight/PiOS/STM32F10x/pios_usb.c | 7 - flight/PiOS/STM32F10x/pios_usb_cdc.c | 2 +- flight/PiOS/STM32F10x/pios_usbhook.c | 114 +++++------ flight/PiOS/inc/pios_usb_board_data_priv.h | 1 + flight/PiOS/inc/pios_usb_cdc_priv.h | 2 +- flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h | 8 + flight/PiOS/inc/pios_usb_desc_hid_only_priv.h | 8 + flight/PiOS/inc/pios_usbhook.h | 13 ++ flight/PipXtreme/inc/pios_usb_board_data.h | 27 --- flight/PipXtreme/pios_board.c | 14 +- flight/PipXtreme/pios_usb_board_data.c | 77 ++++++- shared/uavobjectdefinition/hwsettings.xml | 1 + 44 files changed, 980 insertions(+), 549 deletions(-) create mode 100644 flight/PiOS/inc/pios_usb_board_data_priv.h create mode 100644 flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h create mode 100644 flight/PiOS/inc/pios_usb_desc_hid_only_priv.h diff --git a/flight/Bootloaders/CopterControl/Makefile b/flight/Bootloaders/CopterControl/Makefile index a5effde9c..699fd02e5 100644 --- a/flight/Bootloaders/CopterControl/Makefile +++ b/flight/Bootloaders/CopterControl/Makefile @@ -104,7 +104,6 @@ SRC += $(PIOSSTM32F10X)/pios_irq.c SRC += $(PIOSSTM32F10X)/pios_debug.c SRC += $(PIOSSTM32F10X)/pios_gpio.c - # PIOS USB related files (seperated to make code maintenance more easy) SRC += $(PIOSSTM32F10X)/pios_usb.c SRC += $(PIOSSTM32F10X)/pios_usbhook.c diff --git a/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h b/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h index 85f407a9e..f1accee17 100644 --- a/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h +++ b/flight/Bootloaders/CopterControl/inc/pios_usb_board_data.h @@ -37,33 +37,6 @@ #include "pios_usb_defs.h" /* struct usb_* */ -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[28]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; - #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_COPTERCONTROL #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_COPTERCONTROL, USB_OP_BOARD_MODE_BL) diff --git a/flight/Bootloaders/CopterControl/pios_board.c b/flight/Bootloaders/CopterControl/pios_board.c index 972a85be0..a70537fcc 100644 --- a/flight/Bootloaders/CopterControl/pios_board.c +++ b/flight/Bootloaders/CopterControl/pios_board.c @@ -48,6 +48,10 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }, }; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + #endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) @@ -87,6 +91,12 @@ void PIOS_Board_Init(void) { PIOS_GPIO_Init(); #if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + /* Activate the HID-only USB configuration */ + PIOS_USB_DESC_HID_ONLY_Init(); + uint32_t pios_usb_id; if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); diff --git a/flight/Bootloaders/CopterControl/pios_usb_board_data.c b/flight/Bootloaders/CopterControl/pios_usb_board_data.c index b39fcbec3..4f02ce424 100644 --- a/flight/Bootloaders/CopterControl/pios_usb_board_data.c +++ b/flight/Bootloaders/CopterControl/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[28] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'C', 0, 'o', 0, @@ -48,3 +50,74 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'l', 0, }; +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} diff --git a/flight/Bootloaders/OpenPilot/Makefile b/flight/Bootloaders/OpenPilot/Makefile index 6c3888797..05d1bec1d 100644 --- a/flight/Bootloaders/OpenPilot/Makefile +++ b/flight/Bootloaders/OpenPilot/Makefile @@ -293,7 +293,7 @@ CSTANDARD = -std=gnu99 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++) ifeq ($(DEBUG),YES) -CFLAGS = -DDEBUG +CFLAGS += -DDEBUG endif CFLAGS += -g$(DEBUGF) diff --git a/flight/Bootloaders/OpenPilot/inc/pios_usb_board_data.h b/flight/Bootloaders/OpenPilot/inc/pios_usb_board_data.h index d3e1079d6..ca9c948b0 100644 --- a/flight/Bootloaders/OpenPilot/inc/pios_usb_board_data.h +++ b/flight/Bootloaders/OpenPilot/inc/pios_usb_board_data.h @@ -37,33 +37,6 @@ #include "pios_usb_defs.h" /* struct usb_* */ -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[20]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; - #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_OPENPILOT_MAIN #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_OPENPILOT_MAIN, USB_OP_BOARD_MODE_BL) diff --git a/flight/Bootloaders/OpenPilot/main.c b/flight/Bootloaders/OpenPilot/main.c index 8a9e554ef..3a06c9751 100644 --- a/flight/Bootloaders/OpenPilot/main.c +++ b/flight/Bootloaders/OpenPilot/main.c @@ -102,10 +102,6 @@ uint32_t sspTimeSource(); #define RED LED2 #define LED_PWM_TIMER TIM6 int main() { - /* NOTE: Do NOT modify the following start-up sequence */ - /* Any new initialization functions should be added in OpenPilotInit() */ - - /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); if (BSL_HOLD_STATE == 0) USB_connected = TRUE; @@ -228,7 +224,6 @@ void jump_to_app() { RCC_APB1PeriphResetCmd(0xffffffff, DISABLE); _SetCNTR(0); // clear interrupt mask _SetISTR(0); // clear all requests - JumpAddress = *(__IO uint32_t*) (bdinfo->fw_base + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ diff --git a/flight/Bootloaders/OpenPilot/op_dfu.c b/flight/Bootloaders/OpenPilot/op_dfu.c index 40ef6fbda..ef30e4897 100644 --- a/flight/Bootloaders/OpenPilot/op_dfu.c +++ b/flight/Bootloaders/OpenPilot/op_dfu.c @@ -34,10 +34,6 @@ #include #include "pios_opahrs.h" #include "ssp.h" -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ //programmable devices Device devicesTable[10]; uint8_t numberOfDevices = 0; @@ -223,7 +219,7 @@ void processComand(uint8_t *xReceive_Buffer) { } } if (result != 1) { - DeviceState = Last_operation_failed;//ok + DeviceState = Last_operation_failed; Aditionals = (uint32_t) Command; } else { @@ -392,7 +388,6 @@ void processComand(uint8_t *xReceive_Buffer) { DeviceState = too_few_packets; } } - break; case Download_Req: #ifdef DEBUG_SSP diff --git a/flight/Bootloaders/OpenPilot/pios_board.c b/flight/Bootloaders/OpenPilot/pios_board.c index 707600b4d..d1ba74d8b 100644 --- a/flight/Bootloaders/OpenPilot/pios_board.c +++ b/flight/Bootloaders/OpenPilot/pios_board.c @@ -215,7 +215,11 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }, }; -#endif /* PIOS_INCLUDE_USB_HID */ + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + +#endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) #include @@ -270,6 +274,12 @@ void PIOS_Board_Init(void) { PIOS_GPIO_Init(); #if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + /* Activate the HID-only USB configuration */ + PIOS_USB_DESC_HID_ONLY_Init(); + uint32_t pios_usb_id; if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); diff --git a/flight/Bootloaders/OpenPilot/pios_usb_board_data.c b/flight/Bootloaders/OpenPilot/pios_usb_board_data.c index 9492d316e..b73419ba4 100644 --- a/flight/Bootloaders/OpenPilot/pios_usb_board_data.c +++ b/flight/Bootloaders/OpenPilot/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[20] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'O', 0, 'p', 0, @@ -43,3 +45,75 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'o', 0, 't', 0, }; + +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} diff --git a/flight/Bootloaders/PipXtreme/Makefile b/flight/Bootloaders/PipXtreme/Makefile index 9bad695f7..a411b6403 100644 --- a/flight/Bootloaders/PipXtreme/Makefile +++ b/flight/Bootloaders/PipXtreme/Makefile @@ -287,7 +287,7 @@ CSTANDARD = -std=gnu99 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++) ifeq ($(DEBUG),YES) -CFLAGS = -DDEBUG +CFLAGS += -DDEBUG endif CFLAGS += -g$(DEBUGF) diff --git a/flight/Bootloaders/PipXtreme/inc/pios_config.h b/flight/Bootloaders/PipXtreme/inc/pios_config.h index 8084f9c0a..cec926057 100644 --- a/flight/Bootloaders/PipXtreme/inc/pios_config.h +++ b/flight/Bootloaders/PipXtreme/inc/pios_config.h @@ -40,7 +40,6 @@ #define PIOS_INCLUDE_USB_HID #define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO -//#define DEBUG_SSP /* Defaults for Logging */ #define LOG_FILENAME "PIOS.LOG" diff --git a/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h b/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h index fb6ced1f8..2e35f2fa4 100644 --- a/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h +++ b/flight/Bootloaders/PipXtreme/inc/pios_usb_board_data.h @@ -37,33 +37,6 @@ #include "pios_usb_defs.h" /* struct usb_* */ -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[20]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; - #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_PIPXTREME #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_PIPXTREME, USB_OP_BOARD_MODE_BL) diff --git a/flight/Bootloaders/PipXtreme/main.c b/flight/Bootloaders/PipXtreme/main.c index 4923f8fc1..602193f5c 100644 --- a/flight/Bootloaders/PipXtreme/main.c +++ b/flight/Bootloaders/PipXtreme/main.c @@ -72,10 +72,6 @@ void jump_to_app(); #define BLUE LED1 #define RED LED4 int main() { - /* NOTE: Do NOT modify the following start-up sequence */ - /* Any new initialization functions should be added in OpenPilotInit() */ - - /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); if (BSL_HOLD_STATE == 0) USB_connected = TRUE; @@ -182,7 +178,6 @@ void jump_to_app() { RCC_APB1PeriphResetCmd(0xffffffff, DISABLE); _SetCNTR(0); // clear interrupt mask _SetISTR(0); // clear all requests - JumpAddress = *(__IO uint32_t*) (bdinfo->fw_base + 4); Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ diff --git a/flight/Bootloaders/PipXtreme/op_dfu.c b/flight/Bootloaders/PipXtreme/op_dfu.c index 0d5da248f..249e3d320 100644 --- a/flight/Bootloaders/PipXtreme/op_dfu.c +++ b/flight/Bootloaders/PipXtreme/op_dfu.c @@ -32,10 +32,6 @@ #include "pios_bl_helper.h" #include "pios_com_msg.h" #include -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ //programmable devices Device devicesTable[10]; uint8_t numberOfDevices = 0; @@ -145,7 +141,7 @@ void processComand(uint8_t *xReceive_Buffer) { case EnterDFU: if (((DeviceState == BLidle) && (Data0 < numberOfDevices)) || (DeviceState == DFUidle)) { - if (Data0 > 0)//PORQUE??? + if (Data0 > 0) OPDfuIni(TRUE); DeviceState = DFUidle; currentProgrammingDestination = devicesTable[Data0].programmingType; @@ -202,7 +198,7 @@ void processComand(uint8_t *xReceive_Buffer) { } } if (result != 1) { - DeviceState = Last_operation_failed;//ok + DeviceState = Last_operation_failed; Aditionals = (uint32_t) Command; } else { @@ -253,11 +249,9 @@ void processComand(uint8_t *xReceive_Buffer) { ++Next_Packet; } else { - DeviceState = wrong_packet_received; Aditionals = Count; } - // FLASH_ProgramWord(MemLocations[TransferType]+4,++Next_Packet);//+Count,Data); } else { DeviceState = Last_operation_failed; Aditionals = (uint32_t) Command; @@ -331,7 +325,6 @@ void processComand(uint8_t *xReceive_Buffer) { DeviceState = too_few_packets; } } - break; case Download_Req: #ifdef DEBUG_SSP diff --git a/flight/Bootloaders/PipXtreme/pios_board.c b/flight/Bootloaders/PipXtreme/pios_board.c index 3c06d820b..a70537fcc 100644 --- a/flight/Bootloaders/PipXtreme/pios_board.c +++ b/flight/Bootloaders/PipXtreme/pios_board.c @@ -49,6 +49,9 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }; +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + #endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) @@ -88,6 +91,12 @@ void PIOS_Board_Init(void) { PIOS_GPIO_Init(); #if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + /* Activate the HID-only USB configuration */ + PIOS_USB_DESC_HID_ONLY_Init(); + uint32_t pios_usb_id; if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { PIOS_Assert(0); diff --git a/flight/Bootloaders/PipXtreme/pios_usb_board_data.c b/flight/Bootloaders/PipXtreme/pios_usb_board_data.c index d54ca6565..3e41e5ac9 100644 --- a/flight/Bootloaders/PipXtreme/pios_usb_board_data.c +++ b/flight/Bootloaders/PipXtreme/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[20] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'P', 0, 'i', 0, @@ -44,3 +46,74 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'e', 0, }; +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 589251a4a..891e7f6c6 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -216,6 +216,7 @@ SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(OPSYSTEM)/pios_usb_board_data.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c +SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_crc.c diff --git a/flight/CopterControl/System/inc/pios_usb_board_data.h b/flight/CopterControl/System/inc/pios_usb_board_data.h index ee53c7455..9907a4934 100644 --- a/flight/CopterControl/System/inc/pios_usb_board_data.h +++ b/flight/CopterControl/System/inc/pios_usb_board_data.h @@ -37,44 +37,7 @@ #define PIOS_USB_BOARD_EP_NUM 4 -#include "pios_usb_defs.h" /* struct usb_* */ - -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_association_desc iad; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; - struct usb_interface_desc cdc_control_if; - struct usb_cdc_header_func_desc cdc_header; - struct usb_cdc_callmgmt_func_desc cdc_callmgmt; - struct usb_cdc_acm_func_desc cdc_acm; - struct usb_cdc_union_func_desc cdc_union; - struct usb_endpoint_desc cdc_mgmt_in; - struct usb_interface_desc cdc_data_if; - struct usb_endpoint_desc cdc_in; - struct usb_endpoint_desc cdc_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[28]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; +#include "pios_usb_defs.h" /* USB_* macros */ #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_COPTERCONTROL #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_COPTERCONTROL, USB_OP_BOARD_MODE_FW) diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index 3a4c3e89f..ffdde4759 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -998,6 +998,11 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }, }; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_cdc_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + #endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) @@ -1090,14 +1095,50 @@ void PIOS_Board_Init(void) { PIOS_TIM_InitClock(&tim_4_cfg); #if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + /* Flags to determine if various USB interfaces are advertised */ + bool usb_hid_present = false; + bool usb_cdc_present = false; + + uint8_t hwsettings_usb_devicetype; + HwSettingsUSB_DeviceTypeGet(&hwsettings_usb_devicetype); + + switch (hwsettings_usb_devicetype) { + case HWSETTINGS_USB_DEVICETYPE_HIDONLY: + if (PIOS_USB_DESC_HID_ONLY_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; + break; + case HWSETTINGS_USB_DEVICETYPE_HIDVCP: + if (PIOS_USB_DESC_HID_CDC_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; + usb_cdc_present = true; + break; + case HWSETTINGS_USB_DEVICETYPE_VCPONLY: + break; + default: + PIOS_Assert(0); + } + uint32_t pios_usb_id; PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg); #if defined(PIOS_INCLUDE_USB_CDC) - /* Configure the USB VCP port */ + uint8_t hwsettings_usb_vcpport; + /* Configure the USB VCP port */ HwSettingsUSB_VCPPortGet(&hwsettings_usb_vcpport); + if (!usb_cdc_present) { + /* Force VCP port function to disabled if we haven't advertised VCP in our USB descriptor */ + hwsettings_usb_vcpport = HWSETTINGS_USB_VCPPORT_DISABLED; + } + switch (hwsettings_usb_vcpport) { case HWSETTINGS_USB_VCPPORT_DISABLED: break; @@ -1136,7 +1177,6 @@ void PIOS_Board_Init(void) { tx_buffer, PIOS_COM_BRIDGE_TX_BUF_LEN)) { PIOS_Assert(0); } - } #endif /* PIOS_INCLUDE_COM */ break; @@ -1148,6 +1188,11 @@ void PIOS_Board_Init(void) { uint8_t hwsettings_usb_hidport; HwSettingsUSB_HIDPortGet(&hwsettings_usb_hidport); + if (!usb_hid_present) { + /* Force HID port function to disabled if we haven't advertised HID in our USB descriptor */ + hwsettings_usb_hidport = HWSETTINGS_USB_HIDPORT_DISABLED; + } + switch (hwsettings_usb_hidport) { case HWSETTINGS_USB_HIDPORT_DISABLED: break; diff --git a/flight/CopterControl/System/pios_usb_board_data.c b/flight/CopterControl/System/pios_usb_board_data.c index b39fcbec3..4f02ce424 100644 --- a/flight/CopterControl/System/pios_usb_board_data.c +++ b/flight/CopterControl/System/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[28] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'C', 0, 'o', 0, @@ -48,3 +50,74 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'l', 0, }; +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} diff --git a/flight/OpenPilot/Makefile b/flight/OpenPilot/Makefile index 8f9d9bef9..940c1f117 100644 --- a/flight/OpenPilot/Makefile +++ b/flight/OpenPilot/Makefile @@ -183,9 +183,11 @@ SRC += $(PIOSSTM32F10X)/pios_wdg.c SRC += $(PIOSSTM32F10X)/pios_usb.c SRC += $(PIOSSTM32F10X)/pios_usbhook.c SRC += $(PIOSSTM32F10X)/pios_usb_hid.c +SRC += $(PIOSSTM32F10X)/pios_usb_cdc.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_istr.c SRC += $(PIOSSTM32F10X)/pios_usb_hid_pwr.c SRC += $(OPSYSTEM)/pios_usb_board_data.c +SRC += $(PIOSCOMMON)/pios_usb_desc_hid_cdc.c SRC += $(PIOSCOMMON)/pios_usb_desc_hid_only.c ## PIOS Hardware (Common) diff --git a/flight/OpenPilot/System/inc/pios_config.h b/flight/OpenPilot/System/inc/pios_config.h index 3ec902e8e..ce0484a8d 100644 --- a/flight/OpenPilot/System/inc/pios_config.h +++ b/flight/OpenPilot/System/inc/pios_config.h @@ -57,6 +57,7 @@ #define PIOS_INCLUDE_USART #define PIOS_INCLUDE_USB #define PIOS_INCLUDE_USB_HID +#define PIOS_INCLUDE_USB_CDC #define PIOS_INCLUDE_BMP085 //#define PIOS_INCLUDE_HCSR04 #define PIOS_INCLUDE_OPAHRS diff --git a/flight/OpenPilot/System/inc/pios_usb_board_data.h b/flight/OpenPilot/System/inc/pios_usb_board_data.h index e2f079bc2..08fc3423b 100644 --- a/flight/OpenPilot/System/inc/pios_usb_board_data.h +++ b/flight/OpenPilot/System/inc/pios_usb_board_data.h @@ -39,43 +39,6 @@ #include "pios_usb_defs.h" /* struct usb_* */ -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_association_desc iad; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; - struct usb_interface_desc cdc_control_if; - struct usb_cdc_header_func_desc cdc_header; - struct usb_cdc_callmgmt_func_desc cdc_callmgmt; - struct usb_cdc_acm_func_desc cdc_acm; - struct usb_cdc_union_func_desc cdc_union; - struct usb_endpoint_desc cdc_mgmt_in; - struct usb_interface_desc cdc_data_if; - struct usb_endpoint_desc cdc_in; - struct usb_endpoint_desc cdc_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[20]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; - #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_OPENPILOT_MAIN #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_OPENPILOT_MAIN, USB_OP_BOARD_MODE_FW) diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index 314a8e24d..8dbb5eee2 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -611,6 +611,9 @@ static const struct pios_dsm_cfg pios_dsm_cfg = { #define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 #define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 +#define PIOS_COM_BRIDGE_RX_BUF_LEN 65 +#define PIOS_COM_BRIDGE_TX_BUF_LEN 12 + #endif /* PIOS_INCLUDE_COM */ /** @@ -1054,6 +1057,10 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }, }; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_cdc_priv.h" +#include "pios_usb_desc_hid_only_priv.h" #endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) @@ -1067,8 +1074,22 @@ const struct pios_usb_hid_cfg pios_usb_hid_cfg = { #endif /* PIOS_INCLUDE_USB_HID */ +#if defined(PIOS_INCLUDE_USB_CDC) +#include + +const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { + .ctrl_if = 1, + .ctrl_tx_ep = 2, + + .data_if = 2, + .data_rx_ep = 3, + .data_tx_ep = 3, +}; +#endif /* PIOS_INCLUDE_USB_CDC */ + uint32_t pios_com_telem_rf_id; uint32_t pios_com_telem_usb_id; +uint32_t pios_com_vcp_id; uint32_t pios_com_gps_id; uint32_t pios_com_aux_id; uint32_t pios_com_dsm_id; @@ -1109,14 +1130,27 @@ void PIOS_Board_Init(void) { HwSettingsInitialize(); + PIOS_WDG_Init(); + + /* Initialize the alarms library */ + AlarmsInitialize(); + + PIOS_IAP_Init(); + uint16_t boot_count = PIOS_IAP_ReadBootCount(); + if (boot_count < 3) { + PIOS_IAP_WriteBootCount(++boot_count); + AlarmsClear(SYSTEMALARMS_ALARM_BOOTFAULT); + } else { + /* Too many failed boot attempts, force hwsettings to defaults */ + HwSettingsSetDefaults(HwSettingsHandle(), 0); + AlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT, SYSTEMALARMS_ALARM_CRITICAL); + } + #if defined(PIOS_INCLUDE_RTC) /* Initialize the real-time clock and its associated tick */ PIOS_RTC_Init(&pios_rtc_main_cfg); #endif - /* Initialize the alarms library */ - AlarmsInitialize(); - /* Initialize the task monitor library */ TaskMonitorInitialize(); @@ -1124,7 +1158,6 @@ void PIOS_Board_Init(void) { PIOS_TIM_InitClock(&tim_1_cfg); PIOS_TIM_InitClock(&tim_3_cfg); PIOS_TIM_InitClock(&tim_5_cfg); - PIOS_TIM_InitClock(&tim_4_cfg); PIOS_TIM_InitClock(&tim_8_cfg); @@ -1139,6 +1172,133 @@ void PIOS_Board_Init(void) { /* Bind the AHRS comms layer to the AHRS SPI link */ AhrsConnect(pios_spi_ahrs_id); +#if defined(PIOS_INCLUDE_USB) + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + /* Flags to determine if various USB interfaces are advertised */ + bool usb_hid_present = false; + bool usb_cdc_present = false; + + uint8_t hwsettings_usb_devicetype; + HwSettingsUSB_DeviceTypeGet(&hwsettings_usb_devicetype); + + switch (hwsettings_usb_devicetype) { + case HWSETTINGS_USB_DEVICETYPE_HIDONLY: + if (PIOS_USB_DESC_HID_ONLY_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; + break; + case HWSETTINGS_USB_DEVICETYPE_HIDVCP: + if (PIOS_USB_DESC_HID_CDC_Init()) { + PIOS_Assert(0); + } + usb_hid_present = true; + usb_cdc_present = true; + break; + case HWSETTINGS_USB_DEVICETYPE_VCPONLY: + break; + default: + PIOS_Assert(0); + } + + uint32_t pios_usb_id; + PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg); + +#if defined(PIOS_INCLUDE_USB_CDC) + /* Configure the USB VCP port */ + uint8_t hwsettings_usb_vcpport; + HwSettingsUSB_VCPPortGet(&hwsettings_usb_vcpport); + + if (!usb_cdc_present) { + /* Force VCP port function to disabled if we haven't advertised VCP in our USB descriptor */ + hwsettings_usb_vcpport = HWSETTINGS_USB_VCPPORT_DISABLED; + } + + switch (hwsettings_usb_vcpport) { + case HWSETTINGS_USB_VCPPORT_DISABLED: + break; + case HWSETTINGS_USB_VCPPORT_USBTELEMETRY: +#if defined(PIOS_INCLUDE_COM) + { + uint32_t pios_usb_cdc_id; + if (PIOS_USB_CDC_Init(&pios_usb_cdc_id, &pios_usb_cdc_cfg, pios_usb_id)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_cdc_com_driver, pios_usb_cdc_id, + rx_buffer, PIOS_COM_TELEM_USB_RX_BUF_LEN, + tx_buffer, PIOS_COM_TELEM_USB_TX_BUF_LEN)) { + PIOS_Assert(0); + } + } +#endif /* PIOS_INCLUDE_COM */ + break; + case HWSETTINGS_USB_VCPPORT_COMBRIDGE: +#if defined(PIOS_INCLUDE_COM) + { + uint32_t pios_usb_cdc_id; + if (PIOS_USB_CDC_Init(&pios_usb_cdc_id, &pios_usb_cdc_cfg, pios_usb_id)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_BRIDGE_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_BRIDGE_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_vcp_id, &pios_usb_cdc_com_driver, pios_usb_cdc_id, + rx_buffer, PIOS_COM_BRIDGE_RX_BUF_LEN, + tx_buffer, PIOS_COM_BRIDGE_TX_BUF_LEN)) { + PIOS_Assert(0); + } + + } +#endif /* PIOS_INCLUDE_COM */ + break; + } +#endif /* PIOS_INCLUDE_USB_CDC */ + +#if defined(PIOS_INCLUDE_USB_HID) + /* Configure the usb HID port */ + uint8_t hwsettings_usb_hidport; + HwSettingsUSB_HIDPortGet(&hwsettings_usb_hidport); + + if (!usb_hid_present) { + /* Force HID port function to disabled if we haven't advertised HID in our USB descriptor */ + hwsettings_usb_hidport = HWSETTINGS_USB_HIDPORT_DISABLED; + } + + switch (hwsettings_usb_hidport) { + case HWSETTINGS_USB_HIDPORT_DISABLED: + break; + case HWSETTINGS_USB_HIDPORT_USBTELEMETRY: +#if defined(PIOS_INCLUDE_COM) + { + uint32_t pios_usb_hid_id; + if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { + PIOS_Assert(0); + } + uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_RX_BUF_LEN); + uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_TX_BUF_LEN); + PIOS_Assert(rx_buffer); + PIOS_Assert(tx_buffer); + if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, + rx_buffer, PIOS_COM_TELEM_USB_RX_BUF_LEN, + tx_buffer, PIOS_COM_TELEM_USB_TX_BUF_LEN)) { + PIOS_Assert(0); + } + } +#endif /* PIOS_INCLUDE_COM */ + break; + } + +#endif /* PIOS_INCLUDE_USB_HID */ + +#endif /* PIOS_INCLUDE_USB */ + /* Configure the main IO port */ uint8_t hwsettings_op_mainport; HwSettingsOP_MainPortGet(&hwsettings_op_mainport); @@ -1285,36 +1445,11 @@ void PIOS_Board_Init(void) { break; } -#if defined(PIOS_INCLUDE_USB) - uint32_t pios_usb_id; - if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { - PIOS_Assert(0); - } -#if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) - uint32_t pios_usb_hid_id; - if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { - PIOS_Assert(0); - } - uint8_t * rx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_RX_BUF_LEN); - uint8_t * tx_buffer = (uint8_t *) pvPortMalloc(PIOS_COM_TELEM_USB_TX_BUF_LEN); - PIOS_Assert(rx_buffer); - PIOS_Assert(tx_buffer); - if (PIOS_COM_Init(&pios_com_telem_usb_id, &pios_usb_hid_com_driver, pios_usb_hid_id, - rx_buffer, PIOS_COM_TELEM_USB_RX_BUF_LEN, - tx_buffer, PIOS_COM_TELEM_USB_TX_BUF_LEN)) { - PIOS_Assert(0); - } -#endif /* PIOS_INCLUDE_USB_HID && PIOS_INCLUDE_COM */ - -#endif /* PIOS_INCLUDE_USB */ - #if defined(PIOS_INCLUDE_I2C) if (PIOS_I2C_Init(&pios_i2c_main_adapter_id, &pios_i2c_main_adapter_cfg)) { PIOS_Assert(0); } #endif /* PIOS_INCLUDE_I2C */ - PIOS_IAP_Init(); - PIOS_WDG_Init(); } /** diff --git a/flight/OpenPilot/System/pios_usb_board_data.c b/flight/OpenPilot/System/pios_usb_board_data.c index 9492d316e..a6fa67abe 100644 --- a/flight/OpenPilot/System/pios_usb_board_data.c +++ b/flight/OpenPilot/System/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[20] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'O', 0, 'p', 0, @@ -43,3 +45,76 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'o', 0, 't', 0, }; + +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} + diff --git a/flight/PiOS/Common/pios_usb_desc_hid_cdc.c b/flight/PiOS/Common/pios_usb_desc_hid_cdc.c index 3d5748163..cd4e8a1da 100644 --- a/flight/PiOS/Common/pios_usb_desc_hid_cdc.c +++ b/flight/PiOS/Common/pios_usb_desc_hid_cdc.c @@ -28,9 +28,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_usb_desc_hid_cdc_priv.h" /* exported API */ +#include "pios_usb_defs.h" /* struct usb_*, USB_* */ +#include "pios_usb_board_data.h" /* PIOS_USB_BOARD_* */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_Register* */ -const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor = { +static const struct usb_device_desc device_desc = { .bLength = sizeof(struct usb_device_desc), .bDescriptorType = USB_DESC_TYPE_DEVICE, .bcdUSB = htousbs(0x0200), @@ -41,17 +44,79 @@ const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor = { .idVendor = htousbs(USB_VENDOR_ID_OPENPILOT), .idProduct = htousbs(PIOS_USB_BOARD_PRODUCT_ID), .bcdDevice = htousbs(PIOS_USB_BOARD_DEVICE_VER), - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, + .iManufacturer = USB_STRING_DESC_VENDOR, + .iProduct = USB_STRING_DESC_PRODUCT, + .iSerialNumber = USB_STRING_DESC_SERIAL, .bNumConfigurations = 1, }; -const struct usb_board_config PIOS_USB_BOARD_Configuration = { +static const uint8_t hid_report_desc[36] = { + HID_GLOBAL_ITEM_2 (HID_TAG_GLOBAL_USAGE_PAGE), + 0x9C, 0xFF, /* Usage Page 0xFF9C (Vendor Defined) */ + HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), + 0x01, /* Usage ID 0x0001 (0x01-0x1F uaually for top-level collections) */ + + HID_MAIN_ITEM_1 (HID_TAG_MAIN_COLLECTION), + 0x01, /* Application */ + + /* Device -> Host emulated serial channel */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_ID), + 0x01, /* OpenPilot emulated serial channel (Device -> Host) */ + HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), + 0x02, + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MIN), + 0x00, /* Values range from min = 0x00 */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MAX), + 0xFF, /* Values range to max = 0xFF */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_SIZE), + 0x08, /* 8 bits wide */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_CNT), + PIOS_USB_BOARD_HID_DATA_LENGTH-1, /* Need to leave room for a report ID */ + HID_MAIN_ITEM_1 (HID_TAG_MAIN_INPUT), + 0x03, /* Variable, Constant (read-only) */ + + /* Host -> Host emulated serial channel */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_ID), + 0x02, /* OpenPilot emulated Serial Channel (Host -> Device) */ + HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), + 0x02, + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MIN), + 0x00, /* Values range from min = 0x00 */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MAX), + 0xFF, /* Values range to max = 0xFF */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_SIZE), + 0x08, /* 8 bits wide */ + HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_CNT), + PIOS_USB_BOARD_HID_DATA_LENGTH-1, /* Need to leave room for a report ID */ + HID_MAIN_ITEM_1 (HID_TAG_MAIN_OUTPUT), + 0x82, /* Volatile, Variable */ + + HID_MAIN_ITEM_0 (HID_TAG_MAIN_ENDCOLLECTION), +}; + +struct usb_config_hid_cdc { + struct usb_configuration_desc config; + struct usb_interface_association_desc iad; + struct usb_interface_desc hid_if; + struct usb_hid_desc hid; + struct usb_endpoint_desc hid_in; + struct usb_endpoint_desc hid_out; + struct usb_interface_desc cdc_control_if; + struct usb_cdc_header_func_desc cdc_header; + struct usb_cdc_callmgmt_func_desc cdc_callmgmt; + struct usb_cdc_acm_func_desc cdc_acm; + struct usb_cdc_union_func_desc cdc_union; + struct usb_endpoint_desc cdc_mgmt_in; + struct usb_interface_desc cdc_data_if; + struct usb_endpoint_desc cdc_in; + struct usb_endpoint_desc cdc_out; +} __attribute__((packed)); + +static const struct usb_config_hid_cdc config_hid_cdc = { .config = { .bLength = sizeof(struct usb_configuration_desc), .bDescriptorType = USB_DESC_TYPE_CONFIGURATION, - .wTotalLength = htousbs(sizeof(struct usb_board_config)), + .wTotalLength = htousbs(sizeof(struct usb_config_hid_cdc)), .bNumInterfaces = 3, .bConfigurationValue = 1, .iConfiguration = 0, @@ -86,7 +151,7 @@ const struct usb_board_config PIOS_USB_BOARD_Configuration = { .bCountryCode = 0, .bNumDescriptors = 1, .bClassDescriptorType = USB_DESC_TYPE_REPORT, - .wItemLength = htousbs(sizeof(PIOS_USB_BOARD_HidReportDescriptor)), + .wItemLength = htousbs(sizeof(hid_report_desc)), }, .hid_in = { .bLength = sizeof(struct usb_endpoint_desc), @@ -178,100 +243,14 @@ const struct usb_board_config PIOS_USB_BOARD_Configuration = { }, }; -const uint8_t PIOS_USB_BOARD_HidReportDescriptor[] = { - HID_GLOBAL_ITEM_2 (HID_TAG_GLOBAL_USAGE_PAGE), - 0x9C, 0xFF, /* Usage Page 0xFF9C (Vendor Defined) */ - HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), - 0x01, /* Usage ID 0x0001 (0x01-0x1F uaually for top-level collections) */ +int32_t PIOS_USB_DESC_HID_CDC_Init(void) +{ + PIOS_USBHOOK_RegisterConfig(1, (uint8_t *)&config_hid_cdc, sizeof(config_hid_cdc)); - HID_MAIN_ITEM_1 (HID_TAG_MAIN_COLLECTION), - 0x01, /* Application */ + PIOS_USBHOOK_RegisterDevice((uint8_t *)&device_desc, sizeof(device_desc)); - /* Device -> Host emulated serial channel */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_ID), - 0x01, /* OpenPilot emulated serial channel (Device -> Host) */ - HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), - 0x02, - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MIN), - 0x00, /* Values range from min = 0x00 */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MAX), - 0xFF, /* Values range to max = 0xFF */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_SIZE), - 0x08, /* 8 bits wide */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_CNT), - PIOS_USB_BOARD_HID_DATA_LENGTH-1, /* Need to leave room for a report ID */ - HID_MAIN_ITEM_1 (HID_TAG_MAIN_INPUT), - 0x03, /* Variable, Constant (read-only) */ + PIOS_USBHOOK_RegisterHidInterface((uint8_t *)&(config_hid_cdc.hid_if), sizeof(config_hid_cdc.hid_if)); + PIOS_USBHOOK_RegisterHidReport((uint8_t *)hid_report_desc, sizeof(hid_report_desc)); - /* Host -> Host emulated serial channel */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_ID), - 0x02, /* OpenPilot emulated Serial Channel (Host -> Device) */ - HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), - 0x02, - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MIN), - 0x00, /* Values range from min = 0x00 */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_LOGICAL_MAX), - 0xFF, /* Values range to max = 0xFF */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_SIZE), - 0x08, /* 8 bits wide */ - HID_GLOBAL_ITEM_1 (HID_TAG_GLOBAL_REPORT_CNT), - PIOS_USB_BOARD_HID_DATA_LENGTH-1, /* Need to leave room for a report ID */ - HID_MAIN_ITEM_1 (HID_TAG_MAIN_OUTPUT), - 0x82, /* Volatile, Variable */ - - HID_MAIN_ITEM_0 (HID_TAG_MAIN_ENDCOLLECTION), -}; - -const struct usb_string_langid PIOS_USB_BOARD_StringLangID = { - .bLength = sizeof(PIOS_USB_BOARD_StringLangID), - .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), -}; - -const uint8_t PIOS_USB_BOARD_StringVendorID[] = { - sizeof(PIOS_USB_BOARD_StringVendorID), - USB_DESC_TYPE_STRING, - 'o', 0, - 'p', 0, - 'e', 0, - 'n', 0, - 'p', 0, - 'i', 0, - 'l', 0, - 'o', 0, - 't', 0, - '.', 0, - 'o', 0, - 'r', 0, - 'g', 0 -}; - -uint8_t PIOS_USB_BOARD_StringSerial[] = { - sizeof(PIOS_USB_BOARD_StringSerial), - USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 -}; + return 0; +} diff --git a/flight/PiOS/Common/pios_usb_desc_hid_only.c b/flight/PiOS/Common/pios_usb_desc_hid_only.c index 913c18b16..168efe841 100644 --- a/flight/PiOS/Common/pios_usb_desc_hid_only.c +++ b/flight/PiOS/Common/pios_usb_desc_hid_only.c @@ -28,9 +28,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_usb_desc_hid_only_priv.h" /* exported API */ +#include "pios_usb_defs.h" /* struct usb_*, USB_* */ +#include "pios_usb_board_data.h" /* PIOS_USB_BOARD_* */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_Register* */ -const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor = { +static const struct usb_device_desc device_desc = { .bLength = sizeof(struct usb_device_desc), .bDescriptorType = USB_DESC_TYPE_DEVICE, .bcdUSB = htousbs(0x0200), @@ -47,56 +50,7 @@ const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor = { .bNumConfigurations = 1, }; -const struct usb_board_config PIOS_USB_BOARD_Configuration = { - .config = { - .bLength = sizeof(struct usb_configuration_desc), - .bDescriptorType = USB_DESC_TYPE_CONFIGURATION, - .wTotalLength = htousbs(sizeof(struct usb_board_config)), - .bNumInterfaces = 1, - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0xC0, - .bMaxPower = 250/2, /* in units of 2ma */ - }, - .hid_if = { - .bLength = sizeof(struct usb_interface_desc), - .bDescriptorType = USB_DESC_TYPE_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_INTERFACE_CLASS_HID, - .bInterfaceSubClass = 0, /* no boot */ - .nInterfaceProtocol = 0, /* none */ - .iInterface = 0, - }, - .hid = { - .bLength = sizeof(struct usb_hid_desc), - .bDescriptorType = USB_DESC_TYPE_HID, - .bcdHID = htousbs(0x0110), - .bCountryCode = 0, - .bNumDescriptors = 1, - .bClassDescriptorType = USB_DESC_TYPE_REPORT, - .wItemLength = htousbs(sizeof(PIOS_USB_BOARD_HidReportDescriptor)), - }, - .hid_in = { - .bLength = sizeof(struct usb_endpoint_desc), - .bDescriptorType = USB_DESC_TYPE_ENDPOINT, - .bEndpointAddress = USB_EP_IN(1), - .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, - .wMaxPacketSize = htousbs(PIOS_USB_BOARD_HID_DATA_LENGTH), - .bInterval = 4, /* ms */ - }, - .hid_out = { - .bLength = sizeof(struct usb_endpoint_desc), - .bDescriptorType = USB_DESC_TYPE_ENDPOINT, - .bEndpointAddress = USB_EP_OUT(1), - .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, - .wMaxPacketSize = htousbs(PIOS_USB_BOARD_HID_DATA_LENGTH), - .bInterval = 4, /* ms */ - }, -}; - -const uint8_t PIOS_USB_BOARD_HidReportDescriptor[] = { +static const uint8_t hid_report_desc[36] = { HID_GLOBAL_ITEM_2 (HID_TAG_GLOBAL_USAGE_PAGE), 0x9C, 0xFF, /* Usage Page 0xFF9C (Vendor Defined) */ HID_LOCAL_ITEM_1 (HID_TAG_LOCAL_USAGE), @@ -140,56 +94,71 @@ const uint8_t PIOS_USB_BOARD_HidReportDescriptor[] = { HID_MAIN_ITEM_0 (HID_TAG_MAIN_ENDCOLLECTION), }; -const struct usb_string_langid PIOS_USB_BOARD_StringLangID = { - .bLength = sizeof(PIOS_USB_BOARD_StringLangID), - .bDescriptorType = USB_DESC_TYPE_STRING, - .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +struct usb_config_hid_only { + struct usb_configuration_desc config; + struct usb_interface_desc hid_if; + struct usb_hid_desc hid; + struct usb_endpoint_desc hid_in; + struct usb_endpoint_desc hid_out; +} __attribute__((packed)); + +const struct usb_config_hid_only config_hid_only = { + .config = { + .bLength = sizeof(struct usb_configuration_desc), + .bDescriptorType = USB_DESC_TYPE_CONFIGURATION, + .wTotalLength = htousbs(sizeof(struct usb_config_hid_only)), + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 250/2, /* in units of 2ma */ + }, + .hid_if = { + .bLength = sizeof(struct usb_interface_desc), + .bDescriptorType = USB_DESC_TYPE_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_INTERFACE_CLASS_HID, + .bInterfaceSubClass = 0, /* no boot */ + .nInterfaceProtocol = 0, /* none */ + .iInterface = 0, + }, + .hid = { + .bLength = sizeof(struct usb_hid_desc), + .bDescriptorType = USB_DESC_TYPE_HID, + .bcdHID = htousbs(0x0110), + .bCountryCode = 0, + .bNumDescriptors = 1, + .bClassDescriptorType = USB_DESC_TYPE_REPORT, + .wItemLength = htousbs(sizeof(hid_report_desc)), + }, + .hid_in = { + .bLength = sizeof(struct usb_endpoint_desc), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_IN(1), + .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, + .wMaxPacketSize = htousbs(PIOS_USB_BOARD_HID_DATA_LENGTH), + .bInterval = 4, /* ms */ + }, + .hid_out = { + .bLength = sizeof(struct usb_endpoint_desc), + .bDescriptorType = USB_DESC_TYPE_ENDPOINT, + .bEndpointAddress = USB_EP_OUT(1), + .bmAttributes = USB_EP_ATTR_TT_INTERRUPT, + .wMaxPacketSize = htousbs(PIOS_USB_BOARD_HID_DATA_LENGTH), + .bInterval = 4, /* ms */ + }, }; -const uint8_t PIOS_USB_BOARD_StringVendorID[] = { - sizeof(PIOS_USB_BOARD_StringVendorID), - USB_DESC_TYPE_STRING, - 'o', 0, - 'p', 0, - 'e', 0, - 'n', 0, - 'p', 0, - 'i', 0, - 'l', 0, - 'o', 0, - 't', 0, - '.', 0, - 'o', 0, - 'r', 0, - 'g', 0 -}; +int32_t PIOS_USB_DESC_HID_ONLY_Init(void) +{ + PIOS_USBHOOK_RegisterConfig(1, (uint8_t *)&config_hid_only, sizeof(config_hid_only)); -uint8_t PIOS_USB_BOARD_StringSerial[] = { - sizeof(PIOS_USB_BOARD_StringSerial), - USB_DESC_TYPE_STRING, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 -}; + PIOS_USBHOOK_RegisterDevice((uint8_t *)&device_desc, sizeof(device_desc)); + + PIOS_USBHOOK_RegisterHidInterface((uint8_t *)&(config_hid_only.hid_if), sizeof(config_hid_only.hid_if)); + PIOS_USBHOOK_RegisterHidReport((uint8_t *)hid_report_desc, sizeof(hid_report_desc)); + + return 0; +} diff --git a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_core.h b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_core.h index 84f975da6..7e606e44b 100644 --- a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_core.h +++ b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_core.h @@ -35,7 +35,7 @@ typedef enum _CONTROL_STATE typedef struct OneDescriptor { - uint8_t *Descriptor; + const uint8_t *Descriptor; uint16_t Descriptor_Size; } ONE_DESCRIPTOR, *PONE_DESCRIPTOR; @@ -80,7 +80,8 @@ typedef struct _ENDPOINT_INFO uint16_t Usb_wLength; uint16_t Usb_wOffset; uint16_t PacketSize; - uint8_t *(*CopyData)(uint16_t Length); + const uint8_t *(*CopyDataIn)(uint16_t Length); + uint8_t *(*CopyDataOut)(uint16_t Length); }ENDPOINT_INFO; /*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/ @@ -169,9 +170,9 @@ typedef struct _DEVICE_PROP RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting); - uint8_t* (*GetDeviceDescriptor)(uint16_t Length); - uint8_t* (*GetConfigDescriptor)(uint16_t Length); - uint8_t* (*GetStringDescriptor)(uint16_t Length); + const uint8_t* (*GetDeviceDescriptor)(uint16_t Length); + const uint8_t* (*GetConfigDescriptor)(uint16_t Length); + const uint8_t* (*GetStringDescriptor)(uint16_t Length); /* This field is not used in current library version. It is kept only for compatibility with previous versions */ @@ -221,13 +222,13 @@ uint8_t In0_Process(void); RESULT Standard_SetEndPointFeature(void); RESULT Standard_SetDeviceFeature(void); -uint8_t *Standard_GetConfiguration(uint16_t Length); +const uint8_t *Standard_GetConfiguration(uint16_t Length); RESULT Standard_SetConfiguration(void); -uint8_t *Standard_GetInterface(uint16_t Length); +const uint8_t *Standard_GetInterface(uint16_t Length); RESULT Standard_SetInterface(void); -uint8_t *Standard_GetDescriptorData(uint16_t Length, const ONE_DESCRIPTOR * pDesc); +const uint8_t *Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR *pDesc); -uint8_t *Standard_GetStatus(uint16_t Length); +const uint8_t *Standard_GetStatus(uint16_t Length); RESULT Standard_ClearFeature(void); void SetDeviceAddress(uint8_t); void NOP_Process(void); diff --git a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_mem.h b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_mem.h index 4d43fbe8c..f7f0ace12 100644 --- a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_mem.h +++ b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/inc/usb_mem.h @@ -22,7 +22,7 @@ /* Exported constants --------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */ -void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +void UserToPMABufferCopy(const uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); /* External variables --------------------------------------------------------*/ diff --git a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_core.c b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_core.c index fb5ca3e40..75ddaa42e 100644 --- a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_core.c +++ b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_core.c @@ -58,7 +58,7 @@ static void Data_Setup0(void); * Return : Return 1 , if the request is invalid when "Length" is 0. * Return "Buffer" if the "Length" is not 0. *******************************************************************************/ -uint8_t *Standard_GetConfiguration(uint16_t Length) +const uint8_t *Standard_GetConfiguration(uint16_t Length) { if (Length == 0) { @@ -104,7 +104,7 @@ RESULT Standard_SetConfiguration(void) * Return : Return 0, if the request is invalid when "Length" is 0. * Return "Buffer" if the "Length" is not 0. *******************************************************************************/ -uint8_t *Standard_GetInterface(uint16_t Length) +const uint8_t *Standard_GetInterface(uint16_t Length) { if (Length == 0) { @@ -160,7 +160,7 @@ RESULT Standard_SetInterface(void) * Return : Return 0, if the request is at end of data block, * or is invalid when "Length" is 0. *******************************************************************************/ -uint8_t *Standard_GetStatus(uint16_t Length) +const uint8_t *Standard_GetStatus(uint16_t Length) { if (Length == 0) { @@ -415,7 +415,7 @@ RESULT Standard_SetDeviceFeature(void) * wOffset The buffer pointed by this address contains at least * Length bytes. *******************************************************************************/ -uint8_t *Standard_GetDescriptorData(uint16_t Length, const ONE_DESCRIPTOR * pDesc) +const uint8_t *Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc) { uint32_t wOffset; @@ -443,7 +443,7 @@ void DataStageOut(void) save_rLength = pEPinfo->Usb_rLength; - if (pEPinfo->CopyData && save_rLength) + if (pEPinfo->CopyDataOut && save_rLength) { uint8_t *Buffer; uint32_t Length; @@ -454,7 +454,7 @@ void DataStageOut(void) Length = save_rLength; } - Buffer = (*pEPinfo->CopyData)(Length); + Buffer = (*pEPinfo->CopyDataOut)(Length); pEPinfo->Usb_rLength -= Length; pEPinfo->Usb_rOffset += Length; @@ -503,7 +503,7 @@ void DataStageIn(void) uint32_t save_wLength = pEPinfo->Usb_wLength; uint32_t ControlState = pInformation->ControlState; - uint8_t *DataBuffer; + const uint8_t *DataBuffer; uint32_t Length; if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) @@ -540,7 +540,7 @@ void DataStageIn(void) Length = save_wLength; } - DataBuffer = (*pEPinfo->CopyData)(Length); + DataBuffer = (*pEPinfo->CopyDataIn)(Length); #ifdef STM32F10X_CL PCD_EP_Write (ENDP0, DataBuffer, Length); @@ -697,7 +697,7 @@ exit_NoData_Setup0: *******************************************************************************/ void Data_Setup0(void) { - uint8_t *(*CopyRoutine)(uint16_t); + const uint8_t *(*CopyRoutine)(uint16_t); RESULT Result; uint32_t Request_No = pInformation->USBbRequest; @@ -802,7 +802,7 @@ void Data_Setup0(void) if (CopyRoutine) { pInformation->Ctrl_Info.Usb_wOffset = wOffset; - pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.CopyDataIn = CopyRoutine; /* sb in the original the cast to word was directly */ /* now the cast is made step by step */ (*CopyRoutine)(0); diff --git a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_mem.c b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_mem.c index e729b844c..ca50a23c4 100644 --- a/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_mem.c +++ b/flight/PiOS/STM32F10x/Libraries/STM32_USB-FS-Device_Driver/src/usb_mem.c @@ -33,7 +33,7 @@ * Output : None. * Return : None . *******************************************************************************/ -void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +void UserToPMABufferCopy(const uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) { uint32_t n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */ uint32_t i, temp1, temp2; diff --git a/flight/PiOS/STM32F10x/pios_usb.c b/flight/PiOS/STM32F10x/pios_usb.c index df17777c7..15decfca1 100644 --- a/flight/PiOS/STM32F10x/pios_usb.c +++ b/flight/PiOS/STM32F10x/pios_usb.c @@ -123,13 +123,6 @@ int32_t PIOS_USB_Init(uint32_t * usb_id, const struct pios_usb_cfg * cfg) /* Enable the USB clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); - /* Update the USB serial number from the chip */ - uint8_t sn[25]; - PIOS_SYS_SerialNumberGet((char *)sn); - for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < PIOS_USB_BOARD_StringSerial[0]; i++) { - PIOS_USB_BOARD_StringSerial[2 + 2 * i] = sn[i]; - } - USB_Init(); USB_SIL_Init(); diff --git a/flight/PiOS/STM32F10x/pios_usb_cdc.c b/flight/PiOS/STM32F10x/pios_usb_cdc.c index 994c276ea..4bb1303d9 100644 --- a/flight/PiOS/STM32F10x/pios_usb_cdc.c +++ b/flight/PiOS/STM32F10x/pios_usb_cdc.c @@ -346,7 +346,7 @@ RESULT PIOS_USB_CDC_SetLineCoding(void) return USB_SUCCESS; } -uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length) +const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length) { struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)pios_usb_cdc_id; diff --git a/flight/PiOS/STM32F10x/pios_usbhook.c b/flight/PiOS/STM32F10x/pios_usbhook.c index ade1f8ac1..7800faed1 100644 --- a/flight/PiOS/STM32F10x/pios_usbhook.c +++ b/flight/PiOS/STM32F10x/pios_usbhook.c @@ -36,6 +36,48 @@ #include "pios_usb_cdc_priv.h" /* PIOS_USB_CDC_* */ #include "pios_usb_board_data.h" /* PIOS_USB_BOARD_* */ +static ONE_DESCRIPTOR Device_Descriptor; + +void PIOS_USBHOOK_RegisterDevice(const uint8_t * desc, uint16_t desc_size) +{ + Device_Descriptor.Descriptor = desc; + Device_Descriptor.Descriptor_Size = desc_size; +} + +static ONE_DESCRIPTOR Config_Descriptor; + +void PIOS_USBHOOK_RegisterConfig(uint8_t config_id, const uint8_t * desc, uint16_t desc_size) +{ + Config_Descriptor.Descriptor = desc; + Config_Descriptor.Descriptor_Size = desc_size; +} + +static ONE_DESCRIPTOR String_Descriptor[4]; + +void PIOS_USBHOOK_RegisterString(enum usb_string_desc string_id, const uint8_t * desc, uint16_t desc_size) +{ + if (string_id < NELEMENTS(String_Descriptor)) { + String_Descriptor[string_id].Descriptor = desc; + String_Descriptor[string_id].Descriptor_Size = desc_size; + } +} + +static ONE_DESCRIPTOR Hid_Interface_Descriptor; + +void PIOS_USBHOOK_RegisterHidInterface(const uint8_t * desc, uint16_t desc_size) +{ + Hid_Interface_Descriptor.Descriptor = desc; + Hid_Interface_Descriptor.Descriptor_Size = desc_size; +} + +static ONE_DESCRIPTOR Hid_Report_Descriptor; + +void PIOS_USBHOOK_RegisterHidReport(const uint8_t * desc, uint16_t desc_size) +{ + Hid_Report_Descriptor.Descriptor = desc; + Hid_Report_Descriptor.Descriptor_Size = desc_size; +} + #include "stm32f10x.h" /* __IO */ __IO uint8_t EXTI_Enable; @@ -53,9 +95,9 @@ static void PIOS_USBHOOK_Status_Out(void); static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo); static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo); static RESULT PIOS_USBHOOK_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting); -static uint8_t *PIOS_USBHOOK_GetDeviceDescriptor(uint16_t Length); -static uint8_t *PIOS_USBHOOK_GetConfigDescriptor(uint16_t Length); -static uint8_t *PIOS_USBHOOK_GetStringDescriptor(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetDeviceDescriptor(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetConfigDescriptor(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetStringDescriptor(uint16_t Length); DEVICE_PROP Device_Property = { .Init = PIOS_USBHOOK_Init, @@ -87,49 +129,10 @@ USER_STANDARD_REQUESTS User_Standard_Requests = { .User_SetDeviceAddress = PIOS_USBHOOK_SetDeviceAddress }; -const static ONE_DESCRIPTOR Device_Descriptor = { - (uint8_t *) &PIOS_USB_BOARD_DeviceDescriptor, - sizeof(PIOS_USB_BOARD_DeviceDescriptor), -}; - -static ONE_DESCRIPTOR Config_Descriptor = { - (uint8_t *) &PIOS_USB_BOARD_Configuration, - sizeof(PIOS_USB_BOARD_Configuration), -}; - -const static ONE_DESCRIPTOR Hid_Report_Descriptor = { - (uint8_t *) &PIOS_USB_BOARD_HidReportDescriptor, - sizeof(PIOS_USB_BOARD_HidReportDescriptor), -}; - -const static ONE_DESCRIPTOR Hid_Interface_Descriptor = { - (uint8_t *) &PIOS_USB_BOARD_Configuration.hid_if, - sizeof(PIOS_USB_BOARD_Configuration.hid_if), -}; - -const static ONE_DESCRIPTOR String_Descriptor[] = { - { - (uint8_t *) &PIOS_USB_BOARD_StringLangID, - sizeof(PIOS_USB_BOARD_StringLangID), - }, - { - (uint8_t *) PIOS_USB_BOARD_StringVendorID, - sizeof(PIOS_USB_BOARD_StringVendorID), - }, - { - (uint8_t *) PIOS_USB_BOARD_StringProductID, - sizeof(PIOS_USB_BOARD_StringProductID), - }, - { - (uint8_t *) PIOS_USB_BOARD_StringSerial, - sizeof(PIOS_USB_BOARD_StringSerial), - }, -}; - static RESULT PIOS_USBHOOK_SetProtocol(void); -static uint8_t *PIOS_USBHOOK_GetProtocolValue(uint16_t Length); -static uint8_t *PIOS_USBHOOK_GetReportDescriptor(uint16_t Length); -static uint8_t *PIOS_USBHOOK_GetHIDDescriptor(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetProtocolValue(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetReportDescriptor(uint16_t Length); +static const uint8_t *PIOS_USBHOOK_GetHIDDescriptor(uint16_t Length); /******************************************************************************* * Function Name : PIOS_USBHOOK_Init. @@ -140,11 +143,8 @@ static uint8_t *PIOS_USBHOOK_GetHIDDescriptor(uint16_t Length); *******************************************************************************/ static void PIOS_USBHOOK_Init(void) { - /* Update the serial number string descriptor with the data from the unique - ID */ - //Get_SerialNum(); - pInformation->Current_Configuration = 0; + /* Connect the device */ PowerOn(); @@ -292,7 +292,7 @@ static void PIOS_USBHOOK_Status_Out(void) *******************************************************************************/ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo) { - uint8_t *(*CopyRoutine) (uint16_t); + const uint8_t *(*CopyRoutine) (uint16_t); CopyRoutine = NULL; @@ -350,7 +350,7 @@ static RESULT PIOS_USBHOOK_Data_Setup(uint8_t RequestNo) return USB_UNSUPPORT; } - pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.CopyDataIn = CopyRoutine; pInformation->Ctrl_Info.Usb_wOffset = 0; (*CopyRoutine) (0); return USB_SUCCESS; @@ -405,7 +405,7 @@ static RESULT PIOS_USBHOOK_NoData_Setup(uint8_t RequestNo) * Output : None. * Return : The address of the device descriptor. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetDeviceDescriptor(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetDeviceDescriptor(uint16_t Length) { return Standard_GetDescriptorData(Length, &Device_Descriptor); } @@ -417,7 +417,7 @@ static uint8_t *PIOS_USBHOOK_GetDeviceDescriptor(uint16_t Length) * Output : None. * Return : The address of the configuration descriptor. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetConfigDescriptor(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetConfigDescriptor(uint16_t Length) { return Standard_GetDescriptorData(Length, &Config_Descriptor); } @@ -429,7 +429,7 @@ static uint8_t *PIOS_USBHOOK_GetConfigDescriptor(uint16_t Length) * Output : None. * Return : The address of the string descriptors. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetStringDescriptor(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetStringDescriptor(uint16_t Length) { uint8_t wValue0 = pInformation->USBwValue0; if (wValue0 > 4) { @@ -446,7 +446,7 @@ static uint8_t *PIOS_USBHOOK_GetStringDescriptor(uint16_t Length) * Output : None. * Return : The address of the configuration descriptor. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetReportDescriptor(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetReportDescriptor(uint16_t Length) { return Standard_GetDescriptorData(Length, &Hid_Report_Descriptor); } @@ -458,7 +458,7 @@ static uint8_t *PIOS_USBHOOK_GetReportDescriptor(uint16_t Length) * Output : None. * Return : The address of the configuration descriptor. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetHIDDescriptor(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetHIDDescriptor(uint16_t Length) { return Standard_GetDescriptorData(Length, &Hid_Interface_Descriptor); } @@ -503,7 +503,7 @@ static RESULT PIOS_USBHOOK_SetProtocol(void) * Output : None. * Return : address of the protcol value. *******************************************************************************/ -static uint8_t *PIOS_USBHOOK_GetProtocolValue(uint16_t Length) +static const uint8_t *PIOS_USBHOOK_GetProtocolValue(uint16_t Length) { if (Length == 0) { pInformation->Ctrl_Info.Usb_wLength = 1; diff --git a/flight/PiOS/inc/pios_usb_board_data_priv.h b/flight/PiOS/inc/pios_usb_board_data_priv.h new file mode 100644 index 000000000..49166c25f --- /dev/null +++ b/flight/PiOS/inc/pios_usb_board_data_priv.h @@ -0,0 +1 @@ +extern int32_t PIOS_USB_BOARD_DATA_Init(void); diff --git a/flight/PiOS/inc/pios_usb_cdc_priv.h b/flight/PiOS/inc/pios_usb_cdc_priv.h index e6b94bad8..74d6e347d 100644 --- a/flight/PiOS/inc/pios_usb_cdc_priv.h +++ b/flight/PiOS/inc/pios_usb_cdc_priv.h @@ -46,7 +46,7 @@ extern const struct pios_com_driver pios_usb_cdc_com_driver; extern int32_t PIOS_USB_CDC_Init(uint32_t * usbcdc_id, const struct pios_usb_cdc_cfg * cfg, uint32_t lower_id); -extern uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length); +extern const uint8_t *PIOS_USB_CDC_GetLineCoding(uint16_t Length); extern RESULT PIOS_USB_CDC_SetControlLineState(void); extern RESULT PIOS_USB_CDC_SetLineCoding(void); diff --git a/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h b/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h new file mode 100644 index 000000000..4836f4569 --- /dev/null +++ b/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h @@ -0,0 +1,8 @@ +#ifndef PIOS_USB_DESC_HID_CDC_PRIV_H +#define PIOS_USB_DESC_HID_CDC_PRIV_H + +#include + +extern int32_t PIOS_USB_DESC_HID_CDC_Init(void); + +#endif /* PIOS_USB_DESC_HID_CDC_PRIV_H */ diff --git a/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h b/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h new file mode 100644 index 000000000..5d161d233 --- /dev/null +++ b/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h @@ -0,0 +1,8 @@ +#ifndef PIOS_USB_DESC_HID_ONLY_PRIV_H +#define PIOS_USB_DESC_HID_ONLY_PRIV_H + +#include + +extern int32_t PIOS_USB_DESC_HID_ONLY_Init(void); + +#endif /* PIOS_USB_DESC_HID_ONLY_PRIV_H */ diff --git a/flight/PiOS/inc/pios_usbhook.h b/flight/PiOS/inc/pios_usbhook.h index d5f032450..f005a6fa1 100644 --- a/flight/PiOS/inc/pios_usbhook.h +++ b/flight/PiOS/inc/pios_usbhook.h @@ -47,5 +47,18 @@ typedef enum CDC_REQUESTS { SET_CONTROL_LINE_STATE = 0x23, } CDC_REQUESTS; +enum usb_string_desc { + USB_STRING_DESC_LANG = 0, + USB_STRING_DESC_VENDOR = 1, + USB_STRING_DESC_PRODUCT = 2, + USB_STRING_DESC_SERIAL = 3, +} __attribute__((packed)); + +extern void PIOS_USBHOOK_RegisterDevice(const uint8_t * desc, uint16_t desc_size); +extern void PIOS_USBHOOK_RegisterConfig(uint8_t config_id, const uint8_t * desc, uint16_t desc_size); +extern void PIOS_USBHOOK_RegisterString(enum usb_string_desc string_id, const uint8_t * desc, uint16_t desc_size); +extern void PIOS_USBHOOK_RegisterHidInterface(const uint8_t * desc, uint16_t desc_size); +extern void PIOS_USBHOOK_RegisterHidReport(const uint8_t * desc, uint16_t desc_size); + #endif /* PIOS_USBHOOK_H */ diff --git a/flight/PipXtreme/inc/pios_usb_board_data.h b/flight/PipXtreme/inc/pios_usb_board_data.h index 95dc03d73..d4f4daf0a 100644 --- a/flight/PipXtreme/inc/pios_usb_board_data.h +++ b/flight/PipXtreme/inc/pios_usb_board_data.h @@ -37,33 +37,6 @@ #include "pios_usb_defs.h" /* struct usb_* */ -struct usb_board_config { - struct usb_configuration_desc config; - struct usb_interface_desc hid_if; - struct usb_hid_desc hid; - struct usb_endpoint_desc hid_in; - struct usb_endpoint_desc hid_out; -} __attribute__((packed)); - -extern const struct usb_device_desc PIOS_USB_BOARD_DeviceDescriptor; -extern const struct usb_board_config PIOS_USB_BOARD_Configuration; -extern const struct usb_string_langid PIOS_USB_BOARD_StringLangID; - -/* NOTE NOTE NOTE - * - * Care must be taken to ensure that the _actual_ contents of - * these arrays (in each board's pios_usb_board_data.c) is no - * smaller than the stated sizes here or these descriptors - * will end up with trailing zeros on the wire. - * - * The compiler will catch any time that these definitions are - * too small. - */ -extern const uint8_t PIOS_USB_BOARD_HidReportDescriptor[36]; -extern const uint8_t PIOS_USB_BOARD_StringVendorID[28]; -extern const uint8_t PIOS_USB_BOARD_StringProductID[20]; -extern uint8_t PIOS_USB_BOARD_StringSerial[52]; - #define PIOS_USB_BOARD_PRODUCT_ID USB_PRODUCT_ID_PIPXTREME #define PIOS_USB_BOARD_DEVICE_VER USB_OP_DEVICE_VER(USB_OP_BOARD_ID_PIPXTREME, USB_OP_BOARD_MODE_FW) diff --git a/flight/PipXtreme/pios_board.c b/flight/PipXtreme/pios_board.c index 7da3705a8..ab6bcffef 100644 --- a/flight/PipXtreme/pios_board.c +++ b/flight/PipXtreme/pios_board.c @@ -324,6 +324,10 @@ static const struct pios_usb_cfg pios_usb_main_cfg = { }, }, }; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + #endif /* PIOS_INCLUDE_USB */ #if defined(PIOS_INCLUDE_USB_HID) @@ -369,10 +373,16 @@ void PIOS_Board_Init(void) { } #if defined(PIOS_INCLUDE_USB) - uint32_t pios_usb_id; - if (PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg)) { + /* Initialize board specific USB data */ + PIOS_USB_BOARD_DATA_Init(); + + if (PIOS_USB_DESC_HID_ONLY_Init()) { PIOS_Assert(0); } + + uint32_t pios_usb_id; + PIOS_USB_Init(&pios_usb_id, &pios_usb_main_cfg); + #if defined(PIOS_INCLUDE_USB_HID) && defined(PIOS_INCLUDE_COM) uint32_t pios_usb_hid_id; if (PIOS_USB_HID_Init(&pios_usb_hid_id, &pios_usb_hid_cfg, pios_usb_id)) { diff --git a/flight/PipXtreme/pios_usb_board_data.c b/flight/PipXtreme/pios_usb_board_data.c index d54ca6565..3e41e5ac9 100644 --- a/flight/PipXtreme/pios_usb_board_data.c +++ b/flight/PipXtreme/pios_usb_board_data.c @@ -29,9 +29,11 @@ */ #include "pios_usb_board_data.h" /* struct usb_*, USB_* */ +#include "pios_sys.h" /* PIOS_SYS_SerialNumberGet */ +#include "pios_usbhook.h" /* PIOS_USBHOOK_* */ -const uint8_t PIOS_USB_BOARD_StringProductID[] = { - sizeof(PIOS_USB_BOARD_StringProductID), +static const uint8_t usb_product_id[20] = { + sizeof(usb_product_id), USB_DESC_TYPE_STRING, 'P', 0, 'i', 0, @@ -44,3 +46,74 @@ const uint8_t PIOS_USB_BOARD_StringProductID[] = { 'e', 0, }; +static uint8_t usb_serial_number[52] = { + sizeof(usb_serial_number), + USB_DESC_TYPE_STRING, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0 +}; + +static const struct usb_string_langid usb_lang_id = { + .bLength = sizeof(usb_lang_id), + .bDescriptorType = USB_DESC_TYPE_STRING, + .bLangID = htousbs(USB_LANGID_ENGLISH_UK), +}; + +static const uint8_t usb_vendor_id[28] = { + sizeof(usb_vendor_id), + USB_DESC_TYPE_STRING, + 'o', 0, + 'p', 0, + 'e', 0, + 'n', 0, + 'p', 0, + 'i', 0, + 'l', 0, + 'o', 0, + 't', 0, + '.', 0, + 'o', 0, + 'r', 0, + 'g', 0 +}; + +int32_t PIOS_USB_BOARD_DATA_Init(void) +{ + /* Load device serial number into serial number string */ + uint8_t sn[25]; + PIOS_SYS_SerialNumberGet((char *)sn); + for (uint8_t i = 0; sn[i] != '\0' && (2 * i) < usb_serial_number[0]; i++) { + usb_serial_number[2 + 2 * i] = sn[i]; + } + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_PRODUCT, (uint8_t *)&usb_product_id, sizeof(usb_product_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_SERIAL, (uint8_t *)&usb_serial_number, sizeof(usb_serial_number)); + + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_LANG, (uint8_t *)&usb_lang_id, sizeof(usb_lang_id)); + PIOS_USBHOOK_RegisterString(USB_STRING_DESC_VENDOR, (uint8_t *)&usb_vendor_id, sizeof(usb_vendor_id)); + + return 0; +} diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index 1e34e0808..24727a080 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -12,6 +12,7 @@ + From ec6d5502252295db0881f17807d01b192fb23888 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 12 Nov 2011 21:34:47 -0500 Subject: [PATCH 29/72] i2c: allow i2c adapters to remap pin functions Allows us to support more complex pin configurations for i2c. --- flight/PiOS/STM32F10x/pios_i2c.c | 4 ++++ flight/PiOS/inc/pios_i2c_priv.h | 1 + 2 files changed, 5 insertions(+) diff --git a/flight/PiOS/STM32F10x/pios_i2c.c b/flight/PiOS/STM32F10x/pios_i2c.c index 90c208133..e1bdb44f8 100644 --- a/flight/PiOS/STM32F10x/pios_i2c.c +++ b/flight/PiOS/STM32F10x/pios_i2c.c @@ -891,6 +891,10 @@ int32_t PIOS_I2C_Init(uint32_t * i2c_id, const struct pios_i2c_adapter_cfg * cfg break; } + if (i2c_adapter->cfg->remap) { + GPIO_PinRemapConfig(i2c_adapter->cfg->remap, ENABLE); + } + /* Initialize the state machine */ i2c_adapter_fsm_init(i2c_adapter); diff --git a/flight/PiOS/inc/pios_i2c_priv.h b/flight/PiOS/inc/pios_i2c_priv.h index 5834fef34..a10fe0603 100644 --- a/flight/PiOS/inc/pios_i2c_priv.h +++ b/flight/PiOS/inc/pios_i2c_priv.h @@ -37,6 +37,7 @@ struct pios_i2c_adapter_cfg { uint32_t transfer_timeout_ms; struct stm32_gpio scl; struct stm32_gpio sda; + uint32_t remap; struct stm32_irq event; struct stm32_irq error; }; From feacec468d6b0127716fa23183977faa2fa4abad Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 12 Nov 2011 21:39:41 -0500 Subject: [PATCH 30/72] i2c: compile-time decoupling of i2c devices from adapters This allows each device to be moved (at compile time) to a different adapter. This is the first step to allowing devices to be attached to different i2c adapters. --- flight/PiOS/Boards/STM32103CB_CC_Rev1.h | 1 + flight/PiOS/Boards/STM3210E_OP.h | 1 + flight/PiOS/Common/pios_i2c_esc.c | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index 437a49109..ff37debdc 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -112,6 +112,7 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 #define PIOS_I2C_MAX_DEVS 1 extern uint32_t pios_i2c_main_adapter_id; #define PIOS_I2C_MAIN_ADAPTER (pios_i2c_main_adapter_id) +#define PIOS_I2C_ESC_ADAPTER (pios_i2c_main_adapter_id) //------------------------- // SPI diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index a7754c2ed..1cc4249f3 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -115,6 +115,7 @@ TIM8 | Servo 5 | Servo 6 | Servo 7 | Servo 8 #define PIOS_I2C_MAX_DEVS 1 extern uint32_t pios_i2c_main_adapter_id; #define PIOS_I2C_MAIN_ADAPTER (pios_i2c_main_adapter_id) +#define PIOS_I2C_ESC_ADAPTER (pios_i2c_main_adapter_id) //------------------------ // PIOS_BMP085 diff --git a/flight/PiOS/Common/pios_i2c_esc.c b/flight/PiOS/Common/pios_i2c_esc.c index fdb58eba0..d440bfa48 100644 --- a/flight/PiOS/Common/pios_i2c_esc.c +++ b/flight/PiOS/Common/pios_i2c_esc.c @@ -93,7 +93,7 @@ bool PIOS_I2C_ESC_SetSpeed(uint8_t speed[4]) } }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_ESC_ADAPTER, txn_list, NELEMENTS(txn_list)); } bool PIOS_SetMKSpeed(uint8_t motornum, uint8_t speed) { @@ -115,7 +115,7 @@ bool PIOS_SetMKSpeed(uint8_t motornum, uint8_t speed) { } }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_ESC_ADAPTER, txn_list, NELEMENTS(txn_list)); } bool PIOS_SetAstec4Address(uint8_t new_address) { @@ -134,7 +134,7 @@ bool PIOS_SetAstec4Address(uint8_t new_address) { } }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_ESC_ADAPTER, txn_list, NELEMENTS(txn_list)); } bool PIOS_SetAstec4Speed(uint8_t motornum, uint8_t speed) { @@ -161,7 +161,7 @@ bool PIOS_SetAstec4Speed(uint8_t motornum, uint8_t speed) { } }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_ESC_ADAPTER, txn_list, NELEMENTS(txn_list)); } #endif From a0089f072a03d878403efdfe2f263e0379a1a0c7 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 12 Nov 2011 21:50:53 -0500 Subject: [PATCH 31/72] i2c: rename main adapter to flexi adapter on CC --- flight/CopterControl/System/pios_board.c | 20 ++++++++++---------- flight/PiOS/Boards/STM32103CB_CC_Rev1.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index ffdde4759..4e0495776 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -903,12 +903,12 @@ const struct pios_pwm_cfg pios_pwm_cfg = { * I2C Adapters */ -void PIOS_I2C_main_adapter_ev_irq_handler(void); -void PIOS_I2C_main_adapter_er_irq_handler(void); -void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_ev_irq_handler"))); -void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_er_irq_handler"))); +void PIOS_I2C_flexi_adapter_ev_irq_handler(void); +void PIOS_I2C_flexi_adapter_er_irq_handler(void); +void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_ev_irq_handler"))); +void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_er_irq_handler"))); -static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { +static const struct pios_i2c_adapter_cfg pios_i2c_flexi_adapter_cfg = { .regs = I2C2, .init = { .I2C_Mode = I2C_Mode_I2C, @@ -955,17 +955,17 @@ static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { }, }; -uint32_t pios_i2c_main_adapter_id; -void PIOS_I2C_main_adapter_ev_irq_handler(void) +uint32_t pios_i2c_flexi_adapter_id; +void PIOS_I2C_flexi_adapter_ev_irq_handler(void) { /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id); + PIOS_I2C_EV_IRQ_Handler(pios_i2c_flexi_adapter_id); } -void PIOS_I2C_main_adapter_er_irq_handler(void) +void PIOS_I2C_flexi_adapter_er_irq_handler(void) { /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id); + PIOS_I2C_ER_IRQ_Handler(pios_i2c_flexi_adapter_id); } #endif /* PIOS_INCLUDE_I2C */ diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index ff37debdc..e908345b7 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -110,9 +110,9 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 // See also pios_board.c //------------------------ #define PIOS_I2C_MAX_DEVS 1 -extern uint32_t pios_i2c_main_adapter_id; -#define PIOS_I2C_MAIN_ADAPTER (pios_i2c_main_adapter_id) -#define PIOS_I2C_ESC_ADAPTER (pios_i2c_main_adapter_id) +extern uint32_t pios_i2c_flexi_adapter_id; +#define PIOS_I2C_MAIN_ADAPTER (pios_i2c_flexi_adapter_id) +#define PIOS_I2C_ESC_ADAPTER (pios_i2c_flexi_adapter_id) //------------------------- // SPI From 4cb0c4133855742b00a1a35a1375c1019d0403e4 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Fri, 25 Nov 2011 19:38:16 -0500 Subject: [PATCH 32/72] bmp085: only use eoc and drdy gpios when available When the bmp085 chip is on an external board, we don't have access to the eoc and drdy gpio lines. Only use them when available. --- flight/Modules/Altitude/altitude.c | 8 ++++++++ flight/PiOS/Boards/STM3210E_INS.h | 1 + flight/PiOS/Boards/STM3210E_OP.h | 1 + flight/PiOS/Common/pios_bmp085.c | 10 ++++++++++ flight/PiOS/STM32F10x/pios_exti.c | 2 +- 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/flight/Modules/Altitude/altitude.c b/flight/Modules/Altitude/altitude.c index d1655aaa8..163258c1c 100644 --- a/flight/Modules/Altitude/altitude.c +++ b/flight/Modules/Altitude/altitude.c @@ -144,13 +144,21 @@ static void altitudeTask(void *parameters) #endif // Update the temperature data PIOS_BMP085_StartADC(TemperatureConv); +#ifdef PIOS_BMP085_HAS_GPIOS xSemaphoreTake(PIOS_BMP085_EOC, portMAX_DELAY); +#else + vTaskDelay(5 / portTICK_RATE_MS); +#endif PIOS_BMP085_ReadADC(); alt_ds_temp += PIOS_BMP085_GetTemperature(); // Update the pressure data PIOS_BMP085_StartADC(PressureConv); +#ifdef PIOS_BMP085_HAS_GPIOS xSemaphoreTake(PIOS_BMP085_EOC, portMAX_DELAY); +#else + vTaskDelay(26 / portTICK_RATE_MS); +#endif PIOS_BMP085_ReadADC(); alt_ds_pres += PIOS_BMP085_GetPressure(); diff --git a/flight/PiOS/Boards/STM3210E_INS.h b/flight/PiOS/Boards/STM3210E_INS.h index d661e8b96..5973bd168 100644 --- a/flight/PiOS/Boards/STM3210E_INS.h +++ b/flight/PiOS/Boards/STM3210E_INS.h @@ -106,6 +106,7 @@ extern uint32_t pios_i2c_gyro_adapter_id; //------------------------ // PIOS_BMP085 //------------------------ +#define PIOS_BMP085_HAS_GPIOS #define PIOS_BMP085_EOC_GPIO_PORT GPIOC #define PIOS_BMP085_EOC_GPIO_PIN GPIO_Pin_2 #define PIOS_BMP085_EOC_PORT_SOURCE GPIO_PortSourceGPIOC diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index 1cc4249f3..87d4ab4a0 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -120,6 +120,7 @@ extern uint32_t pios_i2c_main_adapter_id; //------------------------ // PIOS_BMP085 //------------------------ +#define PIOS_BMP085_HAS_GPIOS #define PIOS_BMP085_EOC_GPIO_PORT GPIOC #define PIOS_BMP085_EOC_GPIO_PIN GPIO_Pin_15 #define PIOS_BMP085_EOC_PORT_SOURCE GPIO_PortSourceGPIOC diff --git a/flight/PiOS/Common/pios_bmp085.c b/flight/PiOS/Common/pios_bmp085.c index 9a6a2310f..5d3668b2f 100644 --- a/flight/PiOS/Common/pios_bmp085.c +++ b/flight/PiOS/Common/pios_bmp085.c @@ -38,12 +38,17 @@ /* Glocal Variables */ ConversionTypeTypeDef CurrentRead; + +#ifdef PIOS_BMP085_HAS_GPIOS + #if defined(PIOS_INCLUDE_FREERTOS) xSemaphoreHandle PIOS_BMP085_EOC; #else int32_t PIOS_BMP085_EOC; #endif +#endif /* PIOS_BMP085_HAS_GPIOS */ + /* Local Variables */ static BMP085CalibDataTypeDef CalibData; @@ -60,6 +65,9 @@ static volatile uint16_t Temperature; */ void PIOS_BMP085_Init(void) { + +#ifdef PIOS_BMP085_HAS_GPIOS + GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; @@ -101,6 +109,8 @@ void PIOS_BMP085_Init(void) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(PIOS_BMP085_XCLR_GPIO_PORT, &GPIO_InitStructure); +#endif /* PIOS_BMP085_HAS_GPIOS */ + /* Read all 22 bytes of calibration data in one transfer, this is a very optimized way of doing things */ uint8_t Data[BMP085_CALIB_LEN]; while (!PIOS_BMP085_Read(BMP085_CALIB_ADDR, Data, BMP085_CALIB_LEN)) diff --git a/flight/PiOS/STM32F10x/pios_exti.c b/flight/PiOS/STM32F10x/pios_exti.c index 0b886666a..0b4a9a1ae 100644 --- a/flight/PiOS/STM32F10x/pios_exti.c +++ b/flight/PiOS/STM32F10x/pios_exti.c @@ -44,7 +44,7 @@ void EXTI15_10_IRQHandler(void) portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; #endif -#if defined(PIOS_INCLUDE_BMP085) +#if defined(PIOS_INCLUDE_BMP085) && defined(PIOS_BMP085_HAS_GPIOS) if (EXTI_GetITStatus(PIOS_BMP085_EOC_EXTI_LINE) != RESET) { /* Read the ADC Value */ #if defined(PIOS_INCLUDE_FREERTOS) From bae08fcad060712eb38fabdf11fe44a1972be3c9 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 10 Dec 2011 19:38:06 -0500 Subject: [PATCH 33/72] bmp085: decouple i2c adapter Let the bmp085 be attached to different adapters for different boards. --- flight/PiOS/Boards/STM3210E_INS.h | 1 + flight/PiOS/Boards/STM3210E_OP.h | 1 + flight/PiOS/Common/pios_bmp085.c | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/flight/PiOS/Boards/STM3210E_INS.h b/flight/PiOS/Boards/STM3210E_INS.h index 5973bd168..37ca4abe3 100644 --- a/flight/PiOS/Boards/STM3210E_INS.h +++ b/flight/PiOS/Boards/STM3210E_INS.h @@ -100,6 +100,7 @@ TIM8 | | | | #define PIOS_I2C_MAX_DEVS 3 extern uint32_t pios_i2c_pres_mag_adapter_id; #define PIOS_I2C_MAIN_ADAPTER (pios_i2c_pres_mag_adapter_id) +#define PIOS_I2C_BMP085_ADAPTER (pios_i2c_pres_mag_adapter_id) extern uint32_t pios_i2c_gyro_adapter_id; #define PIOS_I2C_GYRO_ADAPTER (pios_i2c_gyro_adapter_id) diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index 87d4ab4a0..7099234c6 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -116,6 +116,7 @@ TIM8 | Servo 5 | Servo 6 | Servo 7 | Servo 8 extern uint32_t pios_i2c_main_adapter_id; #define PIOS_I2C_MAIN_ADAPTER (pios_i2c_main_adapter_id) #define PIOS_I2C_ESC_ADAPTER (pios_i2c_main_adapter_id) +#define PIOS_I2C_BMP085_ADAPTER (pios_i2c_main_adapter_id) //------------------------ // PIOS_BMP085 diff --git a/flight/PiOS/Common/pios_bmp085.c b/flight/PiOS/Common/pios_bmp085.c index 5d3668b2f..5a4b0cd94 100644 --- a/flight/PiOS/Common/pios_bmp085.c +++ b/flight/PiOS/Common/pios_bmp085.c @@ -245,7 +245,7 @@ bool PIOS_BMP085_Read(uint8_t address, uint8_t * buffer, uint8_t len) } }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_BMP085_ADAPTER, txn_list, NELEMENTS(txn_list)); } /** @@ -274,7 +274,7 @@ bool PIOS_BMP085_Write(uint8_t address, uint8_t buffer) , }; - return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); + return PIOS_I2C_Transfer(PIOS_I2C_BMP085_ADAPTER, txn_list, NELEMENTS(txn_list)); } /** From 717c1311e62983889adc5fc34ac8a81bbb474f69 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 14 Jan 2012 15:04:49 -0500 Subject: [PATCH 34/72] altitude: allow altitude to be an optional module --- flight/Modules/Altitude/altitude.c | 66 ++++++++++++++--------- shared/uavobjectdefinition/hwsettings.xml | 2 +- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/flight/Modules/Altitude/altitude.c b/flight/Modules/Altitude/altitude.c index 163258c1c..9c0d5399f 100644 --- a/flight/Modules/Altitude/altitude.c +++ b/flight/Modules/Altitude/altitude.c @@ -37,6 +37,7 @@ */ #include "openpilot.h" +#include "hwsettings.h" #include "altitude.h" #include "baroaltitude.h" // object that will be updated by the module #if defined(PIOS_INCLUDE_HCSR04) @@ -60,6 +61,8 @@ static int32_t alt_ds_temp = 0; static int32_t alt_ds_pres = 0; static int alt_ds_count = 0; +static bool altitudeEnabled; + // Private functions static void altitudeTask(void *parameters); @@ -69,17 +72,19 @@ static void altitudeTask(void *parameters); */ int32_t AltitudeStart() { - - BaroAltitudeInitialize(); -#if defined(PIOS_INCLUDE_HCSR04) - SonarAltitudeInitialze(); -#endif - - // Start main task - xTaskCreate(altitudeTask, (signed char *)"Altitude", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &taskHandle); - TaskMonitorAdd(TASKINFO_RUNNING_ALTITUDE, taskHandle); - return 0; + if (altitudeEnabled) { + BaroAltitudeInitialize(); +#if defined(PIOS_INCLUDE_HCSR04) + SonarAltitudeInitialze(); +#endif + + // Start main task + xTaskCreate(altitudeTask, (signed char *)"Altitude", STACK_SIZE_BYTES/4, NULL, TASK_PRIORITY, &taskHandle); + TaskMonitorAdd(TASKINFO_RUNNING_ALTITUDE, taskHandle); + return 0; + } + return -1; } /** @@ -89,10 +94,19 @@ int32_t AltitudeStart() int32_t AltitudeInitialize() { + HwSettingsInitialize(); + uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; + HwSettingsOptionalModulesGet(optionalModules); + if (optionalModules[HWSETTINGS_OPTIONALMODULES_ALTITUDE] == HWSETTINGS_OPTIONALMODULES_ENABLED) { + altitudeEnabled = 1; + } else { + altitudeEnabled = 0; + } + // init down-sampling data - alt_ds_temp = 0; - alt_ds_pres = 0; - alt_ds_count = 0; + alt_ds_temp = 0; + alt_ds_pres = 0; + alt_ds_count = 0; return 0; } @@ -163,23 +177,23 @@ static void altitudeTask(void *parameters) alt_ds_pres += PIOS_BMP085_GetPressure(); if (++alt_ds_count >= alt_ds_size) - { - alt_ds_count = 0; + { + alt_ds_count = 0; - // Convert from 1/10ths of degC to degC - data.Temperature = alt_ds_temp / (10.0 * alt_ds_size); - alt_ds_temp = 0; + // Convert from 1/10ths of degC to degC + data.Temperature = alt_ds_temp / (10.0 * alt_ds_size); + alt_ds_temp = 0; - // Convert from Pa to kPa - data.Pressure = alt_ds_pres / (1000.0f * alt_ds_size); - alt_ds_pres = 0; + // Convert from Pa to kPa + data.Pressure = alt_ds_pres / (1000.0f * alt_ds_size); + alt_ds_pres = 0; - // Compute the current altitude (all pressures in kPa) - data.Altitude = 44330.0 * (1.0 - powf((data.Pressure / (BMP085_P0 / 1000.0)), (1.0 / 5.255))); + // Compute the current altitude (all pressures in kPa) + data.Altitude = 44330.0 * (1.0 - powf((data.Pressure / (BMP085_P0 / 1000.0)), (1.0 / 5.255))); - // Update the AltitudeActual UAVObject - BaroAltitudeSet(&data); - } + // Update the AltitudeActual UAVObject + BaroAltitudeSet(&data); + } // Delay until it is time to read the next sample vTaskDelayUntil(&lastSysTime, UPDATE_PERIOD / portTICK_RATE_MS); diff --git a/shared/uavobjectdefinition/hwsettings.xml b/shared/uavobjectdefinition/hwsettings.xml index 24727a080..455e23cd7 100644 --- a/shared/uavobjectdefinition/hwsettings.xml +++ b/shared/uavobjectdefinition/hwsettings.xml @@ -16,7 +16,7 @@ - + From 53e9ef06b4261feed21e4e8fe3d0261d1560d416 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 14 Jan 2012 15:17:24 -0500 Subject: [PATCH 35/72] altitude: add optional altitude module --- flight/CopterControl/Makefile | 6 ++++-- flight/CopterControl/System/inc/pios_config.h | 2 ++ flight/CopterControl/System/pios_board.c | 2 +- flight/Modules/Altitude/altitude.c | 3 +-- flight/PiOS/Boards/STM32103CB_CC_Rev1.h | 6 ++++++ 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 891e7f6c6..7a1653c0e 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -50,7 +50,7 @@ ENABLE_AUX_UART ?= NO USE_GPS ?= YES -USE_I2C ?= NO +USE_I2C ?= YES # Set to YES when using Code Sourcery toolchain CODE_SOURCERY ?= YES @@ -65,7 +65,7 @@ endif FLASH_TOOL = OPENOCD # List of modules to include -OPTMODULES = CameraStab ComUsbBridge +OPTMODULES = CameraStab ComUsbBridge Altitude ifeq ($(USE_GPS), YES) OPTMODULES += GPS endif @@ -182,6 +182,7 @@ SRC += $(OPUAVSYNTHDIR)/receiveractivity.c SRC += $(OPUAVSYNTHDIR)/taskinfo.c SRC += $(OPUAVSYNTHDIR)/mixerstatus.c SRC += $(OPUAVSYNTHDIR)/ratedesired.c +SRC += $(OPUAVSYNTHDIR)/baroaltitude.c endif @@ -225,6 +226,7 @@ SRC += $(PIOSCOMMON)/pios_flash_w25x.c SRC += $(PIOSCOMMON)/pios_adxl345.c SRC += $(PIOSCOMMON)/pios_com.c SRC += $(PIOSCOMMON)/pios_i2c_esc.c +SRC += $(PIOSCOMMON)/pios_bmp085.c SRC += $(PIOSCOMMON)/pios_iap.c SRC += $(PIOSCOMMON)/pios_bl_helper.c SRC += $(PIOSCOMMON)/pios_rcvr.c diff --git a/flight/CopterControl/System/inc/pios_config.h b/flight/CopterControl/System/inc/pios_config.h index 54c5b3b22..9be4387f0 100644 --- a/flight/CopterControl/System/inc/pios_config.h +++ b/flight/CopterControl/System/inc/pios_config.h @@ -76,6 +76,8 @@ #define PIOS_INCLUDE_ADXL345 #define PIOS_INCLUDE_FLASH +#define PIOS_INCLUDE_BMP085 + /* A really shitty setting saving implementation */ #define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index 4e0495776..a7197768d 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -1464,7 +1464,7 @@ void PIOS_Board_Init(void) { case HWSETTINGS_CC_FLEXIPORT_I2C: #if defined(PIOS_INCLUDE_I2C) { - if (PIOS_I2C_Init(&pios_i2c_main_adapter_id, &pios_i2c_main_adapter_cfg)) { + if (PIOS_I2C_Init(&pios_i2c_flexi_adapter_id, &pios_i2c_flexi_adapter_cfg)) { PIOS_Assert(0); } } diff --git a/flight/Modules/Altitude/altitude.c b/flight/Modules/Altitude/altitude.c index 9c0d5399f..da90b7f7c 100644 --- a/flight/Modules/Altitude/altitude.c +++ b/flight/Modules/Altitude/altitude.c @@ -47,8 +47,7 @@ // Private constants #define STACK_SIZE_BYTES 500 #define TASK_PRIORITY (tskIDLE_PRIORITY+1) -//#define UPDATE_PERIOD 100 -#define UPDATE_PERIOD 25 +#define UPDATE_PERIOD 50 // Private types diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index e908345b7..7773b9092 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -113,6 +113,12 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 extern uint32_t pios_i2c_flexi_adapter_id; #define PIOS_I2C_MAIN_ADAPTER (pios_i2c_flexi_adapter_id) #define PIOS_I2C_ESC_ADAPTER (pios_i2c_flexi_adapter_id) +#define PIOS_I2C_BMP085_ADAPTER (pios_i2c_flexi_adapter_id) + +//------------------------ +// PIOS_BMP085 +//------------------------ +#define PIOS_BMP085_OVERSAMPLING 3 //------------------------- // SPI From 27ceb7ea92c29f803ac5f3fd0cf12ae970727b96 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 14 Jan 2012 16:55:55 -0500 Subject: [PATCH 36/72] modules: Allow optional modules to be used as built-in Some modules are written such that they can be included or excluded at runtime. These are added to the OPTMODULES list in the makefile for a given board. This change provides a mechanism to allow a build to force a given module to be built-in (ie. always initialized) regardless of the configuration in hwsettings. The main use case for this is to handle a module being optional on one platform but essential on another. All modules added to the MODULES list in the Makefile will automatically result in a matching #define in the form MODULE_TheModuleName_BUILTIN being defined in the CFLAGS for all compiled source. Note that the capitalization of TheModuleName must match exactly the capitalization used in the MODULES list. --- flight/CopterControl/Makefile | 3 +++ flight/Modules/Altitude/altitude.c | 5 ++++- flight/Modules/CameraStab/camerastab.c | 5 +++++ flight/Modules/ComUsbBridge/ComUsbBridge.c | 4 ++++ flight/Modules/Fault/Fault.c | 4 ++++ flight/Modules/GPS/GPS.c | 4 ++++ flight/OpenPilot/Makefile | 3 +++ 7 files changed, 27 insertions(+), 1 deletion(-) diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 7a1653c0e..631a0e7c9 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -412,6 +412,9 @@ ifeq ($(USE_I2C), YES) CDEFS += -DUSE_I2C endif +# Declare all non-optional modules as built-in to force inclusion +CDEFS += ${foreach MOD, ${MODULES}, -DMODULE_$(MOD)_BUILTIN } + # Place project-specific -D and/or -U options for # Assembler with preprocessor here. #ADEFS = -DUSE_IRQ_ASM_WRAPPER diff --git a/flight/Modules/Altitude/altitude.c b/flight/Modules/Altitude/altitude.c index da90b7f7c..87a4240b6 100644 --- a/flight/Modules/Altitude/altitude.c +++ b/flight/Modules/Altitude/altitude.c @@ -92,7 +92,9 @@ int32_t AltitudeStart() */ int32_t AltitudeInitialize() { - +#ifdef MODULE_Altitude_BUILTIN + altitudeEnabled = 1; +#else HwSettingsInitialize(); uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; HwSettingsOptionalModulesGet(optionalModules); @@ -101,6 +103,7 @@ int32_t AltitudeInitialize() } else { altitudeEnabled = 0; } +#endif // init down-sampling data alt_ds_temp = 0; diff --git a/flight/Modules/CameraStab/camerastab.c b/flight/Modules/CameraStab/camerastab.c index 770ff7ab6..0c5b189d9 100644 --- a/flight/Modules/CameraStab/camerastab.c +++ b/flight/Modules/CameraStab/camerastab.c @@ -75,6 +75,10 @@ int32_t CameraStabInitialize(void) static UAVObjEvent ev; bool cameraStabEnabled; + +#ifdef MODULE_CameraStab_BUILTIN + cameraStabEnabled = true; +#else uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; HwSettingsInitialize(); @@ -84,6 +88,7 @@ int32_t CameraStabInitialize(void) cameraStabEnabled = true; else cameraStabEnabled = false; +#endif if (cameraStabEnabled) { diff --git a/flight/Modules/ComUsbBridge/ComUsbBridge.c b/flight/Modules/ComUsbBridge/ComUsbBridge.c index 984a53944..678e7039d 100644 --- a/flight/Modules/ComUsbBridge/ComUsbBridge.c +++ b/flight/Modules/ComUsbBridge/ComUsbBridge.c @@ -94,6 +94,9 @@ static int32_t comUsbBridgeInitialize(void) usart_port = PIOS_COM_BRIDGE; vcp_port = PIOS_COM_VCP; +#ifdef MODULE_ComUsbBridge_BUILTIN + bridge_enabled = true; +#else HwSettingsInitialize(); uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; @@ -104,6 +107,7 @@ static int32_t comUsbBridgeInitialize(void) bridge_enabled = true; else bridge_enabled = false; +#endif if (bridge_enabled) { com2usb_buf = pvPortMalloc(BRIDGE_BUF_LEN); diff --git a/flight/Modules/Fault/Fault.c b/flight/Modules/Fault/Fault.c index 0ac3748a6..868330739 100644 --- a/flight/Modules/Fault/Fault.c +++ b/flight/Modules/Fault/Fault.c @@ -40,6 +40,9 @@ static uint8_t active_fault; static int32_t fault_initialize(void) { +#ifdef MODULE_Fault_BUILTIN + module_enabled = true; +#else HwSettingsInitialize(); uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; @@ -50,6 +53,7 @@ static int32_t fault_initialize(void) } else { module_enabled = false; } +#endif /* Do this outside the module_enabled test so that it * can be changed even when the module has been disabled. diff --git a/flight/Modules/GPS/GPS.c b/flight/Modules/GPS/GPS.c index bc8f92c17..1f93d6dba 100644 --- a/flight/Modules/GPS/GPS.c +++ b/flight/Modules/GPS/GPS.c @@ -121,6 +121,9 @@ int32_t GPSInitialize(void) { gpsPort = PIOS_COM_GPS; +#ifdef MODULE_GPS_BUILTIN + gpsEnabled = true; +#else HwSettingsInitialize(); uint8_t optionalModules[HWSETTINGS_OPTIONALMODULES_NUMELEM]; @@ -130,6 +133,7 @@ int32_t GPSInitialize(void) gpsEnabled = true; else gpsEnabled = false; +#endif if (gpsPort && gpsEnabled) { GPSPositionInitialize(); diff --git a/flight/OpenPilot/Makefile b/flight/OpenPilot/Makefile index 940c1f117..2130bf283 100644 --- a/flight/OpenPilot/Makefile +++ b/flight/OpenPilot/Makefile @@ -369,6 +369,9 @@ ifeq ($(ENABLE_AUX_UART), YES) CDEFS += -DPIOS_ENABLE_AUX_UART endif +# Declare all non-optional modules as built-in to force inclusion +CDEFS += ${foreach MOD, ${MODULES}, -DMODULE_$(MOD)_BUILTIN } + # Place project-specific -D and/or -U options for # Assembler with preprocessor here. #ADEFS = -DUSE_IRQ_ASM_WRAPPER From c97b108a1f2c1b9aa5acdd4ff130c306f3447443 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 17:56:42 -0500 Subject: [PATCH 37/72] bootfault: make IAP usage depend on PiOS config The sim platforms don't support an IAP mechanism. Let PiOS config control when we try to use it. --- flight/AHRS/inc/pios_config.h | 1 + flight/Bootloaders/AHRS/inc/pios_config.h | 1 + flight/Bootloaders/CopterControl/inc/pios_config.h | 1 + flight/Bootloaders/OpenPilot/inc/pios_config.h | 1 + flight/Bootloaders/PipXtreme/inc/pios_config.h | 1 + flight/CopterControl/System/inc/pios_config.h | 1 + flight/INS/inc/pios_config.h | 1 + flight/Modules/System/systemmod.c | 4 ++-- flight/OpenPilot/System/inc/pios_config.h | 1 + flight/PiOS/pios.h | 3 +++ 10 files changed, 13 insertions(+), 2 deletions(-) diff --git a/flight/AHRS/inc/pios_config.h b/flight/AHRS/inc/pios_config.h index 64f3559a0..77ddf0f2f 100644 --- a/flight/AHRS/inc/pios_config.h +++ b/flight/AHRS/inc/pios_config.h @@ -41,5 +41,6 @@ #define PIOS_INCLUDE_GPIO #define PIOS_INCLUDE_EXTI #define PIOS_INCLUDE_BL_HELPER +#define PIOS_INCLUDE_IAP #endif /* PIOS_CONFIG_H */ diff --git a/flight/Bootloaders/AHRS/inc/pios_config.h b/flight/Bootloaders/AHRS/inc/pios_config.h index b24e0fc5b..82344e2ad 100644 --- a/flight/Bootloaders/AHRS/inc/pios_config.h +++ b/flight/Bootloaders/AHRS/inc/pios_config.h @@ -36,5 +36,6 @@ #define PIOS_INCLUDE_BL_HELPER #define PIOS_INCLUDE_BL_HELPER_WRITE_SUPPORT #define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_IAP #endif /* PIOS_CONFIG_H */ diff --git a/flight/Bootloaders/CopterControl/inc/pios_config.h b/flight/Bootloaders/CopterControl/inc/pios_config.h index 864ed4665..3eb2c281a 100644 --- a/flight/Bootloaders/CopterControl/inc/pios_config.h +++ b/flight/Bootloaders/CopterControl/inc/pios_config.h @@ -41,6 +41,7 @@ #define PIOS_INCLUDE_USB_HID #define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_IAP #define PIOS_NO_GPS #endif /* PIOS_CONFIG_H */ diff --git a/flight/Bootloaders/OpenPilot/inc/pios_config.h b/flight/Bootloaders/OpenPilot/inc/pios_config.h index cf8981339..932c1a913 100644 --- a/flight/Bootloaders/OpenPilot/inc/pios_config.h +++ b/flight/Bootloaders/OpenPilot/inc/pios_config.h @@ -44,6 +44,7 @@ #define PIOS_INCLUDE_COM #define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_IAP //#define DEBUG_SSP /* Defaults for Logging */ diff --git a/flight/Bootloaders/PipXtreme/inc/pios_config.h b/flight/Bootloaders/PipXtreme/inc/pios_config.h index cec926057..1b1b9c2bc 100644 --- a/flight/Bootloaders/PipXtreme/inc/pios_config.h +++ b/flight/Bootloaders/PipXtreme/inc/pios_config.h @@ -40,6 +40,7 @@ #define PIOS_INCLUDE_USB_HID #define PIOS_INCLUDE_COM_MSG #define PIOS_INCLUDE_GPIO +#define PIOS_INCLUDE_IAP /* Defaults for Logging */ #define LOG_FILENAME "PIOS.LOG" diff --git a/flight/CopterControl/System/inc/pios_config.h b/flight/CopterControl/System/inc/pios_config.h index 54c5b3b22..6ca38bf2c 100644 --- a/flight/CopterControl/System/inc/pios_config.h +++ b/flight/CopterControl/System/inc/pios_config.h @@ -42,6 +42,7 @@ #endif #define PIOS_INCLUDE_IRQ #define PIOS_INCLUDE_LED +#define PIOS_INCLUDE_IAP #define PIOS_INCLUDE_RCVR diff --git a/flight/INS/inc/pios_config.h b/flight/INS/inc/pios_config.h index ae6561236..a13394179 100644 --- a/flight/INS/inc/pios_config.h +++ b/flight/INS/inc/pios_config.h @@ -51,6 +51,7 @@ #define PIOS_INCLUDE_IMU3000 #define PIOS_INCLUDE_GPIO #define PIOS_INCLUDE_EXTI +#define PIOS_INCLUDE_IAP #define PIOS_INCLUDE_BMA180 diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c index bb3496b0f..29fb99791 100644 --- a/flight/Modules/System/systemmod.c +++ b/flight/Modules/System/systemmod.c @@ -48,8 +48,6 @@ #include "taskinfo.h" #include "watchdogstatus.h" #include "taskmonitor.h" -#include "pios_iap.h" - // Private constants #define SYSTEM_UPDATE_PERIOD_MS 1000 @@ -148,8 +146,10 @@ static void systemTask(void *parameters) PIOS_SYS_Reset(); } +#if defined(PIOS_INCLUDE_IAP) /* Record a successful boot */ PIOS_IAP_WriteBootCount(0); +#endif // Initialize vars idleCounter = 0; diff --git a/flight/OpenPilot/System/inc/pios_config.h b/flight/OpenPilot/System/inc/pios_config.h index ce0484a8d..f5227019f 100644 --- a/flight/OpenPilot/System/inc/pios_config.h +++ b/flight/OpenPilot/System/inc/pios_config.h @@ -41,6 +41,7 @@ #define PIOS_INCLUDE_I2C #define PIOS_INCLUDE_IRQ #define PIOS_INCLUDE_LED +#define PIOS_INCLUDE_IAP #define PIOS_INCLUDE_RCVR diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index 58d869517..4429c477a 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -112,7 +112,10 @@ #if defined(PIOS_INCLUDE_IMU3000) #include #endif + +#if defined(PIOS_INCLUDE_IAP) #include +#endif #if defined(PIOS_INCLUDE_ADXL345) #include From 0575b45378cc17d89ee4bb06819a5b4cc3fceea6 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 17:58:09 -0500 Subject: [PATCH 38/72] usb: make USB usage depend on PiOS config USB is not supported on sim platforms. Let PiOS config determine when we use it. --- flight/Modules/Telemetry/telemetry.c | 1 - flight/PiOS/pios.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/flight/Modules/Telemetry/telemetry.c b/flight/Modules/Telemetry/telemetry.c index d01085591..12818529f 100644 --- a/flight/Modules/Telemetry/telemetry.c +++ b/flight/Modules/Telemetry/telemetry.c @@ -35,7 +35,6 @@ #include "flighttelemetrystats.h" #include "gcstelemetrystats.h" #include "hwsettings.h" -#include "pios_usb.h" /* PIOS_USB_* */ // Private constants #define MAX_QUEUE_SIZE TELEM_QUEUE_SIZE diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index 4429c477a..e7d02dfd2 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -137,6 +137,7 @@ #if defined(PIOS_INCLUDE_USB) /* USB Libs */ #include +#include #endif #include From b05697c2cfcf5127e79b3bca554ede625cf45e0d Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 18:02:38 -0500 Subject: [PATCH 39/72] taskinfo: ensure usage of TaskInfo uavo is covered by DIAG_TASKS OpenPilot platform (and thus sim too) was missed when the DIAG_TASKS macro was broken out from the DIAGNOSTICS macro. This allowed accesses to the TaskInfo UAVO even though it hadn't been initialized. --- flight/CopterControl/System/taskmonitor.c | 26 +++++++++++++++++++---- flight/Modules/System/systemmod.c | 3 +++ flight/OpenPilot/System/taskmonitor.c | 5 ++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/flight/CopterControl/System/taskmonitor.c b/flight/CopterControl/System/taskmonitor.c index 627dedaab..fffc6435c 100644 --- a/flight/CopterControl/System/taskmonitor.c +++ b/flight/CopterControl/System/taskmonitor.c @@ -71,6 +71,24 @@ int32_t TaskMonitorAdd(TaskInfoRunningElem task, xTaskHandle handle) } } +/** + * Remove a task handle from the library + */ +int32_t TaskMonitorRemove(TaskInfoRunningElem task) +{ + if (task < TASKINFO_RUNNING_NUMELEM) + { + xSemaphoreTakeRecursive(lock, portMAX_DELAY); + handles[task] = 0; + xSemaphoreGiveRecursive(lock); + return 0; + } + else + { + return -1; + } +} + /** * Update the status of all tasks */ @@ -79,10 +97,10 @@ void TaskMonitorUpdateAll(void) #if defined(DIAG_TASKS) TaskInfoData data; int n; - + // Lock xSemaphoreTakeRecursive(lock, portMAX_DELAY); - + #if ( configGENERATE_RUN_TIME_STATS == 1 ) uint32_t currentTime; uint32_t deltaTime; @@ -121,10 +139,10 @@ void TaskMonitorUpdateAll(void) data.RunningTime[n] = 0; } } - + // Update object TaskInfoSet(&data); - + // Done xSemaphoreGiveRecursive(lock); #endif diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c index 29fb99791..7e476f686 100644 --- a/flight/Modules/System/systemmod.c +++ b/flight/Modules/System/systemmod.c @@ -170,8 +170,11 @@ static void systemTask(void *parameters) updateI2Cstats(); updateWDGstats(); #endif + +#if defined(DIAG_TASKS) // Update the task status object TaskMonitorUpdateAll(); +#endif // Flash the heartbeat LED PIOS_LED_Toggle(LED1); diff --git a/flight/OpenPilot/System/taskmonitor.c b/flight/OpenPilot/System/taskmonitor.c index dcd08945c..fffc6435c 100644 --- a/flight/OpenPilot/System/taskmonitor.c +++ b/flight/OpenPilot/System/taskmonitor.c @@ -47,7 +47,7 @@ int32_t TaskMonitorInitialize(void) lock = xSemaphoreCreateRecursiveMutex(); memset(handles, 0, sizeof(xTaskHandle)*TASKINFO_RUNNING_NUMELEM); lastMonitorTime = 0; -#if defined(DIAGNOSTICS) +#if defined(DIAG_TASKS) lastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE(); #endif return 0; @@ -94,7 +94,7 @@ int32_t TaskMonitorRemove(TaskInfoRunningElem task) */ void TaskMonitorUpdateAll(void) { -#if defined(DIAGNOSTICS) +#if defined(DIAG_TASKS) TaskInfoData data; int n; @@ -128,7 +128,6 @@ void TaskMonitorUpdateAll(void) #if ( configGENERATE_RUN_TIME_STATS == 1 ) /* Generate run time stats */ data.RunningTime[n] = uxTaskGetRunTime(handles[n]) / deltaTime; - #endif #endif From 387ea77d3091baaa1d4600d85919d2bc958c5ab8 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 18:06:35 -0500 Subject: [PATCH 40/72] diagnostics: enable DIAG_TASKS on OP board by default --- flight/CopterControl/Makefile | 6 +++--- flight/OpenPilot/Makefile | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 891e7f6c6..c0e202453 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -436,15 +436,15 @@ CSTANDARD = -std=gnu99 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++) ifeq ($(DEBUG),YES) -CFLAGS = -DDEBUG +CFLAGS += -DDEBUG endif ifeq ($(DIAGNOSTICS),YES) -CFLAGS = -DDIAGNOSTICS +CFLAGS += -DDIAGNOSTICS endif ifeq ($(DIAG_TASKS),YES) -CFLAGS = -DDIAG_TASKS +CFLAGS += -DDIAG_TASKS endif CFLAGS += -g$(DEBUGF) diff --git a/flight/OpenPilot/Makefile b/flight/OpenPilot/Makefile index 940c1f117..119762ce9 100644 --- a/flight/OpenPilot/Makefile +++ b/flight/OpenPilot/Makefile @@ -39,6 +39,7 @@ DEBUG ?= YES # Include objects that are just nice information to show DIAGNOSTICS ?= YES +DIAG_TASKS ?= YES # Set to YES to use the Servo output pins for debugging via scope or logic analyser ENABLE_DEBUG_PINS ?= NO @@ -395,11 +396,15 @@ CSTANDARD = -std=gnu99 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++) ifeq ($(DEBUG),YES) -CFLAGS = -DDEBUG +CFLAGS += -DDEBUG endif ifeq ($(DIAGNOSTICS),YES) -CFLAGS = -DDIAGNOSTICS +CFLAGS += -DDIAGNOSTICS +endif + +ifeq ($(DIAG_TASKS),YES) +CFLAGS += -DDIAG_TASKS endif CFLAGS += -g$(DEBUGF) From 8cd4816d7b3ac4a5ad2a68d933b34f6ed478dfe5 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 21:37:10 -0500 Subject: [PATCH 41/72] taskmonitor: move taskmonitor into flight/Libraries taskmonitor.[ch] existed as (nearly) identical copies under CC and OP directories. Both builds now reference the common version under Libraries. --- flight/CopterControl/Makefile | 2 +- flight/CopterControl/System/inc/taskmonitor.h | 42 ----- .../System => Libraries}/inc/taskmonitor.h | 0 .../System => Libraries}/taskmonitor.c | 0 flight/OpenPilot/Makefile | 2 +- flight/OpenPilot/Makefile.posix | 2 +- flight/OpenPilot/System/taskmonitor.c | 149 ------------------ 7 files changed, 3 insertions(+), 194 deletions(-) delete mode 100644 flight/CopterControl/System/inc/taskmonitor.h rename flight/{OpenPilot/System => Libraries}/inc/taskmonitor.h (100%) rename flight/{CopterControl/System => Libraries}/taskmonitor.c (100%) delete mode 100644 flight/OpenPilot/System/taskmonitor.c diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index c0e202453..562e1d9de 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -136,7 +136,6 @@ SRC += ${OPMODULEDIR}/System/systemmod.c SRC += $(OPSYSTEM)/coptercontrol.c SRC += $(OPSYSTEM)/pios_board.c SRC += $(OPSYSTEM)/alarms.c -SRC += $(OPSYSTEM)/taskmonitor.c SRC += $(OPUAVTALK)/uavtalk.c SRC += $(OPUAVOBJ)/uavobjectmanager.c SRC += $(OPUAVOBJ)/eventdispatcher.c @@ -233,6 +232,7 @@ SRC += $(PIOSCOMMON)/printf-stdarg.c ## Libraries for flight calculations SRC += $(FLIGHTLIB)/fifo_buffer.c SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/taskmonitor.c ## CMSIS for STM32 SRC += $(CMSISDIR)/core_cm3.c diff --git a/flight/CopterControl/System/inc/taskmonitor.h b/flight/CopterControl/System/inc/taskmonitor.h deleted file mode 100644 index 511f552f7..000000000 --- a/flight/CopterControl/System/inc/taskmonitor.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - ****************************************************************************** - * @addtogroup OpenPilotSystem OpenPilot System - * @{ - * @addtogroup OpenPilotLibraries OpenPilot System Libraries - * @{ - * @file taskmonitor.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Include file of the task monitoring library - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef TASKMONITOR_H -#define TASKMONITOR_H - -#include "taskinfo.h" - -int32_t TaskMonitorInitialize(void); -int32_t TaskMonitorAdd(TaskInfoRunningElem task, xTaskHandle handle); -void TaskMonitorUpdateAll(void); - -#endif // TASKMONITOR_H - -/** - * @} - * @} - */ diff --git a/flight/OpenPilot/System/inc/taskmonitor.h b/flight/Libraries/inc/taskmonitor.h similarity index 100% rename from flight/OpenPilot/System/inc/taskmonitor.h rename to flight/Libraries/inc/taskmonitor.h diff --git a/flight/CopterControl/System/taskmonitor.c b/flight/Libraries/taskmonitor.c similarity index 100% rename from flight/CopterControl/System/taskmonitor.c rename to flight/Libraries/taskmonitor.c diff --git a/flight/OpenPilot/Makefile b/flight/OpenPilot/Makefile index 119762ce9..6e4bf6279 100644 --- a/flight/OpenPilot/Makefile +++ b/flight/OpenPilot/Makefile @@ -139,7 +139,6 @@ SRC += ${OPMODULEDIR}/System/systemmod.c SRC += $(OPSYSTEM)/openpilot.c SRC += $(OPSYSTEM)/pios_board.c SRC += $(OPSYSTEM)/alarms.c -SRC += $(OPSYSTEM)/taskmonitor.c SRC += $(OPUAVTALK)/uavtalk.c SRC += $(OPUAVOBJ)/uavobjectmanager.c SRC += $(OPUAVOBJ)/eventdispatcher.c @@ -208,6 +207,7 @@ SRC += $(FLIGHTLIB)/ahrs_comm_objects.c SRC += $(FLIGHTLIB)/fifo_buffer.c SRC += $(FLIGHTLIB)/WorldMagModel.c SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/taskmonitor.c ## CMSIS for STM32 SRC += $(CMSISDIR)/core_cm3.c diff --git a/flight/OpenPilot/Makefile.posix b/flight/OpenPilot/Makefile.posix index 4a947ae8d..5fbc66b4b 100644 --- a/flight/OpenPilot/Makefile.posix +++ b/flight/OpenPilot/Makefile.posix @@ -149,7 +149,6 @@ SRC += ${OPMODULEDIR}/System/systemmod.c SRC += $(OPSYSTEM)/openpilot.c SRC += $(OPSYSTEM)/pios_board_posix.c SRC += $(OPSYSTEM)/alarms.c -SRC += $(OPSYSTEM)/taskmonitor.c SRC += $(OPUAVTALK)/uavtalk.c SRC += $(OPUAVOBJ)/uavobjectmanager.c SRC += $(OPUAVOBJ)/eventdispatcher.c @@ -189,6 +188,7 @@ SRC += $(PIOSPOSIX)/pios_rcvr.c SRC += $(FLIGHTLIB)/fifo_buffer.c SRC += $(FLIGHTLIB)/WorldMagModel.c SRC += $(FLIGHTLIB)/CoordinateConversions.c +SRC += $(FLIGHTLIB)/taskmonitor.c ## RTOS and RTOS Portable SRC += $(RTOSSRCDIR)/list.c SRC += $(RTOSSRCDIR)/queue.c diff --git a/flight/OpenPilot/System/taskmonitor.c b/flight/OpenPilot/System/taskmonitor.c deleted file mode 100644 index fffc6435c..000000000 --- a/flight/OpenPilot/System/taskmonitor.c +++ /dev/null @@ -1,149 +0,0 @@ -/** - ****************************************************************************** - * @addtogroup OpenPilotSystem OpenPilot System - * @{ - * @addtogroup OpenPilotLibraries OpenPilot System Libraries - * @{ - * @file taskmonitor.h - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. - * @brief Task monitoring library - * @see The GNU Public License (GPL) Version 3 - * - *****************************************************************************/ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "openpilot.h" -//#include "taskmonitor.h" - -// Private constants - -// Private types - -// Private variables -static xSemaphoreHandle lock; -static xTaskHandle handles[TASKINFO_RUNNING_NUMELEM]; -static uint32_t lastMonitorTime; - -// Private functions - -/** - * Initialize library - */ -int32_t TaskMonitorInitialize(void) -{ - lock = xSemaphoreCreateRecursiveMutex(); - memset(handles, 0, sizeof(xTaskHandle)*TASKINFO_RUNNING_NUMELEM); - lastMonitorTime = 0; -#if defined(DIAG_TASKS) - lastMonitorTime = portGET_RUN_TIME_COUNTER_VALUE(); -#endif - return 0; -} - -/** - * Register a task handle with the library - */ -int32_t TaskMonitorAdd(TaskInfoRunningElem task, xTaskHandle handle) -{ - if (task < TASKINFO_RUNNING_NUMELEM) - { - xSemaphoreTakeRecursive(lock, portMAX_DELAY); - handles[task] = handle; - xSemaphoreGiveRecursive(lock); - return 0; - } - else - { - return -1; - } -} - -/** - * Remove a task handle from the library - */ -int32_t TaskMonitorRemove(TaskInfoRunningElem task) -{ - if (task < TASKINFO_RUNNING_NUMELEM) - { - xSemaphoreTakeRecursive(lock, portMAX_DELAY); - handles[task] = 0; - xSemaphoreGiveRecursive(lock); - return 0; - } - else - { - return -1; - } -} - -/** - * Update the status of all tasks - */ -void TaskMonitorUpdateAll(void) -{ -#if defined(DIAG_TASKS) - TaskInfoData data; - int n; - - // Lock - xSemaphoreTakeRecursive(lock, portMAX_DELAY); - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - uint32_t currentTime; - uint32_t deltaTime; - - /* - * Calculate the amount of elapsed run time between the last time we - * measured and now. Scale so that we can convert task run times - * directly to percentages. - */ - currentTime = portGET_RUN_TIME_COUNTER_VALUE(); - deltaTime = ((currentTime - lastMonitorTime) / 100) ? : 1; /* avoid divide-by-zero if the interval is too small */ - lastMonitorTime = currentTime; -#endif - - // Update all task information - for (n = 0; n < TASKINFO_RUNNING_NUMELEM; ++n) - { - if (handles[n] != 0) - { - data.Running[n] = TASKINFO_RUNNING_TRUE; -#if defined(ARCH_POSIX) || defined(ARCH_WIN32) - data.StackRemaining[n] = 10000; -#else - data.StackRemaining[n] = uxTaskGetStackHighWaterMark(handles[n]) * 4; -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - /* Generate run time stats */ - data.RunningTime[n] = uxTaskGetRunTime(handles[n]) / deltaTime; -#endif -#endif - - } - else - { - data.Running[n] = TASKINFO_RUNNING_FALSE; - data.StackRemaining[n] = 0; - data.RunningTime[n] = 0; - } - } - - // Update object - TaskInfoSet(&data); - - // Done - xSemaphoreGiveRecursive(lock); -#endif -} From 3bda0f450d112df41b2d47921a8f5fa439d047ff Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 15 Jan 2012 23:04:31 -0500 Subject: [PATCH 42/72] bootfault: force fault when no telemetry available on OP too If no telemetry link is configured, this will force the board to reset before finishing init. The BootFault logic will catch this after 3 resets and will boot with default hwsettings on the next reset. This won't currently ever fire on OP though since we always configure the serial telemetry interface. This just makes sure the pattern is present in case anyone decides to compile without serial telemetry. --- flight/OpenPilot/System/pios_board.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index 8dbb5eee2..0fb873f0a 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -1450,6 +1450,9 @@ void PIOS_Board_Init(void) { PIOS_Assert(0); } #endif /* PIOS_INCLUDE_I2C */ + + /* Make sure we have at least one telemetry link configured or else fail initialization */ + PIOS_Assert(pios_com_telem_rf_id || pios_com_telem_usb_id); } /** From ee0895aa77c7cf198c1850f5c302c659f124ef17 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Mon, 16 Jan 2012 21:31:07 -0500 Subject: [PATCH 43/72] usb hid: remove stale files from pipx These files are no longer relevent for USB configuration. --- flight/PipXtreme/inc/pios_usb_hid_desc.h | 56 ------ flight/PipXtreme/pios_usb_hid_desc.c | 220 ----------------------- 2 files changed, 276 deletions(-) delete mode 100644 flight/PipXtreme/inc/pios_usb_hid_desc.h delete mode 100644 flight/PipXtreme/pios_usb_hid_desc.c diff --git a/flight/PipXtreme/inc/pios_usb_hid_desc.h b/flight/PipXtreme/inc/pios_usb_hid_desc.h deleted file mode 100644 index 4810c1274..000000000 --- a/flight/PipXtreme/inc/pios_usb_hid_desc.h +++ /dev/null @@ -1,56 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_desc.h -* Author : MCD Application Team -* Version : V3.2.1 -* Date : 07/05/2010 -* Description : Descriptor Header for Custom HID Demo -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_DESC_H -#define __USB_DESC_H - -/* Includes ------------------------------------------------------------------*/ -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported define -----------------------------------------------------------*/ -#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 -#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 -#define USB_STRING_DESCRIPTOR_TYPE 0x03 -#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 -#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 - -#define HID_DESCRIPTOR_TYPE 0x21 -#define PIOS_HID_SIZ_HID_DESC 0x09 -#define PIOS_HID_OFF_HID_DESC 0x12 - -#define PIOS_HID_SIZ_DEVICE_DESC 18 -#define PIOS_HID_SIZ_CONFIG_DESC 41 -#define PIOS_HID_SIZ_REPORT_DESC 36 -#define PIOS_HID_SIZ_STRING_LANGID 4 -#define PIOS_HID_SIZ_STRING_VENDOR 28 -#define PIOS_HID_SIZ_STRING_PRODUCT 20 -#define PIOS_HID_SIZ_STRING_SERIAL 52 /* 96 bits, 12 bytes, 24 characters, 48 in unicode */ - -#define STANDARD_ENDPOINT_DESC_SIZE 0x09 - -/* Exported functions ------------------------------------------------------- */ -extern const uint8_t PIOS_HID_DeviceDescriptor[PIOS_HID_SIZ_DEVICE_DESC]; -extern const uint8_t PIOS_HID_ConfigDescriptor[PIOS_HID_SIZ_CONFIG_DESC]; -extern const uint8_t PIOS_HID_ReportDescriptor[PIOS_HID_SIZ_REPORT_DESC]; -extern const uint8_t PIOS_HID_StringLangID[PIOS_HID_SIZ_STRING_LANGID]; -extern const uint8_t PIOS_HID_StringVendor[PIOS_HID_SIZ_STRING_VENDOR]; -extern const uint8_t PIOS_HID_StringProduct[PIOS_HID_SIZ_STRING_PRODUCT]; -extern uint8_t PIOS_HID_StringSerial[PIOS_HID_SIZ_STRING_SERIAL]; - -#endif /* __USB_DESC_H */ - -/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ diff --git a/flight/PipXtreme/pios_usb_hid_desc.c b/flight/PipXtreme/pios_usb_hid_desc.c deleted file mode 100644 index c15a80551..000000000 --- a/flight/PipXtreme/pios_usb_hid_desc.c +++ /dev/null @@ -1,220 +0,0 @@ -/******************** (C) COPYRIGHT 2010 STMicroelectronics ******************** -* File Name : usb_desc.c -* Author : MCD Application Team -* Version : V3.2.1 -* Date : 07/05/2010 -* Description : Descriptors for Custom HID Demo -******************************************************************************** -* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. -* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, -* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE -* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING -* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. -*******************************************************************************/ - -#include "usb_lib.h" -#include "pios_usb.h" -#include "pios_usb_hid.h" -#include "pios_usb_hid_desc.h" - -// ************************************************* -// USB Standard Device Descriptor - -const uint8_t PIOS_HID_DeviceDescriptor[PIOS_HID_SIZ_DEVICE_DESC] = - { - 0x12, // bLength - USB_DEVICE_DESCRIPTOR_TYPE, // bDescriptorType - 0x00, // bcdUSB - 0x02, - 0x00, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - 0x40, // bMaxPacketSize40 - (uint8_t)((PIOS_USB_VENDOR_ID) & 0xff), // idVendor - (uint8_t)((PIOS_USB_VENDOR_ID) >> 8), - (uint8_t)((PIOS_USB_PRODUCT_ID) & 0xff), // idProduct - (uint8_t)((PIOS_USB_PRODUCT_ID) >> 8), - (uint8_t)((PIOS_USB_VERSION_ID) & 0xff), // bcdDevice - (uint8_t)((PIOS_USB_VERSION_ID) >> 8), - 0x01, // Index of string descriptor describing manufacturer - 0x02, // Index of string descriptor describing product - 0x03, // Index of string descriptor describing the device serial number - 0x01 // bNumConfigurations - }; - -// ************************************************* -// USB Configuration Descriptor -// All Descriptors (Configuration, Interface, Endpoint, Class, Vendor - -const uint8_t PIOS_HID_ConfigDescriptor[PIOS_HID_SIZ_CONFIG_DESC] = - { - 0x09, // bLength: Configuation Descriptor size - USB_CONFIGURATION_DESCRIPTOR_TYPE, // bDescriptorType: Configuration - PIOS_HID_SIZ_CONFIG_DESC, - // wTotalLength: Bytes returned - 0x00, - 0x01, // bNumInterfaces: 1 interface - 0x01, // bConfigurationValue: Configuration value - 0x00, // iConfiguration: Index of string descriptor describing the configuration - 0xC0, // bmAttributes: Bus powered - 0x7D, // MaxPower 250 mA - needed to power the RF transmitter - - // ************** Descriptor of Custom HID interface **************** - // 09 - 0x09, // bLength: Interface Descriptor size - USB_INTERFACE_DESCRIPTOR_TYPE, // bDescriptorType: Interface descriptor type - 0x00, // bInterfaceNumber: Number of Interface - 0x00, // bAlternateSetting: Alternate setting - 0x02, // bNumEndpoints - 0x03, // bInterfaceClass: HID - 0x00, // bInterfaceSubClass : 1=BOOT, 0=no boot - 0x00, // nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse - 0, // iInterface: Index of string descriptor - - // ******************** Descriptor of Custom HID HID ******************** - // 18 - 0x09, // bLength: HID Descriptor size - HID_DESCRIPTOR_TYPE, // bDescriptorType: HID - 0x10, // bcdHID: HID Class Spec release number - 0x01, - 0x00, // bCountryCode: Hardware target country - 0x01, // bNumDescriptors: Number of HID class descriptors to follow - 0x22, // bDescriptorType - PIOS_HID_SIZ_REPORT_DESC, // wItemLength: Total length of Report descriptor - 0x00, - - // ******************** Descriptor of Custom HID endpoints ****************** - // 27 - 0x07, // bLength: Endpoint Descriptor size - USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: - - 0x81, // bEndpointAddress: Endpoint Address (IN) - 0x03, // bmAttributes: Interrupt endpoint - 0x40, // wMaxPacketSize: 2 Bytes max - 0x00, - 0x04, // bInterval: Polling Interval in ms - // 34 - - 0x07, // bLength: Endpoint Descriptor size - USB_ENDPOINT_DESCRIPTOR_TYPE, // bDescriptorType: - // Endpoint descriptor type - 0x01, // bEndpointAddress: - // Endpoint Address (OUT) - 0x03, // bmAttributes: Interrupt endpoint - 0x40, // wMaxPacketSize: 2 Bytes max - 0x00, - 0x04, // bInterval: Polling Interval in ms - // 41 - }; - -// ************************************************* - - const uint8_t PIOS_HID_ReportDescriptor[PIOS_HID_SIZ_REPORT_DESC] = - { - 0x06, 0x9c, 0xff, // USAGE_PAGE (Vendor Page: 0xFF00) - 0x09, 0x01, // USAGE (Demo Kit) - 0xa1, 0x01, // COLLECTION (Application) - // 6 - - // Data 1 - 0x85, 0x01, // REPORT_ID (1) - 0x09, 0x02, // USAGE (LED 1) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0xff, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, PIOS_USB_COM_DATA_LENGTH+1, // REPORT_COUNT (1) - 0x81, 0x83, // INPUT (Const,Var,Array) - // 20 - - // Data 1 - 0x85, 0x02, // REPORT_ID (2) - 0x09, 0x03, // USAGE (LED 1) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0xff, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, PIOS_USB_COM_DATA_LENGTH+1, // REPORT_COUNT (1) - 0x91, 0x82, // OUTPUT (Data,Var,Abs,Vol) - // 34 - - 0xc0 // END_COLLECTION - }; - -// ************************************************* -// USB String Descriptors (optional) - -const uint8_t PIOS_HID_StringLangID[PIOS_HID_SIZ_STRING_LANGID] = - { - PIOS_HID_SIZ_STRING_LANGID, - USB_STRING_DESCRIPTOR_TYPE, - 0x09, 0x08 // LangID = 0x0809: UK. English -// 0x09, 0x04 // LangID = 0x0409: U.S. English - }; - -const uint8_t PIOS_HID_StringVendor[PIOS_HID_SIZ_STRING_VENDOR] = - { - PIOS_HID_SIZ_STRING_VENDOR, // Size of Vendor string - USB_STRING_DESCRIPTOR_TYPE, // bDescriptorType - // Manufacturer: "STMicroelectronics" - 'o', 0, - 'p', 0, - 'e', 0, - 'n', 0, - 'p', 0, - 'i', 0, - 'l', 0, - 'o', 0, - 't', 0, - '.', 0, - 'o', 0, - 'r', 0, - 'g', 0 - }; - -const uint8_t PIOS_HID_StringProduct[PIOS_HID_SIZ_STRING_PRODUCT] = - { - PIOS_HID_SIZ_STRING_PRODUCT, // bLength - USB_STRING_DESCRIPTOR_TYPE, // bDescriptorType - 'P', 0, - 'i', 0, - 'p', 0, - 'X', 0, - 't', 0, - 'r', 0, - 'e', 0, - 'm', 0, - 'e', 0 - }; - -uint8_t PIOS_HID_StringSerial[PIOS_HID_SIZ_STRING_SERIAL] = - { - PIOS_HID_SIZ_STRING_SERIAL, // bLength - USB_STRING_DESCRIPTOR_TYPE, // bDescriptorType - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0, - 0, 0 - }; - -// ************************************************* From bffb184b7a62d3036f6c264fd3a0d60bfc0b3479 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Mon, 16 Jan 2012 21:32:52 -0500 Subject: [PATCH 44/72] usb: add standard boilerplate to new files --- flight/PiOS/inc/pios_usb_board_data_priv.h | 39 +++++++++++++++++++ flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h | 34 ++++++++++++++++ flight/PiOS/inc/pios_usb_desc_hid_only_priv.h | 34 ++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/flight/PiOS/inc/pios_usb_board_data_priv.h b/flight/PiOS/inc/pios_usb_board_data_priv.h index 49166c25f..f4e7f7c05 100644 --- a/flight/PiOS/inc/pios_usb_board_data_priv.h +++ b/flight/PiOS/inc/pios_usb_board_data_priv.h @@ -1 +1,40 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_USB_BOARD USB board layer functions + * @{ + * + * @file pios_usb_board_data_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Defines the API to the board-specific USB data setup code + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_USB_BOARD_DATA_PRIV_H +#define PIOS_USB_BOARD_DATA_PRIV_H + extern int32_t PIOS_USB_BOARD_DATA_Init(void); + +#endif /* PIOS_USB_BOARD_DATA_PRIV_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h b/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h index 4836f4569..2ae94c74e 100644 --- a/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h +++ b/flight/PiOS/inc/pios_usb_desc_hid_cdc_priv.h @@ -1,3 +1,32 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_USB_DESC USB descriptor layer functions + * @{ + * + * @file pios_usb_desc_hid_cdc_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Defines the API to set up the HID + CDC USB descriptor config + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifndef PIOS_USB_DESC_HID_CDC_PRIV_H #define PIOS_USB_DESC_HID_CDC_PRIV_H @@ -6,3 +35,8 @@ extern int32_t PIOS_USB_DESC_HID_CDC_Init(void); #endif /* PIOS_USB_DESC_HID_CDC_PRIV_H */ + +/** + * @} + * @} + */ diff --git a/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h b/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h index 5d161d233..321d15efa 100644 --- a/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h +++ b/flight/PiOS/inc/pios_usb_desc_hid_only_priv.h @@ -1,3 +1,32 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_USB_DESC USB descriptor layer functions + * @{ + * + * @file pios_usb_desc_hid_only_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief Defines the API to set up the HID-only USB descriptor config + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #ifndef PIOS_USB_DESC_HID_ONLY_PRIV_H #define PIOS_USB_DESC_HID_ONLY_PRIV_H @@ -6,3 +35,8 @@ extern int32_t PIOS_USB_DESC_HID_ONLY_Init(void); #endif /* PIOS_USB_DESC_HID_ONLY_PRIV_H */ + +/** + * @} + * @} + */ From 7d15cbd7200ccf33dc3a769f75c1ef04aa3c44e8 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 21 Jan 2012 00:55:08 +0200 Subject: [PATCH 45/72] gcscontrol: new joystick image with active stick area --- .../plugins/gcscontrol/images/joystick.svg | 2764 ++++++----------- .../plugins/gcscontrol/joystickcontrol.cpp | 32 +- .../src/plugins/gcscontrol/joystickcontrol.h | 1 + 3 files changed, 904 insertions(+), 1893 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/images/joystick.svg b/ground/openpilotgcs/src/plugins/gcscontrol/images/joystick.svg index 386881587..29d5c8762 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/images/joystick.svg +++ b/ground/openpilotgcs/src/plugins/gcscontrol/images/joystick.svg @@ -1,5 +1,5 @@ - + image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 50 % - - 75 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 75 % - - 50 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + inkscape:version="0.48.1 " + sodipodi:docname="joystick.svg"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp index d738da556..3e8e111df 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp +++ b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp @@ -60,13 +60,24 @@ JoystickControl::JoystickControl(QWidget *parent) : m_joystickEnd = new QGraphicsSvgItem(); m_joystickEnd->setSharedRenderer(m_renderer); m_joystickEnd->setElementId(QString("joystickEnd")); - m_joystickEnd->setPos(0,0); + + m_joystickArea = new QGraphicsSvgItem(); + m_joystickArea->setSharedRenderer(m_renderer); + m_joystickArea->setElementId(QString("joystickArea")); + m_joystickArea->setPos( + (m_background->boundingRect().width() - m_joystickArea->boundingRect().width()) * 0.5, + (m_background->boundingRect().height() - m_joystickArea->boundingRect().height()) * 0.5 + ); + m_joystickArea->setVisible(false); QGraphicsScene *l_scene = scene(); l_scene->clear(); // This also deletes all items contained in the scene. l_scene->addItem(m_background); + l_scene->addItem(m_joystickArea); l_scene->addItem(m_joystickEnd); l_scene->setSceneRect(m_background->boundingRect()); + + changePosition(0.0, 0.0); } JoystickControl::~JoystickControl() @@ -90,11 +101,12 @@ void JoystickControl::enableOpenGL(bool flag) */ void JoystickControl::changePosition(double x, double y) { - QRectF sceneSize = scene()->sceneRect(); - - m_joystickEnd->setPos( - (x+1) / 2*sceneSize.width() - m_joystickEnd->boundingRect().width() / 2, - (-y+1) / 2*sceneSize.height() - m_joystickEnd->boundingRect().height() / 2); + QRectF areaSize = m_joystickArea->boundingRect(); + QPointF point( + ((1 + x) * areaSize.width() - m_joystickEnd->boundingRect().width()) * 0.5, + ((1 - y) * areaSize.height() - m_joystickEnd->boundingRect().height()) * 0.5 + ); + m_joystickEnd->setPos(m_joystickArea->mapToScene(point)); } /** @@ -102,11 +114,11 @@ void JoystickControl::changePosition(double x, double y) */ void JoystickControl::mouseMoveEvent(QMouseEvent *event) { - QPointF point = mapToScene(event->pos()); - QRectF sceneSize = scene()->sceneRect(); + QPointF point = m_joystickArea->mapFromScene(mapToScene(event->pos())); + QSizeF areaSize = m_joystickArea->boundingRect().size(); - double Y = - (point.y() / sceneSize.height() - .5) * 2; - double X = (point.x() / sceneSize.width() - .5) * 2; + double Y = - (point.y() / areaSize.height() - .5) * 2; + double X = (point.x() / areaSize.width() - .5) * 2; if (Y<-1) Y = -1; if (Y> 1) Y = 1; if (X<-1) X = -1; diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h index 8492474e6..bd0871761 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h +++ b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h @@ -64,6 +64,7 @@ signals: private: QSvgRenderer *m_renderer; QGraphicsSvgItem *m_background; + QGraphicsSvgItem *m_joystickArea; QGraphicsSvgItem *m_joystickEnd; }; From 9006dd558f97dce5da4677be57f3cded0fb3cb4d Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Sat, 21 Jan 2012 00:52:35 +0200 Subject: [PATCH 46/72] gcscontrol: code style formatting and cleanup --- .../plugins/gcscontrol/joystickcontrol.cpp | 60 ++++++++----------- .../src/plugins/gcscontrol/joystickcontrol.h | 21 ++++--- 2 files changed, 36 insertions(+), 45 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp index 3e8e111df..0596b22c1 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp +++ b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp @@ -7,7 +7,7 @@ * @{ * @addtogroup GCSControlGadgetPlugin GCSControl Gadget Plugin * @{ - * @brief A that mimics a transmitter joystick and updates the MCC + * @brief The plugin that mimics a transmitter joystick and updates the MCC *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -28,30 +28,24 @@ #include "joystickcontrol.h" #include "extensionsystem/pluginmanager.h" #include -#include #include -#include -#include -#include -#include -#include #include -#include +#include /** * @brief Constructor for JoystickControl widget. Sets up the image of a joystick */ -JoystickControl::JoystickControl(QWidget *parent) : - QGraphicsView(parent) +JoystickControl::JoystickControl(QWidget *parent) : QGraphicsView(parent) { - setMinimumSize(64,64); + setMinimumSize(64, 64); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); setScene(new QGraphicsScene(this)); setRenderHints(QPainter::Antialiasing); m_renderer = new QSvgRenderer(); bool test = m_renderer->load(QString(":/gcscontrol/images/joystick.svg")); - Q_ASSERT( test ); + Q_UNUSED(test); + Q_ASSERT(test); m_background = new QGraphicsSvgItem(); m_background->setSharedRenderer(m_renderer); @@ -82,18 +76,18 @@ JoystickControl::JoystickControl(QWidget *parent) : JoystickControl::~JoystickControl() { - + // Do nothing } -/*! - \brief Enables/Disables OpenGL +/** + * @brief Enables/Disables OpenGL */ void JoystickControl::enableOpenGL(bool flag) { - if (flag) - setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); - else - setViewport(new QWidget); + if (flag) + setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); + else + setViewport(new QWidget); } /** @@ -103,8 +97,8 @@ void JoystickControl::changePosition(double x, double y) { QRectF areaSize = m_joystickArea->boundingRect(); QPointF point( - ((1 + x) * areaSize.width() - m_joystickEnd->boundingRect().width()) * 0.5, - ((1 - y) * areaSize.height() - m_joystickEnd->boundingRect().height()) * 0.5 + ((1.0 + x) * areaSize.width() - m_joystickEnd->boundingRect().width()) * 0.5, + ((1.0 - y) * areaSize.height() - m_joystickEnd->boundingRect().height()) * 0.5 ); m_joystickEnd->setPos(m_joystickArea->mapToScene(point)); } @@ -117,14 +111,14 @@ void JoystickControl::mouseMoveEvent(QMouseEvent *event) QPointF point = m_joystickArea->mapFromScene(mapToScene(event->pos())); QSizeF areaSize = m_joystickArea->boundingRect().size(); - double Y = - (point.y() / areaSize.height() - .5) * 2; - double X = (point.x() / areaSize.width() - .5) * 2; - if (Y<-1) Y = -1; - if (Y> 1) Y = 1; - if (X<-1) X = -1; - if (X> 1) X = 1; + double y = - (point.y() / areaSize.height() - 0.5) * 2.0; + double x = (point.x() / areaSize.width() - 0.5) * 2.0; + if (y < -1.0) y = -1.0; + if (y > 1.0) y = 1.0; + if (x < -1.0) x = -1.0; + if (x > 1.0) x = 1.0; - emit positionClicked(X, Y); + emit positionClicked(x, y); } /** @@ -132,12 +126,11 @@ void JoystickControl::mouseMoveEvent(QMouseEvent *event) */ void JoystickControl::mousePressEvent(QMouseEvent *event) { - if( event->button() == Qt::LeftButton ) { + if (event->button() == Qt::LeftButton) { mouseMoveEvent(event); } } - void JoystickControl::paint() { update(); @@ -145,9 +138,9 @@ void JoystickControl::paint() void JoystickControl::paintEvent(QPaintEvent *event) { - // Skip painting until the dial file is loaded - if (! m_renderer->isValid()) { - qDebug()<<"Image file not loaded, not rendering"; + // Skip painting until the image file is loaded + if (!m_renderer->isValid()) { + qDebug() << "Image file not loaded, not rendering"; } QGraphicsView::paintEvent(event); @@ -159,7 +152,6 @@ void JoystickControl::resizeEvent(QResizeEvent *event) fitInView(m_background, Qt::IgnoreAspectRatio ); } - /** * @} * @} diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h index bd0871761..9c6ac59d0 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h +++ b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.h @@ -7,7 +7,7 @@ * @{ * @addtogroup GCSControlGadgetPlugin GCSControl Gadget Plugin * @{ - * @brief A that mimics a transmitter joystick and updates the MCC + * @brief The plugin that mimics a transmitter joystick and updates the MCC *****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #ifndef JOYSTICKCONTROL_H #define JOYSTICKCONTROL_H @@ -46,27 +45,27 @@ class JoystickControl : public QGraphicsView public: explicit JoystickControl(QWidget *parent = 0); ~JoystickControl(); - void enableOpenGL(bool flag); - void paint(); + void enableOpenGL(bool flag); + void paint(); protected: - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); public slots: - void changePosition (double X, double Y); + void changePosition(double x, double y); signals: - void positionClicked(double X, double Y); + void positionClicked(double x, double y); private: QSvgRenderer *m_renderer; QGraphicsSvgItem *m_background; QGraphicsSvgItem *m_joystickArea; QGraphicsSvgItem *m_joystickEnd; - }; +}; #endif // JOYSTICKCONTROL_H From 3cbf4499e1903bb456febf2bae7effde109ee935 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sat, 21 Jan 2012 21:18:06 -0500 Subject: [PATCH 47/72] ld: make sure current pointer never goes backwards Fixes linking on ld version 2.22. --- .../STM32F10x/link_STM32103CB_CC_Rev1_sections.ld | 11 ++--------- flight/PiOS/STM32F10x/link_STM3210E_OP_sections.ld | 10 ++-------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/flight/PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld b/flight/PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld index d3e9f797e..ac579364b 100644 --- a/flight/PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld +++ b/flight/PiOS/STM32F10x/link_STM32103CB_CC_Rev1_sections.ld @@ -98,16 +98,9 @@ SECTIONS _init_stack_top = . - 4 ; } > SRAM + _eram = ORIGIN(SRAM) + LENGTH(SRAM) ; + _ebss = _eram ; - _free_ram = . ; - .free_ram (NOLOAD) : - { - . = ORIGIN(SRAM) + LENGTH(SRAM) - _free_ram ; - /* This is used by the startup in order to initialize the .bss section */ - _ebss = . ; - _eram = . ; - } > SRAM - /* keep the heap section at the end of the SRAM * this will allow to claim the remaining bytes not used * at run time! (done by the reset vector). diff --git a/flight/PiOS/STM32F10x/link_STM3210E_OP_sections.ld b/flight/PiOS/STM32F10x/link_STM3210E_OP_sections.ld index 066fa01ee..f23ed327f 100644 --- a/flight/PiOS/STM32F10x/link_STM3210E_OP_sections.ld +++ b/flight/PiOS/STM32F10x/link_STM3210E_OP_sections.ld @@ -275,14 +275,8 @@ SECTIONS _init_stack_top = . - 4 ; } > RAM - _free_ram = . ; - .free_ram (NOLOAD) : - { - . = ORIGIN(RAM) + LENGTH(RAM) - _free_ram ; - /* This is used by the startup in order to initialize the .bss section */ - _ebss = . ; - _eram = . ; - } > RAM + _eram = ORIGIN(SRAM) + LENGTH(SRAM) ; + _ebss = _eram ; /* keep the heap section at the end of the SRAM * this will allow to claim the remaining bytes not used From 6bb4f0c61dd3c6b839b017254b5d790cce07bea4 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 22 Jan 2012 18:22:59 -0500 Subject: [PATCH 48/72] leds: use boot-time config for PiOS LED layer LEDs are now configured based on a board-specific initialization in PIOS_BOARD_Init(). LEDs are now named: PIOS_LED_HEARTBEAT PIOS_LED_ALARM --- flight/AHRS/ahrs.c | 16 +-- flight/AHRS/pios_board.c | 31 +++++- flight/Bootloaders/AHRS/ahrs_slave_test.c | 4 +- flight/Bootloaders/AHRS/main.c | 24 ++--- flight/Bootloaders/AHRS/pios_board.c | 27 +++++ flight/Bootloaders/BootloaderUpdater/main.c | 16 +-- flight/Bootloaders/CopterControl/main.c | 19 ++-- flight/Bootloaders/CopterControl/pios_board.c | 29 +++++- flight/Bootloaders/OpenPilot/main.c | 20 ++-- flight/Bootloaders/OpenPilot/pios_board.c | 37 +++++++ flight/Bootloaders/PipXtreme/main.c | 20 ++-- flight/Bootloaders/PipXtreme/pios_board.c | 55 ++++++++++- flight/CopterControl/System/coptercontrol.c | 11 ++- flight/CopterControl/System/pios_board.c | 37 ++++++- flight/INS/ins.c | 16 +-- flight/INS/pios_board.c | 37 +++++++ flight/Modules/FirmwareIAP/firmwareiap.c | 13 ++- flight/Modules/System/systemmod.c | 12 ++- flight/OpenPilot/System/openpilot.c | 13 ++- flight/OpenPilot/System/pios_board.c | 47 ++++++++- flight/PiOS/Boards/STM32103CB_AHRS.h | 8 +- flight/PiOS/Boards/STM32103CB_CC_Rev1.h | 8 +- .../PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h | 49 ++++------ flight/PiOS/Boards/STM3210E_INS.h | 12 +-- flight/PiOS/Boards/STM3210E_OP.h | 12 +-- flight/PiOS/Common/pios_flashfs_objlist.c | 4 +- flight/PiOS/STM32F10x/pios_led.c | 98 ++++++++++++++----- flight/PiOS/STM32F10x/pios_sys.c | 36 +++---- flight/PiOS/inc/pios_led.h | 20 +--- flight/PiOS/inc/pios_led_priv.h | 54 ++++++++++ 30 files changed, 548 insertions(+), 237 deletions(-) create mode 100644 flight/PiOS/inc/pios_led_priv.h diff --git a/flight/AHRS/ahrs.c b/flight/AHRS/ahrs.c index 830245572..e8b5742e3 100644 --- a/flight/AHRS/ahrs.c +++ b/flight/AHRS/ahrs.c @@ -447,9 +447,9 @@ void print_ahrs_raw() valid_data_buffer = PIOS_ADC_GetRawBuffer(); if (total_conversion_blocks != previous_conversion + 1) - PIOS_LED_On(LED1); // not keeping up + PIOS_LED_On(PIOS_LED_HEARTBEAT); // not keeping up else - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); previous_conversion = total_conversion_blocks; @@ -463,9 +463,9 @@ void print_ahrs_raw() PIOS_ADC_NUM_PINS * sizeof(valid_data_buffer[0])); if (result == 0) - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); else { - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); } } #endif @@ -490,7 +490,7 @@ void print_ahrs_raw() // wait for new raw samples while (previous_conversion == total_conversion_blocks); if ((previous_conversion + 1) != total_conversion_blocks) - PIOS_LED_On(LED1); // we are not keeping up + PIOS_LED_On(PIOS_LED_HEARTBEAT); // we are not keeping up previous_conversion = total_conversion_blocks; // fetch the buffer address for the new samples @@ -534,9 +534,9 @@ void print_ahrs_raw() result += PIOS_COM_SendBufferNonBlocking(PIOS_COM_AUX, (uint8_t *)gyro_z, over_sampling * sizeof(gyro_z[0])); if (result != 0) - PIOS_LED_On(LED1); // all data not sent + PIOS_LED_On(PIOS_LED_HEARTBEAT); // all data not sent else - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } #endif @@ -616,7 +616,7 @@ for all data to be up to date before doing anything*/ // Alive signal if (((total_conversion_blocks % 100) & 0xFFFE) == 0) - PIOS_LED_Toggle(LED1); + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); // Delay for valid data diff --git a/flight/AHRS/pios_board.c b/flight/AHRS/pios_board.c index aa5b20855..cbd99a32a 100644 --- a/flight/AHRS/pios_board.c +++ b/flight/AHRS/pios_board.c @@ -25,6 +25,29 @@ #include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -365,7 +388,13 @@ void PIOS_Board_Init(void) { /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); - PIOS_LED_On(LED1); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_On(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ /* Delay system */ PIOS_DELAY_Init(); diff --git a/flight/Bootloaders/AHRS/ahrs_slave_test.c b/flight/Bootloaders/AHRS/ahrs_slave_test.c index 4ef55b975..d26957f1c 100644 --- a/flight/Bootloaders/AHRS/ahrs_slave_test.c +++ b/flight/Bootloaders/AHRS/ahrs_slave_test.c @@ -16,7 +16,7 @@ bool WriteData(uint32_t offset, uint8_t *buffer, uint32_t size) { PIOS_COM_SendFormattedString(PIOS_COM_AUX, "Wrote %d bytes to %d\r\n", size, offset); memcpy(buf, buffer, size); - PIOS_LED_Toggle(LED1); + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); return (true); } @@ -28,7 +28,7 @@ bool ReadData(uint32_t offset, uint8_t *buffer, uint32_t size) { PIOS_COM_SendFormattedString(PIOS_COM_AUX, "Read %d bytes from %d\r\n", size, offset); memcpy(buffer, buf, size); - PIOS_LED_Toggle(LED1); + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); return (true); } diff --git a/flight/Bootloaders/AHRS/main.c b/flight/Bootloaders/AHRS/main.c index b284e6365..756d12566 100644 --- a/flight/Bootloaders/AHRS/main.c +++ b/flight/Bootloaders/AHRS/main.c @@ -79,12 +79,7 @@ int main() { break; } } - //while(TRUE) - // { - // PIOS_LED_Toggle(LED1); - // PIOS_DELAY_WaitmS(1000); - // } - //GO_dfu = TRUE; + PIOS_IAP_Init(); GO_dfu = GO_dfu | PIOS_IAP_CheckRequest();// OR with app boot request if (GO_dfu == FALSE) { @@ -97,7 +92,7 @@ int main() { PIOS_Board_Init(); boot_status = idle; Fw_crc = PIOS_BL_HELPER_CRC_Memory_Calc(); - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); while (1) { process_spi_request(); } @@ -150,7 +145,7 @@ void process_spi_request(void) { Fw_crc = PIOS_BL_HELPER_CRC_Memory_Calc(); lfsm_user_set_tx_v0(&user_tx_v0); boot_status = idle; - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; break; case OPAHRS_MSG_V0_REQ_RESET: @@ -158,7 +153,6 @@ void process_spi_request(void) { PIOS_SYS_Reset(); break; case OPAHRS_MSG_V0_REQ_VERSIONS: - //PIOS_LED_On(LED1); opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_VERSIONS); user_tx_v0.payload.user.v.rsp.versions.bl_version = BOOTLOADER_VERSION; user_tx_v0.payload.user.v.rsp.versions.hw_version = (BOARD_TYPE << 8) @@ -191,7 +185,7 @@ void process_spi_request(void) { lfsm_user_set_tx_v0(&user_tx_v0); break; case OPAHRS_MSG_V0_REQ_FWUP_DATA: - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_FWUP_STATUS); if (!(user_rx_v0.payload.user.v.req.fwup_data.adress < bdinfo->fw_base)) { @@ -209,7 +203,7 @@ void process_spi_request(void) { } else { boot_status = outside_dev_capabilities; } - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; lfsm_user_set_tx_v0(&user_tx_v0); break; @@ -227,10 +221,10 @@ void process_spi_request(void) { opahrs_msg_v0_init_user_tx(&user_tx_v0, OPAHRS_MSG_V0_RSP_FWUP_STATUS); user_tx_v0.payload.user.v.rsp.fwup_status.status = boot_status; lfsm_user_set_tx_v0(&user_tx_v0); - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); if (PIOS_BL_HELPER_FLASH_Start() == TRUE) { boot_status = started; - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } else { boot_status = start_failed; break; @@ -254,15 +248,13 @@ void process_spi_request(void) { void jump_to_app() { const struct pios_board_info * bdinfo = &pios_board_info_blob; - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); if (((*(__IO uint32_t*) bdinfo->fw_base) & 0x2FFE0000) == 0x20000000) { /* Jump to user application */ FLASH_Lock(); RCC_APB2PeriphResetCmd(0xffffffff, ENABLE); RCC_APB1PeriphResetCmd(0xffffffff, ENABLE); RCC_APB2PeriphResetCmd(0xffffffff, DISABLE); RCC_APB1PeriphResetCmd(0xffffffff, DISABLE); - //_SetCNTR(0); // clear interrupt mask - //_SetISTR(0); // clear all requests JumpAddress = *(__IO uint32_t*) (bdinfo->fw_base + 4); Jump_To_Application = (pFunction) JumpAddress; diff --git a/flight/Bootloaders/AHRS/pios_board.c b/flight/Bootloaders/AHRS/pios_board.c index 756da9288..b779be4e3 100644 --- a/flight/Bootloaders/AHRS/pios_board.c +++ b/flight/Bootloaders/AHRS/pios_board.c @@ -25,6 +25,29 @@ #include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -138,6 +161,10 @@ void PIOS_Board_Init() { return; } +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + /* Set up the SPI interface to the OP board */ if (PIOS_SPI_Init(&pios_spi_op_id, &pios_spi_op_cfg)) { PIOS_DEBUG_Assert(0); diff --git a/flight/Bootloaders/BootloaderUpdater/main.c b/flight/Bootloaders/BootloaderUpdater/main.c index 9b1691dca..195a25b33 100644 --- a/flight/Bootloaders/BootloaderUpdater/main.c +++ b/flight/Bootloaders/BootloaderUpdater/main.c @@ -50,14 +50,14 @@ int main() { PIOS_SYS_Init(); PIOS_Board_Init(); - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); PIOS_DELAY_WaitmS(3000); - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); /// Self overwrite check uint32_t base_address = SCB->VTOR; if ((0x08000000 + embedded_image_size) > base_address) - error(LED1); + error(PIOS_LED_HEARTBEAT); /// FLASH_Unlock(); @@ -82,7 +82,7 @@ int main() { } if (fail == true) - error(LED1); + error(PIOS_LED_HEARTBEAT); /// @@ -90,7 +90,7 @@ int main() { /// Bootloader programing for (uint32_t offset = 0; offset < embedded_image_size/sizeof(uint32_t); ++offset) { bool result = false; - PIOS_LED_Toggle(LED1); + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); for (uint8_t retry = 0; retry < MAX_WRI_RETRYS; ++retry) { if (result == false) { result = (FLASH_ProgramWord(0x08000000 + (offset * 4), embedded_image_start[offset]) @@ -98,13 +98,13 @@ int main() { } } if (result == false) - error(LED1); + error(PIOS_LED_HEARTBEAT); } /// for (uint8_t x = 0; x < 3; ++x) { - PIOS_LED_On(LED1); + PIOS_LED_On(PIOS_LED_HEARTBEAT); PIOS_DELAY_WaitmS(1000); - PIOS_LED_Off(LED1); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); PIOS_DELAY_WaitmS(1000); } diff --git a/flight/Bootloaders/CopterControl/main.c b/flight/Bootloaders/CopterControl/main.c index 7a61ae9e9..17733bbef 100644 --- a/flight/Bootloaders/CopterControl/main.c +++ b/flight/Bootloaders/CopterControl/main.c @@ -69,7 +69,6 @@ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count); uint8_t processRX(); void jump_to_app(); -#define BLUE LED1 int main() { PIOS_SYS_Init(); if (BSL_HOLD_STATE == 0) @@ -112,7 +111,7 @@ int main() { case DFUidle: period1 = 5000; sweep_steps1 = 100; - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); period2 = 0; break; case uploading: @@ -124,12 +123,12 @@ int main() { case downloading: period1 = 2500; sweep_steps1 = 50; - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); period2 = 0; break; case BLidle: period1 = 0; - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); period2 = 0; break; default://error @@ -141,19 +140,19 @@ int main() { if (period1 != 0) { if (LedPWM(period1, sweep_steps1, stopwatch)) - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); else - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } else - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); if (period2 != 0) { if (LedPWM(period2, sweep_steps2, stopwatch)) - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); else - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } else - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); if (stopwatch > 50 * 1000 * 1000) stopwatch = 0; diff --git a/flight/Bootloaders/CopterControl/pios_board.c b/flight/Bootloaders/CopterControl/pios_board.c index a70537fcc..451a92871 100644 --- a/flight/Bootloaders/CopterControl/pios_board.c +++ b/flight/Bootloaders/CopterControl/pios_board.c @@ -25,7 +25,28 @@ #include -// *********************************************************************************** +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ #if defined(PIOS_INCLUDE_COM_MSG) @@ -33,8 +54,6 @@ #endif /* PIOS_INCLUDE_COM_MSG */ -// *********************************************************************************** - #if defined(PIOS_INCLUDE_USB) #include "pios_usb_priv.h" @@ -90,6 +109,10 @@ void PIOS_Board_Init(void) { /* Initialize the PiOS library */ PIOS_GPIO_Init(); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_USB) /* Initialize board specific USB data */ PIOS_USB_BOARD_DATA_Init(); diff --git a/flight/Bootloaders/OpenPilot/main.c b/flight/Bootloaders/OpenPilot/main.c index 3a06c9751..da39e2521 100644 --- a/flight/Bootloaders/OpenPilot/main.c +++ b/flight/Bootloaders/OpenPilot/main.c @@ -98,8 +98,6 @@ uint8_t processRX(); void jump_to_app(); uint32_t sspTimeSource(); -#define BLUE LED1 -#define RED LED2 #define LED_PWM_TIMER TIM6 int main() { PIOS_SYS_Init(); @@ -159,7 +157,7 @@ int main() { case DFUidle: period1 = 50; sweep_steps1 = 100; - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); period2 = 0; break; case uploading: @@ -171,12 +169,12 @@ int main() { case downloading: period1 = 25; sweep_steps1 = 50; - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); period2 = 0; break; case BLidle: period1 = 0; - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); period2 = 0; break; default://error @@ -188,19 +186,19 @@ int main() { if (period1 != 0) { if (LedPWM(period1, sweep_steps1, STOPWATCH_ValueGet(LED_PWM_TIMER))) - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); else - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } else - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); if (period2 != 0) { if (LedPWM(period2, sweep_steps2, STOPWATCH_ValueGet(LED_PWM_TIMER))) - PIOS_LED_On(RED); + PIOS_LED_On(PIOS_LED_ALARM); else - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); } else - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); if (STOPWATCH_ValueGet(LED_PWM_TIMER) > 100 * 50 * 100) STOPWATCH_Reset(LED_PWM_TIMER); diff --git a/flight/Bootloaders/OpenPilot/pios_board.c b/flight/Bootloaders/OpenPilot/pios_board.c index d1ba74d8b..43101aa03 100644 --- a/flight/Bootloaders/OpenPilot/pios_board.c +++ b/flight/Bootloaders/OpenPilot/pios_board.c @@ -29,6 +29,39 @@ //#include //#include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_ALARM] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -273,6 +306,10 @@ void PIOS_Board_Init(void) { PIOS_GPIO_Init(); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_USB) /* Initialize board specific USB data */ PIOS_USB_BOARD_DATA_Init(); diff --git a/flight/Bootloaders/PipXtreme/main.c b/flight/Bootloaders/PipXtreme/main.c index 602193f5c..908589178 100644 --- a/flight/Bootloaders/PipXtreme/main.c +++ b/flight/Bootloaders/PipXtreme/main.c @@ -69,8 +69,6 @@ uint32_t LedPWM(uint32_t pwm_period, uint32_t pwm_sweep_steps, uint32_t count); uint8_t processRX(); void jump_to_app(); -#define BLUE LED1 -#define RED LED4 int main() { PIOS_SYS_Init(); if (BSL_HOLD_STATE == 0) @@ -113,7 +111,7 @@ int main() { case DFUidle: period1 = 5000; sweep_steps1 = 100; - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); period2 = 0; break; case uploading: @@ -125,12 +123,12 @@ int main() { case downloading: period1 = 2500; sweep_steps1 = 50; - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); period2 = 0; break; case BLidle: period1 = 0; - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); period2 = 0; break; default://error @@ -142,19 +140,19 @@ int main() { if (period1 != 0) { if (LedPWM(period1, sweep_steps1, stopwatch)) - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); else - PIOS_LED_Off(BLUE); + PIOS_LED_Off(PIOS_LED_HEARTBEAT); } else - PIOS_LED_On(BLUE); + PIOS_LED_On(PIOS_LED_HEARTBEAT); if (period2 != 0) { if (LedPWM(period2, sweep_steps2, stopwatch)) - PIOS_LED_On(RED); + PIOS_LED_On(PIOS_LED_ALARM); else - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); } else - PIOS_LED_Off(RED); + PIOS_LED_Off(PIOS_LED_ALARM); if (stopwatch > 50 * 1000 * 1000) stopwatch = 0; diff --git a/flight/Bootloaders/PipXtreme/pios_board.c b/flight/Bootloaders/PipXtreme/pios_board.c index a70537fcc..60ec1db76 100644 --- a/flight/Bootloaders/PipXtreme/pios_board.c +++ b/flight/Bootloaders/PipXtreme/pios_board.c @@ -25,7 +25,58 @@ #include -// *********************************************************************************** +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_USB] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_LINK] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_RX] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_TX] = { + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ #if defined(PIOS_INCLUDE_COM_MSG) @@ -33,8 +84,6 @@ #endif /* PIOS_INCLUDE_COM_MSG */ -// *********************************************************************************** - #if defined(PIOS_INCLUDE_USB) #include "pios_usb_priv.h" diff --git a/flight/CopterControl/System/coptercontrol.c b/flight/CopterControl/System/coptercontrol.c index a7cd909d9..3c64141ec 100644 --- a/flight/CopterControl/System/coptercontrol.c +++ b/flight/CopterControl/System/coptercontrol.c @@ -72,7 +72,9 @@ int main() #ifdef ERASE_FLASH PIOS_Flash_W25X_EraseChip(); - PIOS_LED_Off(LED1); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Off(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ while (1) ; #endif @@ -88,13 +90,14 @@ int main() /* If all is well we will never reach here as the scheduler will now be running. */ /* Do some indication to user that something bad just happened */ - PIOS_LED_Off(LED1); while (1) { - PIOS_LED_Toggle(LED1); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ PIOS_DELAY_WaitmS(100); } - return 0; + return 0; } /** diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index a7197768d..afac2dff0 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -34,6 +34,29 @@ #include #include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -1058,6 +1081,15 @@ void PIOS_Board_Init(void) { EventDispatcherInitialize(); UAVObjInitialize(); +#if defined(PIOS_INCLUDE_RTC) + /* Initialize the real-time clock and its associated tick */ + PIOS_RTC_Init(&pios_rtc_main_cfg); +#endif + +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + HwSettingsInitialize(); #ifndef ERASE_FLASH @@ -1080,11 +1112,6 @@ void PIOS_Board_Init(void) { AlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT, SYSTEMALARMS_ALARM_CRITICAL); } -#if defined(PIOS_INCLUDE_RTC) - /* Initialize the real-time clock and its associated tick */ - PIOS_RTC_Init(&pios_rtc_main_cfg); -#endif - /* Initialize the task monitor library */ TaskMonitorInitialize(); diff --git a/flight/INS/ins.c b/flight/INS/ins.c index 92224a239..2fe538acc 100644 --- a/flight/INS/ins.c +++ b/flight/INS/ins.c @@ -94,18 +94,18 @@ void blink(int led, int times) void test_accel() { if(PIOS_BMA180_Test()) - blink(LED1, 1); + blink(PIOS_LED_HEARTBEAT, 1); else - blink(LED2, 1); + blink(PIOS_LED_ALARM, 1); } #if defined (PIOS_INCLUDE_HMC5883) void test_mag() { if(PIOS_HMC5883_Test()) - blink(LED1, 2); + blink(PIOS_LED_HEARTBEAT, 2); else - blink(LED2, 2); + blink(PIOS_LED_ALARM, 2); } #endif @@ -113,9 +113,9 @@ void test_mag() void test_pressure() { if(PIOS_BMP085_Test()) - blink(LED1, 3); + blink(PIOS_LED_HEARTBEAT, 3); else - blink(LED2, 3); + blink(PIOS_LED_ALARM, 3); } #endif @@ -123,9 +123,9 @@ void test_pressure() void test_imu() { if(PIOS_IMU3000_Test()) - blink(LED1, 4); + blink(PIOS_LED_HEARTBEAT, 4); else - blink(LED2, 4); + blink(PIOS_LED_ALARM, 4); } #endif diff --git a/flight/INS/pios_board.c b/flight/INS/pios_board.c index ffbf27c45..f1ef66d8e 100644 --- a/flight/INS/pios_board.c +++ b/flight/INS/pios_board.c @@ -31,6 +31,39 @@ #include +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_ALARM] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -520,6 +553,10 @@ void PIOS_Board_Init(void) { /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + /* Delay system */ PIOS_DELAY_Init(); diff --git a/flight/Modules/FirmwareIAP/firmwareiap.c b/flight/Modules/FirmwareIAP/firmwareiap.c index 21678397e..aaf2622bd 100644 --- a/flight/Modules/FirmwareIAP/firmwareiap.c +++ b/flight/Modules/FirmwareIAP/firmwareiap.c @@ -230,11 +230,14 @@ static uint32_t get_time(void) * Executed by event dispatcher callback to reset INS before resetting OP */ static void resetTask(UAVObjEvent * ev) -{ - PIOS_LED_Toggle(LED1); -#if (PIOS_LED_NUM > 1) - PIOS_LED_Toggle(LED2); -#endif +{ +#if defined (PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ + +#if defined (PIOS_LED_ALARM) + PIOS_LED_Toggle(PIOS_LED_ALARM); +#endif /* PIOS_LED_ALARM */ if((portTickType) (xTaskGetTickCount() - lastResetSysTime) > RESET_DELAY / portTICK_RATE_MS) { lastResetSysTime = xTaskGetTickCount(); diff --git a/flight/Modules/System/systemmod.c b/flight/Modules/System/systemmod.c index 7e476f686..cae6af590 100644 --- a/flight/Modules/System/systemmod.c +++ b/flight/Modules/System/systemmod.c @@ -177,16 +177,18 @@ static void systemTask(void *parameters) #endif // Flash the heartbeat LED - PIOS_LED_Toggle(LED1); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ // Turn on the error LED if an alarm is set -#if (PIOS_LED_NUM > 1) +#if defined (PIOS_LED_ALARM) if (AlarmsHasWarnings()) { - PIOS_LED_On(LED2); + PIOS_LED_On(PIOS_LED_ALARM); } else { - PIOS_LED_Off(LED2); + PIOS_LED_Off(PIOS_LED_ALARM); } -#endif +#endif /* PIOS_LED_ALARM */ FlightStatusData flightStatus; FlightStatusGet(&flightStatus); diff --git a/flight/OpenPilot/System/openpilot.c b/flight/OpenPilot/System/openpilot.c index c90f5fd81..affe65926 100644 --- a/flight/OpenPilot/System/openpilot.c +++ b/flight/OpenPilot/System/openpilot.c @@ -110,13 +110,12 @@ int main() /* If all is well we will never reach here as the scheduler will now be running. */ /* Do some indication to user that something bad just happened */ - PIOS_LED_Off(LED1); \ - for(;;) { \ - PIOS_LED_Toggle(LED1); \ - PIOS_DELAY_WaitmS(100); \ - }; - - return 0; + while (1) { +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ + PIOS_DELAY_WaitmS(100); + } } diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index 0fb873f0a..16da82cdd 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -36,6 +36,39 @@ //#define I2C_DEBUG_PIN 0 //#define USART_GPS_DEBUG_PIN 1 +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_ALARM] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + #if defined(PIOS_INCLUDE_SPI) #include @@ -1128,6 +1161,15 @@ void PIOS_Board_Init(void) { EventDispatcherInitialize(); UAVObjInitialize(); +#if defined(PIOS_INCLUDE_RTC) + /* Initialize the real-time clock and its associated tick */ + PIOS_RTC_Init(&pios_rtc_main_cfg); +#endif + +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + HwSettingsInitialize(); PIOS_WDG_Init(); @@ -1146,11 +1188,6 @@ void PIOS_Board_Init(void) { AlarmsSet(SYSTEMALARMS_ALARM_BOOTFAULT, SYSTEMALARMS_ALARM_CRITICAL); } -#if defined(PIOS_INCLUDE_RTC) - /* Initialize the real-time clock and its associated tick */ - PIOS_RTC_Init(&pios_rtc_main_cfg); -#endif - /* Initialize the task monitor library */ TaskMonitorInitialize(); diff --git a/flight/PiOS/Boards/STM32103CB_AHRS.h b/flight/PiOS/Boards/STM32103CB_AHRS.h index 26d88fce1..1852d60fb 100644 --- a/flight/PiOS/Boards/STM32103CB_AHRS.h +++ b/flight/PiOS/Boards/STM32103CB_AHRS.h @@ -71,13 +71,7 @@ TIM8 | | | | //------------------------ // PIOS_LED //------------------------ -#define PIOS_LED_LED1_GPIO_PORT GPIOA -#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_3 -#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOA -#define PIOS_LED_NUM 1 -#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT } -#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN } -#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK } +#define PIOS_LED_HEARTBEAT 0 //------------------------- // System Settings diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index 7773b9092..05214876f 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -83,13 +83,7 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 //------------------------ // PIOS_LED //------------------------ -#define PIOS_LED_LED1_GPIO_PORT GPIOA -#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_6 -#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOA -#define PIOS_LED_NUM 1 -#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT } -#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN } -#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK } +#define PIOS_LED_HEARTBEAT 0 //------------------------- // System Settings diff --git a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h index b918ead67..8d04e05a4 100644 --- a/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_PIPXTREME_Rev1.h @@ -80,42 +80,29 @@ TIM4 | STOPWATCH | // ***************************************************************** // PIOS_LED -#define PIOS_LED_LED1_GPIO_PORT GPIOA // USB Activity LED -#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_3 -#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOA +#define PIOS_LED_USB 0 +#define PIOS_LED_LINK 1 +#define PIOS_LED_RX 2 +#define PIOS_LED_TX 3 -#define PIOS_LED_LED2_GPIO_PORT GPIOB // LINK LED -#define PIOS_LED_LED2_GPIO_PIN GPIO_Pin_5 -#define PIOS_LED_LED2_GPIO_CLK RCC_APB2Periph_GPIOB +#define PIOS_LED_HEARTBEAT PIOS_LED_USB +#define PIOS_LED_ALARM PIOS_LED_TX -#define PIOS_LED_LED3_GPIO_PORT GPIOB // RX LED -#define PIOS_LED_LED3_GPIO_PIN GPIO_Pin_6 -#define PIOS_LED_LED3_GPIO_CLK RCC_APB2Periph_GPIOB +#define USB_LED_ON PIOS_LED_On(PIOS_LED_USB) +#define USB_LED_OFF PIOS_LED_Off(PIOS_LED_USB) +#define USB_LED_TOGGLE PIOS_LED_Toggle(PIOS_LED_USB) -#define PIOS_LED_LED4_GPIO_PORT GPIOB // TX LED -#define PIOS_LED_LED4_GPIO_PIN GPIO_Pin_7 -#define PIOS_LED_LED4_GPIO_CLK RCC_APB2Periph_GPIOB +#define LINK_LED_ON PIOS_LED_On(PIOS_LED_LINK) +#define LINK_LED_OFF PIOS_LED_Off(PIOS_LED_LINK) +#define LINK_LED_TOGGLE PIOS_LED_Toggle(PIOS_LED_LINK) -#define PIOS_LED_NUM 4 -#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT, PIOS_LED_LED2_GPIO_PORT, PIOS_LED_LED3_GPIO_PORT, PIOS_LED_LED4_GPIO_PORT } -#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN, PIOS_LED_LED2_GPIO_PIN, PIOS_LED_LED3_GPIO_PIN, PIOS_LED_LED4_GPIO_PIN } -#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK, PIOS_LED_LED2_GPIO_CLK, PIOS_LED_LED3_GPIO_CLK, PIOS_LED_LED4_GPIO_CLK } +#define RX_LED_ON PIOS_LED_On(PIOS_LED_RX) +#define RX_LED_OFF PIOS_LED_Off(PIOS_LED_RX) +#define RX_LED_TOGGLE PIOS_LED_Toggle(PIOS_LED_RX) -#define USB_LED_ON PIOS_LED_On(LED1) -#define USB_LED_OFF PIOS_LED_Off(LED1) -#define USB_LED_TOGGLE PIOS_LED_Toggle(LED1) - -#define LINK_LED_ON PIOS_LED_On(LED2) -#define LINK_LED_OFF PIOS_LED_Off(LED2) -#define LINK_LED_TOGGLE PIOS_LED_Toggle(LED2) - -#define RX_LED_ON PIOS_LED_On(LED3) -#define RX_LED_OFF PIOS_LED_Off(LED3) -#define RX_LED_TOGGLE PIOS_LED_Toggle(LED3) - -#define TX_LED_ON PIOS_LED_On(LED4) -#define TX_LED_OFF PIOS_LED_Off(LED4) -#define TX_LED_TOGGLE PIOS_LED_Toggle(LED4) +#define TX_LED_ON PIOS_LED_On(PIOS_LED_TX) +#define TX_LED_OFF PIOS_LED_Off(PIOS_LED_TX) +#define TX_LED_TOGGLE PIOS_LED_Toggle(PIOS_LED_TX) // ***************************************************************** // Timer interrupt diff --git a/flight/PiOS/Boards/STM3210E_INS.h b/flight/PiOS/Boards/STM3210E_INS.h index 37ca4abe3..77283a5e4 100644 --- a/flight/PiOS/Boards/STM3210E_INS.h +++ b/flight/PiOS/Boards/STM3210E_INS.h @@ -76,16 +76,8 @@ TIM8 | | | | //------------------------ // PIOS_LED //------------------------ -#define PIOS_LED_LED1_GPIO_PORT GPIOA -#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_3 -#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOA -#define PIOS_LED_LED2_GPIO_PORT GPIOA -#define PIOS_LED_LED2_GPIO_PIN GPIO_Pin_2 -#define PIOS_LED_LED2_GPIO_CLK RCC_APB2Periph_GPIOA -#define PIOS_LED_NUM 2 -#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT, PIOS_LED_LED2_GPIO_PORT } -#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN, PIOS_LED_LED2_GPIO_PIN } -#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK, PIOS_LED_LED2_GPIO_CLK } +#define PIOS_LED_HEARTBEAT 0 +#define PIOS_LED_ALARM 1 //------------------------ // PIOS_SPI diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index 7099234c6..4b5067888 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -91,16 +91,8 @@ TIM8 | Servo 5 | Servo 6 | Servo 7 | Servo 8 //------------------------ // PIOS_LED //------------------------ -#define PIOS_LED_LED1_GPIO_PORT GPIOC -#define PIOS_LED_LED1_GPIO_PIN GPIO_Pin_12 -#define PIOS_LED_LED1_GPIO_CLK RCC_APB2Periph_GPIOC -#define PIOS_LED_LED2_GPIO_PORT GPIOC -#define PIOS_LED_LED2_GPIO_PIN GPIO_Pin_13 -#define PIOS_LED_LED2_GPIO_CLK RCC_APB2Periph_GPIOC -#define PIOS_LED_NUM 2 -#define PIOS_LED_PORTS { PIOS_LED_LED1_GPIO_PORT, PIOS_LED_LED2_GPIO_PORT } -#define PIOS_LED_PINS { PIOS_LED_LED1_GPIO_PIN, PIOS_LED_LED2_GPIO_PIN } -#define PIOS_LED_CLKS { PIOS_LED_LED1_GPIO_CLK, PIOS_LED_LED2_GPIO_CLK } +#define PIOS_LED_HEARTBEAT 0 +#define PIOS_LED_ALARM 1 //------------------------ // PIOS_SPI diff --git a/flight/PiOS/Common/pios_flashfs_objlist.c b/flight/PiOS/Common/pios_flashfs_objlist.c index e02683657..b4322ab78 100644 --- a/flight/PiOS/Common/pios_flashfs_objlist.c +++ b/flight/PiOS/Common/pios_flashfs_objlist.c @@ -81,7 +81,9 @@ int32_t PIOS_FLASHFS_Init() if(object_table_magic != OBJECT_TABLE_MAGIC) { if(magic_fail_count++ > MAX_BADMAGIC) { PIOS_FLASHFS_ClearObjectTableHeader(); - PIOS_LED_Toggle(LED1); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ magic_fail_count = 0; magic_good = true; } else { diff --git a/flight/PiOS/STM32F10x/pios_led.c b/flight/PiOS/STM32F10x/pios_led.c index 76b5bcccf..5db5cc884 100644 --- a/flight/PiOS/STM32F10x/pios_led.c +++ b/flight/PiOS/STM32F10x/pios_led.c @@ -33,57 +33,107 @@ #if defined(PIOS_INCLUDE_LED) -/* Private Function Prototypes */ +#include -/* Local Variables */ -static GPIO_TypeDef *LED_GPIO_PORT[PIOS_LED_NUM] = PIOS_LED_PORTS; -static const uint32_t LED_GPIO_PIN[PIOS_LED_NUM] = PIOS_LED_PINS; -static const uint32_t LED_GPIO_CLK[PIOS_LED_NUM] = PIOS_LED_CLKS; +const static struct pios_led_cfg * led_cfg; /** * Initialises all the LED's */ -void PIOS_LED_Init(void) +int32_t PIOS_LED_Init(const struct pios_led_cfg * cfg) { - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + PIOS_Assert(cfg); - for (int LEDNum = 0; LEDNum < PIOS_LED_NUM; LEDNum++) { - RCC_APB2PeriphClockCmd(LED_GPIO_CLK[LEDNum], ENABLE); - GPIO_InitStructure.GPIO_Pin = LED_GPIO_PIN[LEDNum]; - GPIO_Init(LED_GPIO_PORT[LEDNum], &GPIO_InitStructure); + /* Store away the config in a global used by API functions */ + led_cfg = cfg; - /* LED's Off */ - LED_GPIO_PORT[LEDNum]->BSRR = LED_GPIO_PIN[LEDNum]; + for (uint8_t i = 0; i < cfg->num_leds; i++) { + const struct pios_led * led = &(cfg->leds[i]); + + /* Enable the peripheral clock for the GPIO */ + switch ((uint32_t)led->pin.gpio) { + case (uint32_t) GPIOA: + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + break; + case (uint32_t) GPIOB: + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + break; + case (uint32_t) GPIOC: + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + break; + default: + PIOS_Assert(0); + break; + } + + if (led->remap) { + GPIO_PinRemapConfig(led->remap, ENABLE); + } + + GPIO_Init(led->pin.gpio, &led->pin.init); + + PIOS_LED_Off(i); } + + return 0; } /** * Turn on LED -* \param[in] LED LED Name (LED1, LED2) +* \param[in] LED LED id */ -void PIOS_LED_On(LedTypeDef LED) +void PIOS_LED_On(uint32_t led_id) { - LED_GPIO_PORT[LED]->BRR = LED_GPIO_PIN[LED]; + PIOS_Assert(led_cfg); + + if (led_id >= led_cfg->num_leds) { + /* LED index out of range */ + return; + } + + const struct pios_led * led = &(led_cfg->leds[led_id]); + + GPIO_ResetBits(led->pin.gpio, led->pin.init.GPIO_Pin); } /** * Turn off LED -* \param[in] LED LED Name (LED1, LED2) +* \param[in] LED LED id */ -void PIOS_LED_Off(LedTypeDef LED) +void PIOS_LED_Off(uint32_t led_id) { - LED_GPIO_PORT[LED]->BSRR = LED_GPIO_PIN[LED]; + PIOS_Assert(led_cfg); + + if (led_id >= led_cfg->num_leds) { + /* LED index out of range */ + return; + } + + const struct pios_led * led = &(led_cfg->leds[led_id]); + + GPIO_SetBits(led->pin.gpio, led->pin.init.GPIO_Pin); } /** * Toggle LED on/off -* \param[in] LED LED Name (LED1, LED2) +* \param[in] LED LED id */ -void PIOS_LED_Toggle(LedTypeDef LED) +void PIOS_LED_Toggle(uint32_t led_id) { - LED_GPIO_PORT[LED]->ODR ^= LED_GPIO_PIN[LED]; + PIOS_Assert(led_cfg); + + if (led_id >= led_cfg->num_leds) { + /* LED index out of range */ + return; + } + + const struct pios_led * led = &(led_cfg->leds[led_id]); + + if (GPIO_ReadOutputDataBit(led->pin.gpio, led->pin.init.GPIO_Pin) == Bit_SET) { + PIOS_LED_On(led_id); + } else { + PIOS_LED_Off(led_id); + } } #endif diff --git a/flight/PiOS/STM32F10x/pios_sys.c b/flight/PiOS/STM32F10x/pios_sys.c index cc35194e7..632be2426 100644 --- a/flight/PiOS/STM32F10x/pios_sys.c +++ b/flight/PiOS/STM32F10x/pios_sys.c @@ -77,10 +77,6 @@ void PIOS_SYS_Init(void) /* Initialise Basic NVIC */ NVIC_Configuration(); -#if defined(PIOS_INCLUDE_LED) - /* Initialise LEDs */ - PIOS_LED_Init(); -#endif } /** @@ -105,16 +101,12 @@ int32_t PIOS_SYS_Reset(void) PIOS_IRQ_Disable(); // turn off all board LEDs -#if (PIOS_LED_NUM == 1) - PIOS_LED_Off(LED1); -#elif (PIOS_LED_NUM == 2) - PIOS_LED_Off(LED1); - PIOS_LED_Off(LED2); -#endif - - /* Reset STM32 */ - //RCC_APB2PeriphResetCmd(0xfffffff8, ENABLE); /* MBHP_CORE_STM32: don't reset GPIOA/AF due to USB pins */ - //RCC_APB1PeriphResetCmd(0xff7fffff, ENABLE); /* don't reset USB, so that the connection can survive! */ +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Off(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ +#if defined(PIOS_LED_ALARM) + PIOS_LED_Off(PIOS_LED_ALARM); +#endif /* PIOS_LED_ALARM */ RCC_APB2PeriphResetCmd(0xffffffff, DISABLE); RCC_APB1PeriphResetCmd(0xffffffff, DISABLE); @@ -210,13 +202,21 @@ void assert_failed(uint8_t * file, uint32_t line) /* printf("Wrong parameters value: file %s on line %d\r\n", file, line); */ /* Setup the LEDs to Alternate */ - PIOS_LED_On(LED1); - PIOS_LED_Off(LED2); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_On(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ +#if defined(PIOS_LED_ALARM) + PIOS_LED_Off(PIOS_LED_ALARM); +#endif /* PIOS_LED_ALARM */ /* Infinite loop */ while (1) { - PIOS_LED_Toggle(LED1); - PIOS_LED_Toggle(LED2); +#if defined(PIOS_LED_HEARTBEAT) + PIOS_LED_Toggle(PIOS_LED_HEARTBEAT); +#endif /* PIOS_LED_HEARTBEAT */ +#if defined(PIOS_LED_ALARM) + PIOS_LED_Toggle(PIOS_LED_ALARM); +#endif /* PIOS_LED_ALARM */ for (int i = 0; i < 1000000; i++) ; } } diff --git a/flight/PiOS/inc/pios_led.h b/flight/PiOS/inc/pios_led.h index c18ea3524..2506b75cf 100644 --- a/flight/PiOS/inc/pios_led.h +++ b/flight/PiOS/inc/pios_led.h @@ -30,23 +30,9 @@ #ifndef PIOS_LED_H #define PIOS_LED_H -/* Type Definitions */ -#if (PIOS_LED_NUM == 1) -typedef enum { LED1 = 0 } LedTypeDef; -#elif (PIOS_LED_NUM == 2) -typedef enum { LED1 = 0, LED2 = 1 } LedTypeDef; -#elif (PIOS_LED_NUM == 3) -typedef enum { LED1 = 0, LED2 = 1, LED3 = 2 } LedTypeDef; -#elif (PIOS_LED_NUM == 4) -typedef enum { LED1 = 0, LED2 = 1, LED3 = 2, LED4 = 3 } LedTypeDef; -#else -#error PIOS_LED_NUM not defined -#endif - /* Public Functions */ -extern void PIOS_LED_Init(void); -extern void PIOS_LED_On(LedTypeDef LED); -extern void PIOS_LED_Off(LedTypeDef LED); -extern void PIOS_LED_Toggle(LedTypeDef LED); +extern void PIOS_LED_On(uint32_t led_id); +extern void PIOS_LED_Off(uint32_t led_id); +extern void PIOS_LED_Toggle(uint32_t led_id); #endif /* PIOS_LED_H */ diff --git a/flight/PiOS/inc/pios_led_priv.h b/flight/PiOS/inc/pios_led_priv.h new file mode 100644 index 000000000..20f09eafc --- /dev/null +++ b/flight/PiOS/inc/pios_led_priv.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_LED LED Functions + * @brief PIOS interface for LEDs + * @{ + * + * @file pios_led_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief LED private definitions. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_LED_PRIV_H +#define PIOS_LED_PRIV_H + +#include +#include + +struct pios_led { + struct stm32_gpio pin; + uint32_t remap; +}; + +struct pios_led_cfg { + const struct pios_led * leds; + uint8_t num_leds; +}; + +extern int32_t PIOS_LED_Init(const struct pios_led_cfg * cfg); + +#endif /* PIOS_LED_PRIV_H */ + +/** + * @} + * @} + */ From dc4aa07a329b89646bf7be0a55f7fa4c57dc669f Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 22 Jan 2012 19:41:41 -0500 Subject: [PATCH 49/72] board_hw_defs: factor out board-specific hw config definitions Board specific HW configuration is now collected in a single .c file for each board. This HW configuration is #include'd into the FW, BL and BU builds for each board. These new .c files are found in: flight/board_hw_defs//board_hw_defs.c Parts of this information were previously duplicated between the BL and FW builds. This commit cleans up the duplication. Using a #include on a .c file is a bit ugly but it allows us to ensure that all of the symbols in the board_hw_defs.c file are *ONLY* used in the PIOS_Board_Init() function for each software build. --- flight/AHRS/Makefile | 2 + flight/AHRS/pios_board.c | 357 +----- flight/Bootloaders/AHRS/Makefile | 3 +- flight/Bootloaders/AHRS/pios_board.c | 135 +- flight/Bootloaders/BootloaderUpdater/Makefile | 2 + .../BootloaderUpdater/pios_board.c | 13 + flight/Bootloaders/CopterControl/Makefile | 4 +- flight/Bootloaders/CopterControl/pios_board.c | 68 +- flight/Bootloaders/OpenPilot/Makefile | 2 + flight/Bootloaders/OpenPilot/pios_board.c | 241 +--- flight/CopterControl/Makefile | 2 + flight/CopterControl/System/inc/pios_config.h | 1 + flight/CopterControl/System/pios_board.c | 1017 +-------------- flight/INS/Makefile | 2 + flight/INS/pios_board.c | 507 +------- flight/OpenPilot/Makefile | 2 + flight/OpenPilot/System/inc/pios_config.h | 1 + flight/OpenPilot/System/pios_board.c | 1085 +---------------- flight/PipXtreme/Makefile | 3 +- flight/PipXtreme/pios_board.c | 309 +---- flight/board_hw_defs/ahrs/board_hw_defs.c | 351 ++++++ .../coptercontrol/board_hw_defs.c | 1018 ++++++++++++++++ flight/board_hw_defs/ins/board_hw_defs.c | 496 ++++++++ .../board_hw_defs/openpilot/board_hw_defs.c | 1085 +++++++++++++++++ .../board_hw_defs/pipxtreme/board_hw_defs.c | 273 +++++ 25 files changed, 3332 insertions(+), 3647 deletions(-) create mode 100644 flight/board_hw_defs/ahrs/board_hw_defs.c create mode 100644 flight/board_hw_defs/coptercontrol/board_hw_defs.c create mode 100644 flight/board_hw_defs/ins/board_hw_defs.c create mode 100644 flight/board_hw_defs/openpilot/board_hw_defs.c create mode 100644 flight/board_hw_defs/pipxtreme/board_hw_defs.c diff --git a/flight/AHRS/Makefile b/flight/AHRS/Makefile index 1943cc3a6..17559cf58 100644 --- a/flight/AHRS/Makefile +++ b/flight/AHRS/Makefile @@ -71,6 +71,7 @@ OPUAVOBJINC = $(OPUAVOBJ)/inc OPSYSINC = $(OPDIR)/System/inc BOOT = ../Bootloaders/AHRS BOOTINC = $(BOOT)/inc +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) OPUAVSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight @@ -170,6 +171,7 @@ EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(AHRSINC) EXTRAINCDIRS += $(OPUAVSYNTHDIR) EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/AHRS/pios_board.c b/flight/AHRS/pios_board.c index cbd99a32a..2eb6ab668 100644 --- a/flight/AHRS/pios_board.c +++ b/flight/AHRS/pios_board.c @@ -23,359 +23,20 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* OP Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). - */ -void PIOS_SPI_op_irq_handler(void); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_irq_handler"))); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_irq_handler"))); -static const struct pios_spi_cfg pios_spi_op_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Slave, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Hard, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - }, - .use_crc = TRUE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = - (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | - DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = - (uint32_t) & (SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = - DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = - DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = - DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = - (uint32_t) & (SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = - DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = - DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = - DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -uint32_t pios_spi_op_id; -void PIOS_SPI_op_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_op_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - -/* - * ADC system - */ -#include "pios_adc_priv.h" -extern void PIOS_ADC_handler(void); -void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); -// Remap the ADC DMA handler to this one -static const struct pios_adc_cfg pios_adc_cfg = { - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - .irq = { - .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), - .init = { - .NVIC_IRQChannel = DMA1_Channel1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .channel = DMA1_Channel1, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, - .DMA_Mode = DMA_Mode_Circular, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - } - }, - .half_flag = DMA1_IT_HT1, - .full_flag = DMA1_IT_TC1, -}; - -struct pios_adc_dev pios_adc_devs[] = { - { - .cfg = &pios_adc_cfg, - .callback_function = NULL, - }, -}; - -uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); - -void PIOS_ADC_handler() { - PIOS_ADC_DMA_Handler(); -} - - -#if defined(PIOS_INCLUDE_USART) -#include - -/* - * AUX USART - */ -static const struct pios_usart_cfg pios_usart_aux_cfg = { - .regs = USART3, - .init = { - .USART_BaudRate = 230400, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = - USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#endif /* PIOS_INCLUDE_USART */ - -#if defined(PIOS_INCLUDE_COM) - -#include - #define PIOS_COM_AUX_TX_BUF_LEN 192 static uint8_t pios_com_aux_tx_buffer[PIOS_COM_AUX_TX_BUF_LEN]; -#endif /* PIOS_INCLUDE_COM */ - -#if defined(PIOS_INCLUDE_I2C) - -#include - -/* - * I2C Adapters - */ - -void PIOS_I2C_main_adapter_ev_irq_handler(void); -void PIOS_I2C_main_adapter_er_irq_handler(void); -void I2C1_EV_IRQHandler() - __attribute__ ((alias("PIOS_I2C_main_adapter_ev_irq_handler"))); -void I2C1_ER_IRQHandler() - __attribute__ ((alias("PIOS_I2C_main_adapter_er_irq_handler"))); - -static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { - .regs = I2C1, - .init = { - .I2C_Mode = I2C_Mode_I2C, - .I2C_OwnAddress1 = 0, - .I2C_Ack = I2C_Ack_Enable, - .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_DutyCycle = I2C_DutyCycle_2, - .I2C_ClockSpeed = 200000, /* bits/s */ - }, - .transfer_timeout_ms = 50, - .scl = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .sda = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .event = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C1_EV_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .error = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C1_ER_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -uint32_t pios_i2c_main_adapter_id; -void PIOS_I2C_main_adapter_ev_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id); -} - -void PIOS_I2C_main_adapter_er_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id); -} - -#endif /* PIOS_INCLUDE_I2C */ - -#if defined(PIOS_ENABLE_DEBUG_PINS) - -static const struct stm32_gpio pios_debug_pins[] = { - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, -}; - -#endif /* PIOS_ENABLE_DEBUG_PINS */ - -extern const struct pios_com_driver pios_usart_com_driver; - uint32_t pios_com_aux_id; uint8_t adc_fifo_buf[sizeof(float) * 6 * 4] __attribute__ ((aligned(4))); // align to 32-bit to try and provide speed improvement diff --git a/flight/Bootloaders/AHRS/Makefile b/flight/Bootloaders/AHRS/Makefile index 833dba72b..b4a060373 100644 --- a/flight/Bootloaders/AHRS/Makefile +++ b/flight/Bootloaders/AHRS/Makefile @@ -65,7 +65,7 @@ STMUSBDIR = $(STMLIBDIR)/STM32_USB-FS-Device_Driver STMSPDSRCDIR = $(STMSPDDIR)/src STMSPDINCDIR = $(STMSPDDIR)/inc CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3 - +HWDEFSINC = ../../board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -155,6 +155,7 @@ EXTRAINCDIRS += $(PIOSBOARDS) EXTRAINCDIRS += $(STMSPDINCDIR) EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(AHRS_BLINC) +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/Bootloaders/AHRS/pios_board.c b/flight/Bootloaders/AHRS/pios_board.c index b779be4e3..9b9eac875 100644 --- a/flight/Bootloaders/AHRS/pios_board.c +++ b/flight/Bootloaders/AHRS/pios_board.c @@ -23,135 +23,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include - -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* OP Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE */ -void PIOS_SPI_op_irq_handler(void); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_op_irq_handler"))); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_op_irq_handler"))); -static const struct pios_spi_cfg - pios_spi_op_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Slave, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Hard, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - }, - .use_crc = TRUE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, +#include "board_hw_defs.c" - .irq = { - .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, }; - -uint32_t pios_spi_op_id; -void PIOS_SPI_op_irq_handler(void) { - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_op_id); -} - -#endif /* PIOS_INCLUDE_SPI */ +#include #include "bl_fsm.h" /* lfsm_* */ diff --git a/flight/Bootloaders/BootloaderUpdater/Makefile b/flight/Bootloaders/BootloaderUpdater/Makefile index aabfc88bf..62fc2c056 100644 --- a/flight/Bootloaders/BootloaderUpdater/Makefile +++ b/flight/Bootloaders/BootloaderUpdater/Makefile @@ -89,6 +89,7 @@ RTOSDIR = $(APPLIBDIR)/FreeRTOS RTOSSRCDIR = $(RTOSDIR)/Source RTOSINCDIR = $(RTOSSRCDIR)/include DOXYGENDIR = ../Doc/Doxygen +HWDEFSINC = $(TOP)/flight/board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -165,6 +166,7 @@ EXTRAINCDIRS += $(MSDDIR) EXTRAINCDIRS += $(RTOSINCDIR) EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 +EXTRAINCDIRS += $(HWDEFSINC) diff --git a/flight/Bootloaders/BootloaderUpdater/pios_board.c b/flight/Bootloaders/BootloaderUpdater/pios_board.c index 5d25eb140..d19a2ba13 100644 --- a/flight/Bootloaders/BootloaderUpdater/pios_board.c +++ b/flight/Bootloaders/BootloaderUpdater/pios_board.c @@ -23,6 +23,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include void PIOS_Board_Init(void) { @@ -38,4 +47,8 @@ void PIOS_Board_Init(void) { /* Initialize the PiOS library */ PIOS_GPIO_Init(); +#if defined(PIOS_INCLUDE_LED) + PIOS_LED_Init(&pios_led_cfg); +#endif /* PIOS_INCLUDE_LED */ + } diff --git a/flight/Bootloaders/CopterControl/Makefile b/flight/Bootloaders/CopterControl/Makefile index 699fd02e5..be7e98190 100644 --- a/flight/Bootloaders/CopterControl/Makefile +++ b/flight/Bootloaders/CopterControl/Makefile @@ -86,6 +86,7 @@ RTOSDIR = $(APPLIBDIR)/FreeRTOS RTOSSRCDIR = $(RTOSDIR)/Source RTOSINCDIR = $(RTOSSRCDIR)/include DOXYGENDIR = ../Doc/Doxygen +HWDEFSINC = ../../board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -198,8 +199,7 @@ EXTRAINCDIRS += $(MSDDIR) EXTRAINCDIRS += $(RTOSINCDIR) EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 - - +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/Bootloaders/CopterControl/pios_board.c b/flight/Bootloaders/CopterControl/pios_board.c index 451a92871..c5bd761ea 100644 --- a/flight/Bootloaders/CopterControl/pios_board.c +++ b/flight/Bootloaders/CopterControl/pios_board.c @@ -23,67 +23,17 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_COM_MSG) - -#include - -#endif /* PIOS_INCLUDE_COM_MSG */ - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_only_priv.h" - -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; - -#endif /* PIOS_INCLUDE_USB_HID */ - uint32_t pios_com_telem_usb_id; /** diff --git a/flight/Bootloaders/OpenPilot/Makefile b/flight/Bootloaders/OpenPilot/Makefile index 05d1bec1d..071b20fec 100644 --- a/flight/Bootloaders/OpenPilot/Makefile +++ b/flight/Bootloaders/OpenPilot/Makefile @@ -86,6 +86,7 @@ RTOSDIR = $(APPLIBDIR)/FreeRTOS RTOSSRCDIR = $(RTOSDIR)/Source RTOSINCDIR = $(RTOSSRCDIR)/include DOXYGENDIR = ../Doc/Doxygen +HWDEFSINC = ../../board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -206,6 +207,7 @@ EXTRAINCDIRS += $(MSDDIR) EXTRAINCDIRS += $(RTOSINCDIR) EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 +EXTRAINCDIRS += $(HWDEFSINC) diff --git a/flight/Bootloaders/OpenPilot/pios_board.c b/flight/Bootloaders/OpenPilot/pios_board.c index 43101aa03..beee6ea7f 100644 --- a/flight/Bootloaders/OpenPilot/pios_board.c +++ b/flight/Bootloaders/OpenPilot/pios_board.c @@ -25,197 +25,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include -//#include -//#include - -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_ALARM] = { - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* AHRS Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). - */ -void PIOS_SPI_ahrs_irq_handler(void); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); -const struct pios_spi_cfg - pios_spi_ahrs_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Master, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Soft, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8, - }, - .use_crc = TRUE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, }; - -uint32_t pios_spi_ahrs_id; -void PIOS_SPI_ahrs_irq_handler(void) { - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_ahrs_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - -#if defined(PIOS_INCLUDE_USART) - -#include "pios_usart_priv.h" - -/* - * Telemetry USART - */ -const struct pios_usart_cfg pios_usart_telem_cfg = { - .regs = USART2, - .init = { -#if defined (PIOS_COM_TELEM_BAUDRATE) - .USART_BaudRate = PIOS_COM_TELEM_BAUDRATE, -#else - .USART_BaudRate = 57600, -#endif - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, .irq = { - .init = { - .NVIC_IRQChannel = USART2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, }; - -#endif /* PIOS_INCLUDE_USART */ - -#if defined(PIOS_INCLUDE_COM) - -#include "pios_com_priv.h" #define PIOS_COM_TELEM_RF_RX_BUF_LEN 192 #define PIOS_COM_TELEM_RF_TX_BUF_LEN 192 @@ -223,48 +42,6 @@ const struct pios_usart_cfg pios_usart_telem_cfg = { static uint8_t pios_com_telem_rf_rx_buffer[PIOS_COM_TELEM_RF_RX_BUF_LEN]; static uint8_t pios_com_telem_rf_tx_buffer[PIOS_COM_TELEM_RF_TX_BUF_LEN]; -#endif /* PIOS_INCLUDE_COM */ - -// *********************************************************************************** - -#if defined(PIOS_INCLUDE_COM_MSG) - -#include - -#endif /* PIOS_INCLUDE_COM_MSG */ - -// *********************************************************************************** - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_only_priv.h" - -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; - -#endif /* PIOS_INCLUDE_USB_HID */ - uint32_t pios_com_telem_rf_id; uint32_t pios_com_telem_usb_id; diff --git a/flight/CopterControl/Makefile b/flight/CopterControl/Makefile index 9b2b95397..39afb2cee 100644 --- a/flight/CopterControl/Makefile +++ b/flight/CopterControl/Makefile @@ -121,6 +121,7 @@ PYMITEINC += $(PYMITEPLAT) PYMITEINC += $(OUTDIR) FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) OPUAVSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight @@ -348,6 +349,7 @@ EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 EXTRAINCDIRS += $(AHRSBOOTLOADERINC) EXTRAINCDIRS += $(PYMITEINC) +EXTRAINCDIRS += $(HWDEFSINC) EXTRAINCDIRS += ${foreach MOD, ${OPTMODULES} ${MODULES}, ${OPMODULEDIR}/${MOD}/inc} ${OPMODULEDIR}/System/inc diff --git a/flight/CopterControl/System/inc/pios_config.h b/flight/CopterControl/System/inc/pios_config.h index 004104f70..de954b666 100644 --- a/flight/CopterControl/System/inc/pios_config.h +++ b/flight/CopterControl/System/inc/pios_config.h @@ -43,6 +43,7 @@ #define PIOS_INCLUDE_IRQ #define PIOS_INCLUDE_LED #define PIOS_INCLUDE_IAP +#define PIOS_INCLUDE_TIM #define PIOS_INCLUDE_RCVR diff --git a/flight/CopterControl/System/pios_board.c b/flight/CopterControl/System/pios_board.c index afac2dff0..a103c3d17 100644 --- a/flight/CopterControl/System/pios_board.c +++ b/flight/CopterControl/System/pios_board.c @@ -27,6 +27,15 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include #include #include @@ -34,774 +43,11 @@ #include #include -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* Flash/Accel Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). +/* One slot per selectable receiver group. + * eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS + * NOTE: No slot in this map for NONE. */ -void PIOS_SPI_flash_accel_irq_handler(void); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_flash_accel_irq_handler"))); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_flash_accel_irq_handler"))); -static const struct pios_spi_cfg pios_spi_flash_accel_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Master, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Soft, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, - }, - .use_crc = FALSE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -static uint32_t pios_spi_flash_accel_id; -void PIOS_SPI_flash_accel_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_flash_accel_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - -/* - * ADC system - */ -#include "pios_adc_priv.h" -extern void PIOS_ADC_handler(void); -void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); -// Remap the ADC DMA handler to this one -static const struct pios_adc_cfg pios_adc_cfg = { - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - .irq = { - .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), - .init = { - .NVIC_IRQChannel = DMA1_Channel1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .channel = DMA1_Channel1, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, - .DMA_Mode = DMA_Mode_Circular, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - } - }, - .half_flag = DMA1_IT_HT1, - .full_flag = DMA1_IT_TC1, -}; - -struct pios_adc_dev pios_adc_devs[] = { - { - .cfg = &pios_adc_cfg, - .callback_function = NULL, - }, -}; - -uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); - -void PIOS_ADC_handler() { - PIOS_ADC_DMA_Handler(); -} - -#include "pios_tim_priv.h" - -static const TIM_TimeBaseInitTypeDef tim_1_2_3_4_time_base = { - .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, - .TIM_ClockDivision = TIM_CKD_DIV1, - .TIM_CounterMode = TIM_CounterMode_Up, - .TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1), - .TIM_RepetitionCounter = 0x0000, -}; - -static const struct pios_tim_clock_cfg tim_1_cfg = { - .timer = TIM1, - .time_base_init = &tim_1_2_3_4_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM1_CC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_2_cfg = { - .timer = TIM2, - .time_base_init = &tim_1_2_3_4_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_3_cfg = { - .timer = TIM3, - .time_base_init = &tim_1_2_3_4_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_4_cfg = { - .timer = TIM4, - .time_base_init = &tim_1_2_3_4_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = { - { - .timer = TIM4, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .remap = GPIO_PartialRemap_TIM3, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_1, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_1, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, -}; - -static const struct pios_tim_channel pios_tim_servoport_all_pins[] = { - { - .timer = TIM4, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM1, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .remap = GPIO_PartialRemap_TIM3, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, -}; - - -static const struct pios_tim_channel pios_tim_servoport_rcvrport_pins[] = { - { - .timer = TIM4, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM1, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .remap = GPIO_PartialRemap_TIM3, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - - // Receiver port pins - // S3-S6 inputs are used as outputs in this case - { - .timer = TIM3, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_1, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM2, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_1, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, -}; -#if defined(PIOS_INCLUDE_USART) - -#include "pios_usart_priv.h" - -static const struct pios_usart_cfg pios_usart_generic_main_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -static const struct pios_usart_cfg pios_usart_generic_flexi_cfg = { - .regs = USART3, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#if defined(PIOS_INCLUDE_DSM) -/* - * Spektrum/JR DSM USART - */ -#include - -static const struct pios_usart_cfg pios_usart_dsm_main_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 115200, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -static const struct pios_dsm_cfg pios_dsm_main_cfg = { - .bind = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, -}; - -static const struct pios_usart_cfg pios_usart_dsm_flexi_cfg = { - .regs = USART3, - .init = { - .USART_BaudRate = 115200, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -static const struct pios_dsm_cfg pios_dsm_flexi_cfg = { - .bind = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, -}; - -#endif /* PIOS_INCLUDE_DSM */ - -#if defined(PIOS_INCLUDE_SBUS) -/* - * S.Bus USART - */ -#include - -static const struct pios_usart_cfg pios_usart_sbus_main_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 100000, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_Even, - .USART_StopBits = USART_StopBits_2, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -static const struct pios_sbus_cfg pios_sbus_cfg = { - /* Inverter configuration */ - .inv = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .gpio_clk_func = RCC_APB2PeriphClockCmd, - .gpio_clk_periph = RCC_APB2Periph_GPIOB, - .gpio_inv_enable = Bit_SET, -}; - -#endif /* PIOS_INCLUDE_SBUS */ - -#endif /* PIOS_INCLUDE_USART */ - -#if defined(PIOS_INCLUDE_COM) - -#include "pios_com_priv.h" +uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; #define PIOS_COM_TELEM_RF_RX_BUF_LEN 32 #define PIOS_COM_TELEM_RF_TX_BUF_LEN 12 @@ -814,243 +60,6 @@ static const struct pios_sbus_cfg pios_sbus_cfg = { #define PIOS_COM_BRIDGE_RX_BUF_LEN 65 #define PIOS_COM_BRIDGE_TX_BUF_LEN 12 -#endif /* PIOS_INCLUDE_COM */ - -#if defined(PIOS_INCLUDE_RTC) -/* - * Realtime Clock (RTC) - */ -#include - -void PIOS_RTC_IRQ_Handler (void); -void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); -static const struct pios_rtc_cfg pios_rtc_main_cfg = { - .clksrc = RCC_RTCCLKSource_HSE_Div128, - .prescaler = 100, - .irq = { - .init = { - .NVIC_IRQChannel = RTC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -void PIOS_RTC_IRQ_Handler (void) -{ - PIOS_RTC_irq_handler (); -} - -#endif - -/* - * Servo outputs - */ -#include - -const struct pios_servo_cfg pios_servo_cfg = { - .tim_oc_init = { - .TIM_OCMode = TIM_OCMode_PWM1, - .TIM_OutputState = TIM_OutputState_Enable, - .TIM_OutputNState = TIM_OutputNState_Disable, - .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, - .TIM_OCPolarity = TIM_OCPolarity_High, - .TIM_OCNPolarity = TIM_OCPolarity_High, - .TIM_OCIdleState = TIM_OCIdleState_Reset, - .TIM_OCNIdleState = TIM_OCNIdleState_Reset, - }, - .channels = pios_tim_servoport_all_pins, - .num_channels = NELEMENTS(pios_tim_servoport_all_pins), -}; - -const struct pios_servo_cfg pios_servo_rcvr_cfg = { - .tim_oc_init = { - .TIM_OCMode = TIM_OCMode_PWM1, - .TIM_OutputState = TIM_OutputState_Enable, - .TIM_OutputNState = TIM_OutputNState_Disable, - .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, - .TIM_OCPolarity = TIM_OCPolarity_High, - .TIM_OCNPolarity = TIM_OCPolarity_High, - .TIM_OCIdleState = TIM_OCIdleState_Reset, - .TIM_OCNIdleState = TIM_OCNIdleState_Reset, - }, - .channels = pios_tim_servoport_rcvrport_pins, - .num_channels = NELEMENTS(pios_tim_servoport_rcvrport_pins), -}; - - -/* - * PPM Inputs - */ -#if defined(PIOS_INCLUDE_PPM) -#include - -const struct pios_ppm_cfg pios_ppm_cfg = { - .tim_ic_init = { - .TIM_ICPolarity = TIM_ICPolarity_Rising, - .TIM_ICSelection = TIM_ICSelection_DirectTI, - .TIM_ICPrescaler = TIM_ICPSC_DIV1, - .TIM_ICFilter = 0x0, - }, - /* Use only the first channel for ppm */ - .channels = &pios_tim_rcvrport_all_channels[0], - .num_channels = 1, -}; - -#endif /* PIOS_INCLUDE_PPM */ - -/* - * PWM Inputs - */ -#if defined(PIOS_INCLUDE_PWM) -#include - -const struct pios_pwm_cfg pios_pwm_cfg = { - .tim_ic_init = { - .TIM_ICPolarity = TIM_ICPolarity_Rising, - .TIM_ICSelection = TIM_ICSelection_DirectTI, - .TIM_ICPrescaler = TIM_ICPSC_DIV1, - .TIM_ICFilter = 0x0, - }, - .channels = pios_tim_rcvrport_all_channels, - .num_channels = NELEMENTS(pios_tim_rcvrport_all_channels), -}; -#endif - -#if defined(PIOS_INCLUDE_I2C) - -#include - -/* - * I2C Adapters - */ - -void PIOS_I2C_flexi_adapter_ev_irq_handler(void); -void PIOS_I2C_flexi_adapter_er_irq_handler(void); -void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_ev_irq_handler"))); -void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_er_irq_handler"))); - -static const struct pios_i2c_adapter_cfg pios_i2c_flexi_adapter_cfg = { - .regs = I2C2, - .init = { - .I2C_Mode = I2C_Mode_I2C, - .I2C_OwnAddress1 = 0, - .I2C_Ack = I2C_Ack_Enable, - .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_DutyCycle = I2C_DutyCycle_2, - .I2C_ClockSpeed = 400000, /* bits/s */ - }, - .transfer_timeout_ms = 50, - .scl = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .sda = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .event = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_EV_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .error = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_ER_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -uint32_t pios_i2c_flexi_adapter_id; -void PIOS_I2C_flexi_adapter_ev_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_flexi_adapter_id); -} - -void PIOS_I2C_flexi_adapter_er_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_flexi_adapter_id); -} - -#endif /* PIOS_INCLUDE_I2C */ - -#if defined(PIOS_INCLUDE_GCSRCVR) -#include "pios_gcsrcvr_priv.h" -#endif /* PIOS_INCLUDE_GCSRCVR */ - -#if defined(PIOS_INCLUDE_RCVR) -#include "pios_rcvr_priv.h" - -/* One slot per selectable receiver group. - * eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS - * NOTE: No slot in this map for NONE. - */ -uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; - -#endif /* PIOS_INCLUDE_RCVR */ - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_cdc_priv.h" -#include "pios_usb_desc_hid_only_priv.h" - -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; -#endif /* PIOS_INCLUDE_USB_HID */ - -#if defined(PIOS_INCLUDE_USB_CDC) -#include - -const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { - .ctrl_if = 1, - .ctrl_tx_ep = 2, - - .data_if = 2, - .data_rx_ep = 3, - .data_tx_ep = 3, -}; -#endif /* PIOS_INCLUDE_USB_CDC */ - uint32_t pios_com_telem_rf_id; uint32_t pios_com_telem_usb_id; uint32_t pios_com_vcp_id; diff --git a/flight/INS/Makefile b/flight/INS/Makefile index 4b39267f7..a58f71b9b 100644 --- a/flight/INS/Makefile +++ b/flight/INS/Makefile @@ -71,6 +71,7 @@ OPUAVOBJINC = $(OPUAVOBJ)/inc OPSYSINC = $(OPDIR)/System/inc BOOT = ../Bootloaders/INS BOOTINC = $(BOOT)/inc +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) OPUAVSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight @@ -172,6 +173,7 @@ EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(INSINC) EXTRAINCDIRS += $(OPUAVSYNTHDIR) EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/INS/pios_board.c b/flight/INS/pios_board.c index f1ef66d8e..d1c215e0e 100644 --- a/flight/INS/pios_board.c +++ b/flight/INS/pios_board.c @@ -29,359 +29,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include - -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_ALARM] = { - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* SPI2 Interface - * - Used for mainboard communications and magnetometer +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE */ -void PIOS_SPI_op_mag_irq_handler(void); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_mag_irq_handler"))); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_mag_irq_handler"))); -static const struct pios_spi_cfg pios_spi_op_mag_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Slave, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Hard, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - }, - .use_crc = TRUE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, +#include "board_hw_defs.c" - .irq = { - .flags = - (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | - DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = - (uint32_t) & (SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = - DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = - DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = - DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = - (uint32_t) & (SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = - DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = - DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = - DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -uint32_t pios_spi_op_mag_id; -void PIOS_SPI_op_mag_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_op_mag_id); -} - -/* SPI1 Interface - * - Used for BMA180 accelerometer - */ -void PIOS_SPI_accel_irq_handler(void); -void DMA1_Channel2_IRQHandler() __attribute__ ((alias("PIOS_SPI_accel_irq_handler"))); -void DMA1_Channel3_IRQHandler() __attribute__ ((alias("PIOS_SPI_accel_irq_handler"))); -static const struct pios_spi_cfg pios_spi_accel_cfg = { - .regs = SPI1, - .init = { - .SPI_Mode = SPI_Mode_Master, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Soft, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_1Edge, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, - }, - .use_crc = FALSE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), - .init = { - .NVIC_IRQChannel = DMA1_Channel2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel2, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel3, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - .sclk = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .miso = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .mosi = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -static uint32_t pios_spi_accel_id; -void PIOS_SPI_accel_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_accel_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - - - -#if defined(PIOS_INCLUDE_GPS) -#include - -/* - * GPS USART - */ -static const struct pios_usart_cfg pios_usart_gps_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = - USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#endif /* PIOS_INCLUDE_GPS */ - -#ifdef PIOS_COM_AUX -/* - * AUX USART - */ -static const struct pios_usart_cfg pios_usart_aux_cfg = { - .regs = USART4, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = - USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#endif /* PIOS_COM_AUX */ - - -#if defined(PIOS_INCLUDE_COM) - -#include +#include #if 0 #define PIOS_COM_AUX_TX_BUF_LEN 192 @@ -391,156 +48,6 @@ static uint8_t pios_com_aux_tx_buffer[PIOS_COM_AUX_TX_BUF_LEN]; #define PIOS_COM_GPS_RX_BUF_LEN 96 static uint8_t pios_com_gps_rx_buffer[PIOS_COM_GPS_RX_BUF_LEN]; - -#endif /* PIOS_INCLUDE_COM */ - -#if defined(PIOS_INCLUDE_I2C) - -#include - -/* - * I2C Adapters - */ - -void PIOS_I2C_pres_mag_adapter_ev_irq_handler(void); -void PIOS_I2C_pres_mag_adapter_er_irq_handler(void); -void I2C1_EV_IRQHandler() - __attribute__ ((alias("PIOS_I2C_pres_mag_adapter_ev_irq_handler"))); -void I2C1_ER_IRQHandler() - __attribute__ ((alias("PIOS_I2C_pres_mag_adapter_er_irq_handler"))); - -static const struct pios_i2c_adapter_cfg pios_i2c_pres_mag_adapter_cfg = { - .regs = I2C1, - .init = { - .I2C_Mode = I2C_Mode_I2C, - .I2C_OwnAddress1 = 0, - .I2C_Ack = I2C_Ack_Enable, - .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_DutyCycle = I2C_DutyCycle_2, - .I2C_ClockSpeed = 200000, /* bits/s */ - }, - .transfer_timeout_ms = 50, - .scl = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .sda = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .event = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C1_EV_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .error = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C1_ER_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -uint32_t pios_i2c_pres_mag_adapter_id; -void PIOS_I2C_pres_mag_adapter_ev_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_pres_mag_adapter_id); -} - -void PIOS_I2C_pres_mag_adapter_er_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_pres_mag_adapter_id); -} - - -void PIOS_I2C_gyro_adapter_ev_irq_handler(void); -void PIOS_I2C_gyro_adapter_er_irq_handler(void); -void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_gyro_adapter_ev_irq_handler"))); -void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_gyro_adapter_er_irq_handler"))); - -static const struct pios_i2c_adapter_cfg pios_i2c_gyro_adapter_cfg = { - .regs = I2C2, - .init = { - .I2C_Mode = I2C_Mode_I2C, - .I2C_OwnAddress1 = 0, - .I2C_Ack = I2C_Ack_Enable, - .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_DutyCycle = I2C_DutyCycle_2, - .I2C_ClockSpeed = 400000, /* bits/s */ - }, - .transfer_timeout_ms = 50, - .scl = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .sda = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .event = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_EV_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .error = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_ER_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -uint32_t pios_i2c_gyro_adapter_id; -void PIOS_I2C_gyro_adapter_ev_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_gyro_adapter_id); -} - -void PIOS_I2C_gyro_adapter_er_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_gyro_adapter_id); -} - -#endif /* PIOS_INCLUDE_I2C */ - - - -extern const struct pios_com_driver pios_usart_com_driver; - uint32_t pios_com_aux_id; uint32_t pios_com_gps_id; diff --git a/flight/OpenPilot/Makefile b/flight/OpenPilot/Makefile index 3de0a0d15..96be8ff31 100644 --- a/flight/OpenPilot/Makefile +++ b/flight/OpenPilot/Makefile @@ -113,6 +113,7 @@ PYMITEINC += $(PYMITEPLAT) PYMITEINC += $(OUTDIR) FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) UAVOBJSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight @@ -317,6 +318,7 @@ EXTRAINCDIRS += $(APPLIBDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 EXTRAINCDIRS += $(AHRSBOOTLOADERINC) EXTRAINCDIRS += $(PYMITEINC) +EXTRAINCDIRS += $(HWDEFSINC) EXTRAINCDIRS += ${foreach MOD, ${OPTMODULES} ${MODULES} ${PYMODULES}, $(OPMODULEDIR)/${MOD}/inc} ${OPMODULEDIR}/System/inc diff --git a/flight/OpenPilot/System/inc/pios_config.h b/flight/OpenPilot/System/inc/pios_config.h index f5227019f..b676ec291 100644 --- a/flight/OpenPilot/System/inc/pios_config.h +++ b/flight/OpenPilot/System/inc/pios_config.h @@ -42,6 +42,7 @@ #define PIOS_INCLUDE_IRQ #define PIOS_INCLUDE_LED #define PIOS_INCLUDE_IAP +#define PIOS_INCLUDE_TIM #define PIOS_INCLUDE_RCVR diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index 16da82cdd..ad9c13083 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -27,6 +27,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. + * + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE + */ +#include "board_hw_defs.c" + #include #include #include @@ -36,605 +46,11 @@ //#define I2C_DEBUG_PIN 0 //#define USART_GPS_DEBUG_PIN 1 -#if defined(PIOS_INCLUDE_LED) - -#include -static const struct pios_led pios_leds[] = { - [PIOS_LED_HEARTBEAT] = { - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, - [PIOS_LED_ALARM] = { - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Mode = GPIO_Mode_Out_PP, - .GPIO_Speed = GPIO_Speed_50MHz, - }, - }, - }, -}; - -static const struct pios_led_cfg pios_led_cfg = { - .leds = pios_leds, - .num_leds = NELEMENTS(pios_leds), -}; - -#endif /* PIOS_INCLUDE_LED */ - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* MicroSD Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). +/* One slot per selectable receiver group. + * eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS + * NOTE: No slot in this map for NONE. */ -void PIOS_SPI_sdcard_irq_handler(void); -void DMA1_Channel2_IRQHandler() __attribute__ ((alias ("PIOS_SPI_sdcard_irq_handler"))); -void DMA1_Channel3_IRQHandler() __attribute__ ((alias ("PIOS_SPI_sdcard_irq_handler"))); -static const struct pios_spi_cfg pios_spi_sdcard_cfg = { - .regs = SPI1, - .init = { - .SPI_Mode = SPI_Mode_Master, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Soft, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256, /* Maximum divider (ie. slowest clock rate) */ - }, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), - .init = { - .NVIC_IRQChannel = DMA1_Channel2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel2, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel3, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - .sclk = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .miso = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .mosi = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -/* AHRS Interface - * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). - */ -void PIOS_SPI_ahrs_irq_handler(void); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); -static const struct pios_spi_cfg pios_spi_ahrs_cfg = { - .regs = SPI2, - .init = { - .SPI_Mode = SPI_Mode_Master, - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, - .SPI_DataSize = SPI_DataSize_8b, - .SPI_NSS = SPI_NSS_Soft, - .SPI_FirstBit = SPI_FirstBit_MSB, - .SPI_CRCPolynomial = 7, - .SPI_CPOL = SPI_CPOL_High, - .SPI_CPHA = SPI_CPHA_2Edge, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16, - }, - .use_crc = TRUE, - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - - .irq = { - .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), - .init = { - .NVIC_IRQChannel = DMA1_Channel4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel4, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel5, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - .ssel = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_12, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - .sclk = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_13, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .miso = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_14, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, - .mosi = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_15, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -static uint32_t pios_spi_sdcard_id; -void PIOS_SPI_sdcard_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_sdcard_id); -} - -uint32_t pios_spi_ahrs_id; -void PIOS_SPI_ahrs_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_ahrs_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - -/* - * ADC system - */ -#include "pios_adc_priv.h" -extern void PIOS_ADC_handler(void); -void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); -// Remap the ADC DMA handler to this one -static const struct pios_adc_cfg pios_adc_cfg = { - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - .irq = { - .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), - .init = { - .NVIC_IRQChannel = DMA1_Channel1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .channel = DMA1_Channel1, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, - .DMA_Mode = DMA_Mode_Circular, - .DMA_Priority = DMA_Priority_Low, - .DMA_M2M = DMA_M2M_Disable, - }, - } - }, - .half_flag = DMA1_IT_HT1, - .full_flag = DMA1_IT_TC1, -}; - -struct pios_adc_dev pios_adc_devs[] = { - { - .cfg = &pios_adc_cfg, - .callback_function = NULL, - }, -}; - -uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); - -void PIOS_ADC_handler() { - PIOS_ADC_DMA_Handler(); -} - -#include "pios_tim_priv.h" - -static const TIM_TimeBaseInitTypeDef tim_4_8_time_base = { - .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, - .TIM_ClockDivision = TIM_CKD_DIV1, - .TIM_CounterMode = TIM_CounterMode_Up, - .TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1), - .TIM_RepetitionCounter = 0x0000, -}; - -static const struct pios_tim_clock_cfg tim_4_cfg = { - .timer = TIM4, - .time_base_init = &tim_4_8_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM4_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_8_cfg = { - .timer = TIM8, - .time_base_init = &tim_4_8_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM8_CC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const TIM_TimeBaseInitTypeDef tim_1_3_5_time_base = { - .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, - .TIM_ClockDivision = TIM_CKD_DIV1, - .TIM_CounterMode = TIM_CounterMode_Up, - .TIM_Period = 0xFFFF, - .TIM_RepetitionCounter = 0x0000, -}; - -static const struct pios_tim_clock_cfg tim_1_cfg = { - .timer = TIM1, - .time_base_init = &tim_1_3_5_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM1_CC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_3_cfg = { - .timer = TIM3, - .time_base_init = &tim_1_3_5_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -static const struct pios_tim_clock_cfg tim_5_cfg = { - .timer = TIM5, - .time_base_init = &tim_1_3_5_time_base, - .irq = { - .init = { - .NVIC_IRQChannel = TIM5_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#if defined(PIOS_INCLUDE_USART) - -#include "pios_usart_priv.h" - -/* - * Telemetry USART - */ -static const struct pios_usart_cfg pios_usart_telem_cfg = { - .regs = USART2, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_3, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_2, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -/* - * GPS USART - */ -static const struct pios_usart_cfg pios_usart_gps_cfg = { - .regs = USART3, - .remap = GPIO_PartialRemap_USART3, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART3_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#ifdef PIOS_COM_AUX -/* - * AUX USART - */ -static const struct pios_usart_cfg pios_usart_aux_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .remap = GPIO_Remap_USART1, - .rx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; -#endif - -#if defined(PIOS_INCLUDE_RTC) -/* - * Realtime Clock (RTC) - */ -#include - -void PIOS_RTC_IRQ_Handler (void); -void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); -static const struct pios_rtc_cfg pios_rtc_main_cfg = { - .clksrc = RCC_RTCCLKSource_HSE_Div128, - .prescaler = 100, - .irq = { - .init = { - .NVIC_IRQChannel = RTC_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -void PIOS_RTC_IRQ_Handler (void) -{ - PIOS_RTC_irq_handler (); -} - -#endif - -#if defined(PIOS_INCLUDE_DSM) -/* - * Spektrum/JR DSM USART - */ -#include - -static const struct pios_usart_cfg pios_usart_dsm_cfg = { - .regs = USART1, - .init = { - .USART_BaudRate = 115200, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx, - }, - .irq = { - .init = { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, - }, - }, -}; - -static const struct pios_dsm_cfg pios_dsm_cfg = { - .bind = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, -}; - -#endif /* PIOS_COM_DSM */ - -#if defined(PIOS_INCLUDE_SBUS) -#error PIOS_INCLUDE_SBUS not implemented -#endif /* PIOS_INCLUDE_SBUS */ - -#endif /* PIOS_INCLUDE_USART */ - -#if defined(PIOS_INCLUDE_COM) - -#include "pios_com_priv.h" +uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; #define PIOS_COM_TELEM_RF_RX_BUF_LEN 192 #define PIOS_COM_TELEM_RF_TX_BUF_LEN 192 @@ -647,479 +63,6 @@ static const struct pios_dsm_cfg pios_dsm_cfg = { #define PIOS_COM_BRIDGE_RX_BUF_LEN 65 #define PIOS_COM_BRIDGE_TX_BUF_LEN 12 -#endif /* PIOS_INCLUDE_COM */ - -/** - * Pios servo configuration structures - */ -#include -static const struct pios_tim_channel pios_tim_servoport_all_pins[] = { - { - .timer = TIM4, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM4, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM8, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM8, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM8, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM8, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Mode = GPIO_Mode_AF_PP, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, -}; - -const struct pios_servo_cfg pios_servo_cfg = { - .tim_oc_init = { - .TIM_OCMode = TIM_OCMode_PWM1, - .TIM_OutputState = TIM_OutputState_Enable, - .TIM_OutputNState = TIM_OutputNState_Disable, - .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, - .TIM_OCPolarity = TIM_OCPolarity_High, - .TIM_OCNPolarity = TIM_OCPolarity_High, - .TIM_OCIdleState = TIM_OCIdleState_Reset, - .TIM_OCNIdleState = TIM_OCNIdleState_Reset, - }, - .channels = pios_tim_servoport_all_pins, - .num_channels = NELEMENTS(pios_tim_servoport_all_pins), -}; - - -/* - * PWM Inputs - */ -#if defined(PIOS_INCLUDE_PWM) || defined(PIOS_INCLUDE_PPM) -#include -static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = { - { - .timer = TIM1, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM1, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM5, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM1, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOA, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_4, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_1, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_3, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_0, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_1, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .remap = GPIO_PartialRemap_TIM3, - }, - { - .timer = TIM3, - .timer_chan = TIM_Channel_2, - .pin = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Mode = GPIO_Mode_IPD, - .GPIO_Speed = GPIO_Speed_2MHz, - }, - }, - .remap = GPIO_PartialRemap_TIM3, - }, -}; - -const struct pios_pwm_cfg pios_pwm_cfg = { - .tim_ic_init = { - .TIM_ICPolarity = TIM_ICPolarity_Rising, - .TIM_ICSelection = TIM_ICSelection_DirectTI, - .TIM_ICPrescaler = TIM_ICPSC_DIV1, - .TIM_ICFilter = 0x0, - }, - .channels = pios_tim_rcvrport_all_channels, - .num_channels = NELEMENTS(pios_tim_rcvrport_all_channels), -}; -#endif - -/* - * PPM Input - */ -#if defined(PIOS_INCLUDE_PPM) -#include -static const struct pios_ppm_cfg pios_ppm_cfg = { - .tim_ic_init = { - .TIM_ICPolarity = TIM_ICPolarity_Rising, - .TIM_ICSelection = TIM_ICSelection_DirectTI, - .TIM_ICPrescaler = TIM_ICPSC_DIV1, - .TIM_ICFilter = 0x0, - .TIM_Channel = TIM_Channel_2, - }, - /* Use only the first channel for ppm */ - .channels = &pios_tim_rcvrport_all_channels[0], - .num_channels = 1, -}; - -#endif //PPM - -#if defined(PIOS_INCLUDE_I2C) - -#include - -/* - * I2C Adapters - */ - -void PIOS_I2C_main_adapter_ev_irq_handler(void); -void PIOS_I2C_main_adapter_er_irq_handler(void); -void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_ev_irq_handler"))); -void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_er_irq_handler"))); - -static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { - .regs = I2C2, - .init = { - .I2C_Mode = I2C_Mode_I2C, - .I2C_OwnAddress1 = 0, - .I2C_Ack = I2C_Ack_Enable, - .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, - .I2C_DutyCycle = I2C_DutyCycle_2, - .I2C_ClockSpeed = 400000, /* bits/s */ - }, - .transfer_timeout_ms = 50, - .scl = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .sda = { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_11, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_OD, - }, - }, - .event = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_EV_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .error = { - .flags = 0, /* FIXME: check this */ - .init = { - .NVIC_IRQChannel = I2C2_ER_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -uint32_t pios_i2c_main_adapter_id; -void PIOS_I2C_main_adapter_ev_irq_handler(void) -{ -#ifdef I2C_DEBUG_PIN - PIOS_DEBUG_PinHigh(I2C_DEBUG_PIN); -#endif - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id); -#ifdef I2C_DEBUG_PIN - PIOS_DEBUG_PinLow(I2C_DEBUG_PIN); -#endif -} - -void PIOS_I2C_main_adapter_er_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id); -} - -#endif /* PIOS_INCLUDE_I2C */ - -#if defined(PIOS_ENABLE_DEBUG_PINS) - -static const struct stm32_gpio pios_debug_pins[] = { - #define PIOS_DEBUG_PIN_SERVO_1 0 - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_2 1 - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_3 2 - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_4 3 - { - .gpio = GPIOB, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_5 4 - { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_6 5 - { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_7 6 - { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_8, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - #define PIOS_DEBUG_PIN_SERVO_8 7 - { - .gpio = GPIOC, - .init = { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_50MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, -}; - -#endif /* PIOS_ENABLE_DEBUG_PINS */ - -#if defined(PIOS_INCLUDE_RCVR) -#include "pios_rcvr_priv.h" - -/* One slot per selectable receiver group. - * eg. PWM, PPM, GCS, DSMMAINPORT, DSMFLEXIPORT, SBUS - * NOTE: No slot in this map for NONE. - */ -uint32_t pios_rcvr_group_map[MANUALCONTROLSETTINGS_CHANNELGROUPS_NONE]; - -#endif /* PIOS_INCLUDE_RCVR */ - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_cdc_priv.h" -#include "pios_usb_desc_hid_only_priv.h" -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; - -#endif /* PIOS_INCLUDE_USB_HID */ - -#if defined(PIOS_INCLUDE_USB_CDC) -#include - -const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { - .ctrl_if = 1, - .ctrl_tx_ep = 2, - - .data_if = 2, - .data_rx_ep = 3, - .data_tx_ep = 3, -}; -#endif /* PIOS_INCLUDE_USB_CDC */ - uint32_t pios_com_telem_rf_id; uint32_t pios_com_telem_usb_id; uint32_t pios_com_vcp_id; diff --git a/flight/PipXtreme/Makefile b/flight/PipXtreme/Makefile index c4bc900ca..a21fdb74a 100644 --- a/flight/PipXtreme/Makefile +++ b/flight/PipXtreme/Makefile @@ -75,7 +75,7 @@ endif CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3 BOOT = ../Bootloaders/AHRS BOOTINC = $(BOOT)/inc - +HWDEFSINC = ../board_hw_defs/$(BOARD_NAME) # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files @@ -200,6 +200,7 @@ ifeq ($(USE_USB), YES) endif EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(BOOTINC) +EXTRAINCDIRS += $(HWDEFSINC) # List any extra directories to look for library files here. # Also add directories where the linker should search for diff --git a/flight/PipXtreme/pios_board.c b/flight/PipXtreme/pios_board.c index ab6bcffef..a5536db2b 100644 --- a/flight/PipXtreme/pios_board.c +++ b/flight/PipXtreme/pios_board.c @@ -23,277 +23,16 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include - -// *********************************************************************************** -// SPI - -#if defined(PIOS_INCLUDE_SPI) - -#include - -/* OP Interface +/* Pull in the board-specific static HW definitions. + * Including .c files is a bit ugly but this allows all of + * the HW definitions to be const and static to limit their + * scope. * - * NOTE: Leave this declared as const data so that it ends up in the - * .rodata section (ie. Flash) rather than in the .bss section (RAM). + * NOTE: THIS IS THE ONLY PLACE THAT SHOULD EVER INCLUDE THIS FILE */ -void PIOS_SPI_port_irq_handler(void); -void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_port_irq_handler"))); -void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_port_irq_handler"))); +#include "board_hw_defs.c" -static const struct pios_spi_cfg pios_spi_port_cfg = -{ - .regs = SPI1, -// .regs = SPI2, -// .regs = SPI3, - - .init = - { - .SPI_Mode = SPI_Mode_Master, -// .SPI_Mode = SPI_Mode_Slave, - - .SPI_Direction = SPI_Direction_2Lines_FullDuplex, -// .SPI_Direction = SPI_Direction_2Lines_RxOnly, -// .SPI_Direction = SPI_Direction_1Line_Rx, -// .SPI_Direction = SPI_Direction_1Line_Tx, - -// .SPI_DataSize = SPI_DataSize_16b, - .SPI_DataSize = SPI_DataSize_8b, - - .SPI_NSS = SPI_NSS_Soft, -// .SPI_NSS = SPI_NSS_Hard, - - .SPI_FirstBit = SPI_FirstBit_MSB, -// .SPI_FirstBit = SPI_FirstBit_LSB, - - .SPI_CRCPolynomial = 0, - - .SPI_CPOL = SPI_CPOL_Low, -// .SPI_CPOL = SPI_CPOL_High, - - .SPI_CPHA = SPI_CPHA_1Edge, -// .SPI_CPHA = SPI_CPHA_2Edge, - -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, // fastest SCLK -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4, -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8, -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16, -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32, -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64, -// .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128, - .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256, // slowest SCLK - }, - .use_crc = FALSE, - - .dma = - { - .ahb_clk = RCC_AHBPeriph_DMA1, - .irq = - { - .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), - .init = { - .NVIC_IRQChannel = DMA1_Channel2_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - - .rx = { - .channel = DMA1_Channel2, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - .tx = { - .channel = DMA1_Channel3, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), - .DMA_DIR = DMA_DIR_PeripheralDST, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, - .DMA_Mode = DMA_Mode_Normal, - .DMA_Priority = DMA_Priority_Medium, - .DMA_M2M = DMA_M2M_Disable, - }, - }, - }, - - .ssel = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_4, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_Out_PP, - }, - }, - .sclk = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_5, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, - .miso = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_6, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_IN_FLOATING, -// .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .mosi = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_7, - .GPIO_Speed = GPIO_Speed_10MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -uint32_t pios_spi_port_id; -void PIOS_SPI_port_irq_handler(void) -{ - /* Call into the generic code to handle the IRQ for this specific device */ - PIOS_SPI_IRQ_Handler(pios_spi_port_id); -} - -#endif /* PIOS_INCLUDE_SPI */ - -/* - * ADC system - */ -#include "pios_adc_priv.h" -extern void PIOS_ADC_handler(void); -void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); -// Remap the ADC DMA handler to this one -static const struct pios_adc_cfg pios_adc_cfg = { - .dma = { - .ahb_clk = RCC_AHBPeriph_DMA1, - .irq = { - .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), - .init = { - .NVIC_IRQChannel = DMA1_Channel1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = { - .channel = DMA1_Channel1, - .init = { - .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, - .DMA_DIR = DMA_DIR_PeripheralSRC, - .DMA_PeripheralInc = DMA_PeripheralInc_Disable, - .DMA_MemoryInc = DMA_MemoryInc_Enable, - .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, - .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, - .DMA_Mode = DMA_Mode_Circular, - .DMA_Priority = DMA_Priority_High, - .DMA_M2M = DMA_M2M_Disable, - }, - } - }, - .half_flag = DMA1_IT_HT1, - .full_flag = DMA1_IT_TC1, -}; - -struct pios_adc_dev pios_adc_devs[] = { - { - .cfg = &pios_adc_cfg, - .callback_function = NULL, - }, -}; - -uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); - -void PIOS_ADC_handler() { - PIOS_ADC_DMA_Handler(); -} - - -// *********************************************************************************** -// USART - -#if defined(PIOS_INCLUDE_USART) - -#include - -/* - * SERIAL USART - */ -static const struct pios_usart_cfg pios_usart_serial_cfg = -{ - .regs = USART1, - .init = - { - .USART_BaudRate = 57600, - .USART_WordLength = USART_WordLength_8b, - .USART_Parity = USART_Parity_No, - .USART_StopBits = USART_StopBits_1, - .USART_HardwareFlowControl = USART_HardwareFlowControl_None, - .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, - }, - .irq = - { - .init = - { - .NVIC_IRQChannel = USART1_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, - .rx = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_10, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_IPU, - }, - }, - .tx = - { - .gpio = GPIOA, - .init = - { - .GPIO_Pin = GPIO_Pin_9, - .GPIO_Speed = GPIO_Speed_2MHz, - .GPIO_Mode = GPIO_Mode_AF_PP, - }, - }, -}; - -#endif /* PIOS_INCLUDE_USART */ - -// *********************************************************************************** - -#if defined(PIOS_INCLUDE_COM) - -#include +#include #define PIOS_COM_TELEM_USB_RX_BUF_LEN 192 #define PIOS_COM_TELEM_USB_TX_BUF_LEN 192 @@ -307,40 +46,6 @@ static uint8_t pios_com_telem_usb_tx_buffer[PIOS_COM_TELEM_USB_TX_BUF_LEN]; static uint8_t pios_com_serial_rx_buffer[PIOS_COM_SERIAL_RX_BUF_LEN]; static uint8_t pios_com_serial_tx_buffer[PIOS_COM_SERIAL_TX_BUF_LEN]; -#endif /* PIOS_INCLUDE_COM */ - -// *********************************************************************************** - -#if defined(PIOS_INCLUDE_USB) -#include "pios_usb_priv.h" - -static const struct pios_usb_cfg pios_usb_main_cfg = { - .irq = { - .init = { - .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, - .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, - .NVIC_IRQChannelSubPriority = 0, - .NVIC_IRQChannelCmd = ENABLE, - }, - }, -}; - -#include "pios_usb_board_data_priv.h" -#include "pios_usb_desc_hid_only_priv.h" - -#endif /* PIOS_INCLUDE_USB */ - -#if defined(PIOS_INCLUDE_USB_HID) -#include - -const struct pios_usb_hid_cfg pios_usb_hid_cfg = { - .data_if = 0, - .data_rx_ep = 1, - .data_tx_ep = 1, -}; - -#endif /* PIOS_INCLUDE_USB_HID */ - uint32_t pios_com_serial_id; uint32_t pios_com_telem_usb_id; diff --git a/flight/board_hw_defs/ahrs/board_hw_defs.c b/flight/board_hw_defs/ahrs/board_hw_defs.c new file mode 100644 index 000000000..d774ce799 --- /dev/null +++ b/flight/board_hw_defs/ahrs/board_hw_defs.c @@ -0,0 +1,351 @@ +#include + +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + +#if defined(PIOS_INCLUDE_SPI) + +#include + +/* OP Interface + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_op_irq_handler(void); +void DMA1_Channel5_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_irq_handler"))); +void DMA1_Channel4_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_irq_handler"))); +static const struct pios_spi_cfg pios_spi_op_cfg = { + .regs = SPI2, + .init = { + .SPI_Mode = SPI_Mode_Slave, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Hard, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_2Edge, + }, + .use_crc = TRUE, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = + (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | + DMA1_FLAG_GL4), + .init = { + .NVIC_IRQChannel = DMA1_Channel4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel4, + .init = { + .DMA_PeripheralBaseAddr = + (uint32_t) & (SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = + DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = + DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = + DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel5, + .init = { + .DMA_PeripheralBaseAddr = + (uint32_t) & (SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = + DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = + DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = + DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .sclk = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .miso = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_14, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .mosi = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_15, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +uint32_t pios_spi_op_id; +void PIOS_SPI_op_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_op_id); +} + +#endif /* PIOS_INCLUDE_SPI */ + +#if defined(PIOS_INCLUDE_ADC) + +/* + * ADC system + */ +#include "pios_adc_priv.h" +extern void PIOS_ADC_handler(void); +void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); +// Remap the ADC DMA handler to this one +static const struct pios_adc_cfg pios_adc_cfg = { + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + .irq = { + .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), + .init = { + .NVIC_IRQChannel = DMA1_Channel1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .channel = DMA1_Channel1, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, + .DMA_Mode = DMA_Mode_Circular, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + } + }, + .half_flag = DMA1_IT_HT1, + .full_flag = DMA1_IT_TC1, +}; + +struct pios_adc_dev pios_adc_devs[] = { + { + .cfg = &pios_adc_cfg, + .callback_function = NULL, + }, +}; + +uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); + +void PIOS_ADC_handler() { + PIOS_ADC_DMA_Handler(); +} + +#endif /* PIOS_INCLUDE_ADC */ + +#if defined(PIOS_INCLUDE_USART) + +#include + +/* + * AUX USART + */ +static const struct pios_usart_cfg pios_usart_aux_cfg = { + .regs = USART3, + .init = { + .USART_BaudRate = 230400, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = + USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#endif /* PIOS_INCLUDE_USART */ + +#if defined(PIOS_INCLUDE_COM) + +#include + +#endif /* PIOS_INCLUDE_COM */ + +#if defined(PIOS_INCLUDE_I2C) + +#include + +/* + * I2C Adapters + */ + +void PIOS_I2C_main_adapter_ev_irq_handler(void); +void PIOS_I2C_main_adapter_er_irq_handler(void); +void I2C1_EV_IRQHandler() + __attribute__ ((alias("PIOS_I2C_main_adapter_ev_irq_handler"))); +void I2C1_ER_IRQHandler() + __attribute__ ((alias("PIOS_I2C_main_adapter_er_irq_handler"))); + +static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { + .regs = I2C1, + .init = { + .I2C_Mode = I2C_Mode_I2C, + .I2C_OwnAddress1 = 0, + .I2C_Ack = I2C_Ack_Enable, + .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, + .I2C_DutyCycle = I2C_DutyCycle_2, + .I2C_ClockSpeed = 200000, /* bits/s */ + }, + .transfer_timeout_ms = 50, + .scl = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .sda = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .event = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C1_EV_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .error = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C1_ER_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +uint32_t pios_i2c_main_adapter_id; +void PIOS_I2C_main_adapter_ev_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id); +} + +void PIOS_I2C_main_adapter_er_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id); +} + +#endif /* PIOS_INCLUDE_I2C */ + +#if defined(PIOS_ENABLE_DEBUG_PINS) + +static const struct stm32_gpio pios_debug_pins[] = { + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, +}; + +#endif /* PIOS_ENABLE_DEBUG_PINS */ diff --git a/flight/board_hw_defs/coptercontrol/board_hw_defs.c b/flight/board_hw_defs/coptercontrol/board_hw_defs.c new file mode 100644 index 000000000..b5f81027f --- /dev/null +++ b/flight/board_hw_defs/coptercontrol/board_hw_defs.c @@ -0,0 +1,1018 @@ +#include + +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + +#if defined(PIOS_INCLUDE_SPI) + +#include + +/* Flash/Accel Interface + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_flash_accel_irq_handler(void); +void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_flash_accel_irq_handler"))); +void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_flash_accel_irq_handler"))); +static const struct pios_spi_cfg pios_spi_flash_accel_cfg = { + .regs = SPI2, + .init = { + .SPI_Mode = SPI_Mode_Master, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Soft, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_2Edge, + .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, + }, + .use_crc = FALSE, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), + .init = { + .NVIC_IRQChannel = DMA1_Channel4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel4, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel5, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + .sclk = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .miso = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_14, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .mosi = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_15, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +static uint32_t pios_spi_flash_accel_id; +void PIOS_SPI_flash_accel_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_flash_accel_id); +} + +#endif /* PIOS_INCLUDE_SPI */ + +#if defined(PIOS_INCLUDE_ADC) +/* + * ADC system + */ +#include "pios_adc_priv.h" +extern void PIOS_ADC_handler(void); +void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); +// Remap the ADC DMA handler to this one +static const struct pios_adc_cfg pios_adc_cfg = { + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + .irq = { + .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), + .init = { + .NVIC_IRQChannel = DMA1_Channel1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .channel = DMA1_Channel1, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, + .DMA_Mode = DMA_Mode_Circular, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + } + }, + .half_flag = DMA1_IT_HT1, + .full_flag = DMA1_IT_TC1, +}; + +struct pios_adc_dev pios_adc_devs[] = { + { + .cfg = &pios_adc_cfg, + .callback_function = NULL, + }, +}; + +uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); + +void PIOS_ADC_handler() { + PIOS_ADC_DMA_Handler(); +} + +#endif /* PIOS_INCLUDE_ADC */ + +#if defined(PIOS_INCLUDE_TIM) + +#include "pios_tim_priv.h" + +static const TIM_TimeBaseInitTypeDef tim_1_2_3_4_time_base = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1), + .TIM_RepetitionCounter = 0x0000, +}; + +static const struct pios_tim_clock_cfg tim_1_cfg = { + .timer = TIM1, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM1_CC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_2_cfg = { + .timer = TIM2, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_3_cfg = { + .timer = TIM3, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_4_cfg = { + .timer = TIM4, + .time_base_init = &tim_1_2_3_4_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = { + { + .timer = TIM4, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap_TIM3, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, +}; + +static const struct pios_tim_channel pios_tim_servoport_all_pins[] = { + { + .timer = TIM4, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM1, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap_TIM3, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, +}; + + +static const struct pios_tim_channel pios_tim_servoport_rcvrport_pins[] = { + { + .timer = TIM4, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM1, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap_TIM3, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + + // Receiver port pins + // S3-S6 inputs are used as outputs in this case + { + .timer = TIM3, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM2, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, +}; + +#endif /* PIOS_INCLUDE_TIM */ + +#if defined(PIOS_INCLUDE_USART) + +#include "pios_usart_priv.h" + +static const struct pios_usart_cfg pios_usart_generic_main_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +static const struct pios_usart_cfg pios_usart_generic_flexi_cfg = { + .regs = USART3, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#if defined(PIOS_INCLUDE_DSM) +/* + * Spektrum/JR DSM USART + */ +#include + +static const struct pios_usart_cfg pios_usart_dsm_main_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +static const struct pios_dsm_cfg pios_dsm_main_cfg = { + .bind = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, +}; + +static const struct pios_usart_cfg pios_usart_dsm_flexi_cfg = { + .regs = USART3, + .init = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +static const struct pios_dsm_cfg pios_dsm_flexi_cfg = { + .bind = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, +}; + +#endif /* PIOS_INCLUDE_DSM */ + +#if defined(PIOS_INCLUDE_SBUS) +/* + * S.Bus USART + */ +#include + +static const struct pios_usart_cfg pios_usart_sbus_main_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 100000, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_Even, + .USART_StopBits = USART_StopBits_2, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +static const struct pios_sbus_cfg pios_sbus_cfg = { + /* Inverter configuration */ + .inv = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .gpio_clk_func = RCC_APB2PeriphClockCmd, + .gpio_clk_periph = RCC_APB2Periph_GPIOB, + .gpio_inv_enable = Bit_SET, +}; + +#endif /* PIOS_INCLUDE_SBUS */ + +#endif /* PIOS_INCLUDE_USART */ + +#if defined(PIOS_INCLUDE_COM) + +#include "pios_com_priv.h" + +#endif /* PIOS_INCLUDE_COM */ + +#if defined(PIOS_INCLUDE_RTC) +/* + * Realtime Clock (RTC) + */ +#include + +void PIOS_RTC_IRQ_Handler (void); +void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); +static const struct pios_rtc_cfg pios_rtc_main_cfg = { + .clksrc = RCC_RTCCLKSource_HSE_Div128, + .prescaler = 100, + .irq = { + .init = { + .NVIC_IRQChannel = RTC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_RTC_IRQ_Handler (void) +{ + PIOS_RTC_irq_handler (); +} + +#endif + +#if defined(PIOS_INCLUDE_SERVO) && defined(PIOS_INCLUDE_TIM) +/* + * Servo outputs + */ +#include + +const struct pios_servo_cfg pios_servo_cfg = { + .tim_oc_init = { + .TIM_OCMode = TIM_OCMode_PWM1, + .TIM_OutputState = TIM_OutputState_Enable, + .TIM_OutputNState = TIM_OutputNState_Disable, + .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, + .TIM_OCPolarity = TIM_OCPolarity_High, + .TIM_OCNPolarity = TIM_OCPolarity_High, + .TIM_OCIdleState = TIM_OCIdleState_Reset, + .TIM_OCNIdleState = TIM_OCNIdleState_Reset, + }, + .channels = pios_tim_servoport_all_pins, + .num_channels = NELEMENTS(pios_tim_servoport_all_pins), +}; + +const struct pios_servo_cfg pios_servo_rcvr_cfg = { + .tim_oc_init = { + .TIM_OCMode = TIM_OCMode_PWM1, + .TIM_OutputState = TIM_OutputState_Enable, + .TIM_OutputNState = TIM_OutputNState_Disable, + .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, + .TIM_OCPolarity = TIM_OCPolarity_High, + .TIM_OCNPolarity = TIM_OCPolarity_High, + .TIM_OCIdleState = TIM_OCIdleState_Reset, + .TIM_OCNIdleState = TIM_OCNIdleState_Reset, + }, + .channels = pios_tim_servoport_rcvrport_pins, + .num_channels = NELEMENTS(pios_tim_servoport_rcvrport_pins), +}; + +#endif /* PIOS_INCLUDE_SERVO && PIOS_INCLUDE_TIM */ + +/* + * PPM Inputs + */ +#if defined(PIOS_INCLUDE_PPM) +#include + +const struct pios_ppm_cfg pios_ppm_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + }, + /* Use only the first channel for ppm */ + .channels = &pios_tim_rcvrport_all_channels[0], + .num_channels = 1, +}; + +#endif /* PIOS_INCLUDE_PPM */ + +/* + * PWM Inputs + */ +#if defined(PIOS_INCLUDE_PWM) +#include + +const struct pios_pwm_cfg pios_pwm_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + }, + .channels = pios_tim_rcvrport_all_channels, + .num_channels = NELEMENTS(pios_tim_rcvrport_all_channels), +}; +#endif + +#if defined(PIOS_INCLUDE_I2C) + +#include + +/* + * I2C Adapters + */ + +void PIOS_I2C_flexi_adapter_ev_irq_handler(void); +void PIOS_I2C_flexi_adapter_er_irq_handler(void); +void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_ev_irq_handler"))); +void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_flexi_adapter_er_irq_handler"))); + +static const struct pios_i2c_adapter_cfg pios_i2c_flexi_adapter_cfg = { + .regs = I2C2, + .init = { + .I2C_Mode = I2C_Mode_I2C, + .I2C_OwnAddress1 = 0, + .I2C_Ack = I2C_Ack_Enable, + .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, + .I2C_DutyCycle = I2C_DutyCycle_2, + .I2C_ClockSpeed = 400000, /* bits/s */ + }, + .transfer_timeout_ms = 50, + .scl = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .sda = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .event = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_EV_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .error = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_ER_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +uint32_t pios_i2c_flexi_adapter_id; +void PIOS_I2C_flexi_adapter_ev_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_EV_IRQ_Handler(pios_i2c_flexi_adapter_id); +} + +void PIOS_I2C_flexi_adapter_er_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_ER_IRQ_Handler(pios_i2c_flexi_adapter_id); +} + +#endif /* PIOS_INCLUDE_I2C */ + +#if defined(PIOS_INCLUDE_GCSRCVR) +#include "pios_gcsrcvr_priv.h" +#endif /* PIOS_INCLUDE_GCSRCVR */ + +#if defined(PIOS_INCLUDE_RCVR) +#include "pios_rcvr_priv.h" + +#endif /* PIOS_INCLUDE_RCVR */ + +#if defined(PIOS_INCLUDE_USB) +#include "pios_usb_priv.h" + +static const struct pios_usb_cfg pios_usb_main_cfg = { + .irq = { + .init = { + .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_cdc_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + +#endif /* PIOS_INCLUDE_USB */ + +#if defined(PIOS_INCLUDE_COM_MSG) + +#include + +#endif /* PIOS_INCLUDE_COM_MSG */ + +#if defined(PIOS_INCLUDE_USB_HID) +#include + +const struct pios_usb_hid_cfg pios_usb_hid_cfg = { + .data_if = 0, + .data_rx_ep = 1, + .data_tx_ep = 1, +}; +#endif /* PIOS_INCLUDE_USB_HID */ + +#if defined(PIOS_INCLUDE_USB_CDC) +#include + +const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { + .ctrl_if = 1, + .ctrl_tx_ep = 2, + + .data_if = 2, + .data_rx_ep = 3, + .data_tx_ep = 3, +}; +#endif /* PIOS_INCLUDE_USB_CDC */ + diff --git a/flight/board_hw_defs/ins/board_hw_defs.c b/flight/board_hw_defs/ins/board_hw_defs.c new file mode 100644 index 000000000..b1b5a166c --- /dev/null +++ b/flight/board_hw_defs/ins/board_hw_defs.c @@ -0,0 +1,496 @@ +#include + +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_ALARM] = { + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + +#if defined(PIOS_INCLUDE_SPI) + +#include + +/* SPI2 Interface + * - Used for mainboard communications and magnetometer + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_op_mag_irq_handler(void); +void DMA1_Channel5_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_mag_irq_handler"))); +void DMA1_Channel4_IRQHandler() __attribute__ ((alias("PIOS_SPI_op_mag_irq_handler"))); +static const struct pios_spi_cfg pios_spi_op_mag_cfg = { + .regs = SPI2, + .init = { + .SPI_Mode = SPI_Mode_Slave, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Hard, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_2Edge, + }, + .use_crc = TRUE, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = + (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | + DMA1_FLAG_GL4), + .init = { + .NVIC_IRQChannel = DMA1_Channel4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel4, + .init = { + .DMA_PeripheralBaseAddr = + (uint32_t) & (SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = + DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = + DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = + DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel5, + .init = { + .DMA_PeripheralBaseAddr = + (uint32_t) & (SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = + DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = + DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = + DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .sclk = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .miso = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_14, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .mosi = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_15, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +uint32_t pios_spi_op_mag_id; +void PIOS_SPI_op_mag_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_op_mag_id); +} + +/* SPI1 Interface + * - Used for BMA180 accelerometer + */ +void PIOS_SPI_accel_irq_handler(void); +void DMA1_Channel2_IRQHandler() __attribute__ ((alias("PIOS_SPI_accel_irq_handler"))); +void DMA1_Channel3_IRQHandler() __attribute__ ((alias("PIOS_SPI_accel_irq_handler"))); +static const struct pios_spi_cfg pios_spi_accel_cfg = { + .regs = SPI1, + .init = { + .SPI_Mode = SPI_Mode_Master, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Soft, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_1Edge, + .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, + }, + .use_crc = FALSE, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), + .init = { + .NVIC_IRQChannel = DMA1_Channel2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel2, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel3, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + .sclk = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .miso = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .mosi = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +static uint32_t pios_spi_accel_id; +void PIOS_SPI_accel_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_accel_id); +} + +#endif /* PIOS_INCLUDE_SPI */ + +#if defined(PIOS_INCLUDE_GPS) +#include + +/* + * GPS USART + */ +static const struct pios_usart_cfg pios_usart_gps_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = + USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#endif /* PIOS_INCLUDE_GPS */ + +#ifdef PIOS_COM_AUX +/* + * AUX USART + */ +static const struct pios_usart_cfg pios_usart_aux_cfg = { + .regs = USART4, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = + USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#endif /* PIOS_COM_AUX */ + + +#if defined(PIOS_INCLUDE_COM) + +#include + +#endif /* PIOS_INCLUDE_COM */ + +#if defined(PIOS_INCLUDE_I2C) + +#include + +/* + * I2C Adapters + */ + +void PIOS_I2C_pres_mag_adapter_ev_irq_handler(void); +void PIOS_I2C_pres_mag_adapter_er_irq_handler(void); +void I2C1_EV_IRQHandler() + __attribute__ ((alias("PIOS_I2C_pres_mag_adapter_ev_irq_handler"))); +void I2C1_ER_IRQHandler() + __attribute__ ((alias("PIOS_I2C_pres_mag_adapter_er_irq_handler"))); + +static const struct pios_i2c_adapter_cfg pios_i2c_pres_mag_adapter_cfg = { + .regs = I2C1, + .init = { + .I2C_Mode = I2C_Mode_I2C, + .I2C_OwnAddress1 = 0, + .I2C_Ack = I2C_Ack_Enable, + .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, + .I2C_DutyCycle = I2C_DutyCycle_2, + .I2C_ClockSpeed = 200000, /* bits/s */ + }, + .transfer_timeout_ms = 50, + .scl = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .sda = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .event = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C1_EV_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .error = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C1_ER_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +uint32_t pios_i2c_pres_mag_adapter_id; +void PIOS_I2C_pres_mag_adapter_ev_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_EV_IRQ_Handler(pios_i2c_pres_mag_adapter_id); +} + +void PIOS_I2C_pres_mag_adapter_er_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_ER_IRQ_Handler(pios_i2c_pres_mag_adapter_id); +} + + +void PIOS_I2C_gyro_adapter_ev_irq_handler(void); +void PIOS_I2C_gyro_adapter_er_irq_handler(void); +void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_gyro_adapter_ev_irq_handler"))); +void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_gyro_adapter_er_irq_handler"))); + +static const struct pios_i2c_adapter_cfg pios_i2c_gyro_adapter_cfg = { + .regs = I2C2, + .init = { + .I2C_Mode = I2C_Mode_I2C, + .I2C_OwnAddress1 = 0, + .I2C_Ack = I2C_Ack_Enable, + .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, + .I2C_DutyCycle = I2C_DutyCycle_2, + .I2C_ClockSpeed = 400000, /* bits/s */ + }, + .transfer_timeout_ms = 50, + .scl = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .sda = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .event = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_EV_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .error = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_ER_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +uint32_t pios_i2c_gyro_adapter_id; +void PIOS_I2C_gyro_adapter_ev_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_EV_IRQ_Handler(pios_i2c_gyro_adapter_id); +} + +void PIOS_I2C_gyro_adapter_er_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_ER_IRQ_Handler(pios_i2c_gyro_adapter_id); +} + +#endif /* PIOS_INCLUDE_I2C */ diff --git a/flight/board_hw_defs/openpilot/board_hw_defs.c b/flight/board_hw_defs/openpilot/board_hw_defs.c new file mode 100644 index 000000000..681089d09 --- /dev/null +++ b/flight/board_hw_defs/openpilot/board_hw_defs.c @@ -0,0 +1,1085 @@ +#include + +#if defined(PIOS_INCLUDE_LED) + +#include +static const struct pios_led pios_leds[] = { + [PIOS_LED_HEARTBEAT] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, + [PIOS_LED_ALARM] = { + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Mode = GPIO_Mode_Out_PP, + .GPIO_Speed = GPIO_Speed_50MHz, + }, + }, + }, +}; + +static const struct pios_led_cfg pios_led_cfg = { + .leds = pios_leds, + .num_leds = NELEMENTS(pios_leds), +}; + +#endif /* PIOS_INCLUDE_LED */ + +#if defined(PIOS_INCLUDE_SPI) + +#include + +/* MicroSD Interface + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_sdcard_irq_handler(void); +void DMA1_Channel2_IRQHandler() __attribute__ ((alias ("PIOS_SPI_sdcard_irq_handler"))); +void DMA1_Channel3_IRQHandler() __attribute__ ((alias ("PIOS_SPI_sdcard_irq_handler"))); +static const struct pios_spi_cfg pios_spi_sdcard_cfg = { + .regs = SPI1, + .init = { + .SPI_Mode = SPI_Mode_Master, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Soft, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_2Edge, + .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256, /* Maximum divider (ie. slowest clock rate) */ + }, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), + .init = { + .NVIC_IRQChannel = DMA1_Channel2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel2, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel3, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + .sclk = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .miso = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .mosi = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +/* AHRS Interface + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_ahrs_irq_handler(void); +void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); +void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_ahrs_irq_handler"))); +static const struct pios_spi_cfg pios_spi_ahrs_cfg = { + .regs = SPI2, + .init = { + .SPI_Mode = SPI_Mode_Master, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Soft, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 7, + .SPI_CPOL = SPI_CPOL_High, + .SPI_CPHA = SPI_CPHA_2Edge, + .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16, + }, + .use_crc = TRUE, + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + + .irq = { + .flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4), + .init = { + .NVIC_IRQChannel = DMA1_Channel4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel4, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel5, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + .ssel = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_12, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + .sclk = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_13, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .miso = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_14, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .mosi = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_15, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +static uint32_t pios_spi_sdcard_id; +void PIOS_SPI_sdcard_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_sdcard_id); +} + +uint32_t pios_spi_ahrs_id; +void PIOS_SPI_ahrs_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_ahrs_id); +} + +#endif /* PIOS_INCLUDE_SPI */ + +#if defined(PIOS_INCLUDE_ADC) + +/* + * ADC system + */ +#include "pios_adc_priv.h" +extern void PIOS_ADC_handler(void); +void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); +// Remap the ADC DMA handler to this one +static const struct pios_adc_cfg pios_adc_cfg = { + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + .irq = { + .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), + .init = { + .NVIC_IRQChannel = DMA1_Channel1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .channel = DMA1_Channel1, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, + .DMA_Mode = DMA_Mode_Circular, + .DMA_Priority = DMA_Priority_Low, + .DMA_M2M = DMA_M2M_Disable, + }, + } + }, + .half_flag = DMA1_IT_HT1, + .full_flag = DMA1_IT_TC1, +}; + +struct pios_adc_dev pios_adc_devs[] = { + { + .cfg = &pios_adc_cfg, + .callback_function = NULL, + }, +}; + +uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); + +void PIOS_ADC_handler() { + PIOS_ADC_DMA_Handler(); +} + +#endif /* PIOS_INCLUDE_ADC */ + +#if defined(PIOS_INCLUDE_TIM) + +#include "pios_tim_priv.h" + +static const TIM_TimeBaseInitTypeDef tim_4_8_time_base = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = ((1000000 / PIOS_SERVO_UPDATE_HZ) - 1), + .TIM_RepetitionCounter = 0x0000, +}; + +static const struct pios_tim_clock_cfg tim_4_cfg = { + .timer = TIM4, + .time_base_init = &tim_4_8_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM4_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_8_cfg = { + .timer = TIM8, + .time_base_init = &tim_4_8_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM8_CC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const TIM_TimeBaseInitTypeDef tim_1_3_5_time_base = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = 0xFFFF, + .TIM_RepetitionCounter = 0x0000, +}; + +static const struct pios_tim_clock_cfg tim_1_cfg = { + .timer = TIM1, + .time_base_init = &tim_1_3_5_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM1_CC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_3_cfg = { + .timer = TIM3, + .time_base_init = &tim_1_3_5_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +static const struct pios_tim_clock_cfg tim_5_cfg = { + .timer = TIM5, + .time_base_init = &tim_1_3_5_time_base, + .irq = { + .init = { + .NVIC_IRQChannel = TIM5_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +#endif /* PIOS_INCLUDE_TIM */ + +#if defined(PIOS_INCLUDE_USART) + +#include "pios_usart_priv.h" + +/* + * Telemetry USART + */ +static const struct pios_usart_cfg pios_usart_telem_cfg = { + .regs = USART2, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_3, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_2, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +/* + * GPS USART + */ +static const struct pios_usart_cfg pios_usart_gps_cfg = { + .regs = USART3, + .remap = GPIO_PartialRemap_USART3, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART3_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#ifdef PIOS_COM_AUX +/* + * AUX USART + */ +static const struct pios_usart_cfg pios_usart_aux_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .remap = GPIO_Remap_USART1, + .rx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; +#endif + +#if defined(PIOS_INCLUDE_RTC) +/* + * Realtime Clock (RTC) + */ +#include + +void PIOS_RTC_IRQ_Handler (void); +void RTC_IRQHandler() __attribute__ ((alias ("PIOS_RTC_IRQ_Handler"))); +static const struct pios_rtc_cfg pios_rtc_main_cfg = { + .clksrc = RCC_RTCCLKSource_HSE_Div128, + .prescaler = 100, + .irq = { + .init = { + .NVIC_IRQChannel = RTC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +void PIOS_RTC_IRQ_Handler (void) +{ + PIOS_RTC_irq_handler (); +} + +#endif + +#if defined(PIOS_INCLUDE_DSM) +/* + * Spektrum/JR DSM USART + */ +#include + +static const struct pios_usart_cfg pios_usart_dsm_cfg = { + .regs = USART1, + .init = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx, + }, + .irq = { + .init = { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, +}; + +static const struct pios_dsm_cfg pios_dsm_cfg = { + .bind = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, +}; + +#endif /* PIOS_COM_DSM */ + +#if defined(PIOS_INCLUDE_SBUS) +#error PIOS_INCLUDE_SBUS not implemented +#endif /* PIOS_INCLUDE_SBUS */ + +#endif /* PIOS_INCLUDE_USART */ + +#if defined(PIOS_INCLUDE_COM) + +#include "pios_com_priv.h" + +#endif /* PIOS_INCLUDE_COM */ + +#if defined(PIOS_INCLUDE_SERVO) && defined(PIOS_INCLUDE_TIM) + +/** + * Pios servo configuration structures + */ +#include +static const struct pios_tim_channel pios_tim_servoport_all_pins[] = { + { + .timer = TIM4, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM4, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM8, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM8, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM8, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM8, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Mode = GPIO_Mode_AF_PP, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, +}; + +const struct pios_servo_cfg pios_servo_cfg = { + .tim_oc_init = { + .TIM_OCMode = TIM_OCMode_PWM1, + .TIM_OutputState = TIM_OutputState_Enable, + .TIM_OutputNState = TIM_OutputNState_Disable, + .TIM_Pulse = PIOS_SERVOS_INITIAL_POSITION, + .TIM_OCPolarity = TIM_OCPolarity_High, + .TIM_OCNPolarity = TIM_OCPolarity_High, + .TIM_OCIdleState = TIM_OCIdleState_Reset, + .TIM_OCNIdleState = TIM_OCNIdleState_Reset, + }, + .channels = pios_tim_servoport_all_pins, + .num_channels = NELEMENTS(pios_tim_servoport_all_pins), +}; + +#endif /* PIOS_INCLUDE_SERVO && PIOS_INCLUDE_TIM */ + +/* + * PWM Inputs + */ +#if defined(PIOS_INCLUDE_PWM) || defined(PIOS_INCLUDE_PPM) +#include +static const struct pios_tim_channel pios_tim_rcvrport_all_channels[] = { + { + .timer = TIM1, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM1, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM5, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM1, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOA, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_4, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_1, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_3, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_0, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_1, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap_TIM3, + }, + { + .timer = TIM3, + .timer_chan = TIM_Channel_2, + .pin = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + }, + }, + .remap = GPIO_PartialRemap_TIM3, + }, +}; + +const struct pios_pwm_cfg pios_pwm_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + }, + .channels = pios_tim_rcvrport_all_channels, + .num_channels = NELEMENTS(pios_tim_rcvrport_all_channels), +}; +#endif + +/* + * PPM Input + */ +#if defined(PIOS_INCLUDE_PPM) +#include +static const struct pios_ppm_cfg pios_ppm_cfg = { + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + .TIM_Channel = TIM_Channel_2, + }, + /* Use only the first channel for ppm */ + .channels = &pios_tim_rcvrport_all_channels[0], + .num_channels = 1, +}; + +#endif //PPM + +#if defined(PIOS_INCLUDE_I2C) + +#include + +/* + * I2C Adapters + */ + +void PIOS_I2C_main_adapter_ev_irq_handler(void); +void PIOS_I2C_main_adapter_er_irq_handler(void); +void I2C2_EV_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_ev_irq_handler"))); +void I2C2_ER_IRQHandler() __attribute__ ((alias ("PIOS_I2C_main_adapter_er_irq_handler"))); + +static const struct pios_i2c_adapter_cfg pios_i2c_main_adapter_cfg = { + .regs = I2C2, + .init = { + .I2C_Mode = I2C_Mode_I2C, + .I2C_OwnAddress1 = 0, + .I2C_Ack = I2C_Ack_Enable, + .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit, + .I2C_DutyCycle = I2C_DutyCycle_2, + .I2C_ClockSpeed = 400000, /* bits/s */ + }, + .transfer_timeout_ms = 50, + .scl = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .sda = { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_11, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_OD, + }, + }, + .event = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_EV_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .error = { + .flags = 0, /* FIXME: check this */ + .init = { + .NVIC_IRQChannel = I2C2_ER_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGHEST, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +uint32_t pios_i2c_main_adapter_id; +void PIOS_I2C_main_adapter_ev_irq_handler(void) +{ +#ifdef I2C_DEBUG_PIN + PIOS_DEBUG_PinHigh(I2C_DEBUG_PIN); +#endif + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_EV_IRQ_Handler(pios_i2c_main_adapter_id); +#ifdef I2C_DEBUG_PIN + PIOS_DEBUG_PinLow(I2C_DEBUG_PIN); +#endif +} + +void PIOS_I2C_main_adapter_er_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_I2C_ER_IRQ_Handler(pios_i2c_main_adapter_id); +} + +#endif /* PIOS_INCLUDE_I2C */ + +#if defined(PIOS_ENABLE_DEBUG_PINS) + +static const struct stm32_gpio pios_debug_pins[] = { + #define PIOS_DEBUG_PIN_SERVO_1 0 + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_2 1 + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_3 2 + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_4 3 + { + .gpio = GPIOB, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_5 4 + { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_6 5 + { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_7 6 + { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_8, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + #define PIOS_DEBUG_PIN_SERVO_8 7 + { + .gpio = GPIOC, + .init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, +}; + +#endif /* PIOS_ENABLE_DEBUG_PINS */ + +#if defined(PIOS_INCLUDE_RCVR) +#include "pios_rcvr_priv.h" + +#endif /* PIOS_INCLUDE_RCVR */ + +#if defined(PIOS_INCLUDE_USB) +#include "pios_usb_priv.h" + +static const struct pios_usb_cfg pios_usb_main_cfg = { + .irq = { + .init = { + .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_cdc_priv.h" +#include "pios_usb_desc_hid_only_priv.h" +#endif /* PIOS_INCLUDE_USB */ + +#if defined(PIOS_INCLUDE_COM_MSG) + +#include + +#endif /* PIOS_INCLUDE_COM_MSG */ + +#if defined(PIOS_INCLUDE_USB_HID) +#include + +const struct pios_usb_hid_cfg pios_usb_hid_cfg = { + .data_if = 0, + .data_rx_ep = 1, + .data_tx_ep = 1, +}; + +#endif /* PIOS_INCLUDE_USB_HID */ + +#if defined(PIOS_INCLUDE_USB_CDC) +#include + +const struct pios_usb_cdc_cfg pios_usb_cdc_cfg = { + .ctrl_if = 1, + .ctrl_tx_ep = 2, + + .data_if = 2, + .data_rx_ep = 3, + .data_tx_ep = 3, +}; +#endif /* PIOS_INCLUDE_USB_CDC */ diff --git a/flight/board_hw_defs/pipxtreme/board_hw_defs.c b/flight/board_hw_defs/pipxtreme/board_hw_defs.c new file mode 100644 index 000000000..8dc17d5ba --- /dev/null +++ b/flight/board_hw_defs/pipxtreme/board_hw_defs.c @@ -0,0 +1,273 @@ +#include + +#if defined(PIOS_INCLUDE_SPI) + +#include + +/* OP Interface + * + * NOTE: Leave this declared as const data so that it ends up in the + * .rodata section (ie. Flash) rather than in the .bss section (RAM). + */ +void PIOS_SPI_port_irq_handler(void); +void DMA1_Channel5_IRQHandler() __attribute__ ((alias ("PIOS_SPI_port_irq_handler"))); +void DMA1_Channel4_IRQHandler() __attribute__ ((alias ("PIOS_SPI_port_irq_handler"))); + +static const struct pios_spi_cfg pios_spi_port_cfg = +{ + .regs = SPI1, + + .init = + { + .SPI_Mode = SPI_Mode_Master, + .SPI_Direction = SPI_Direction_2Lines_FullDuplex, + .SPI_DataSize = SPI_DataSize_8b, + .SPI_NSS = SPI_NSS_Soft, + .SPI_FirstBit = SPI_FirstBit_MSB, + .SPI_CRCPolynomial = 0, + .SPI_CPOL = SPI_CPOL_Low, + .SPI_CPHA = SPI_CPHA_1Edge, + .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256, // slowest SCLK + }, + .use_crc = FALSE, + + .dma = + { + .ahb_clk = RCC_AHBPeriph_DMA1, + .irq = + { + .flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2), + .init = { + .NVIC_IRQChannel = DMA1_Channel2_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + + .rx = { + .channel = DMA1_Channel2, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + .tx = { + .channel = DMA1_Channel3, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR), + .DMA_DIR = DMA_DIR_PeripheralDST, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Byte, + .DMA_Mode = DMA_Mode_Normal, + .DMA_Priority = DMA_Priority_Medium, + .DMA_M2M = DMA_M2M_Disable, + }, + }, + }, + + .ssel = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_4, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_Out_PP, + }, + }, + .sclk = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_5, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, + .miso = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_6, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .mosi = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_7, + .GPIO_Speed = GPIO_Speed_10MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +uint32_t pios_spi_port_id; +void PIOS_SPI_port_irq_handler(void) +{ + /* Call into the generic code to handle the IRQ for this specific device */ + PIOS_SPI_IRQ_Handler(pios_spi_port_id); +} + +#endif /* PIOS_INCLUDE_SPI */ + +#if defined(PIOS_INCLUDE_ADC) + +/* + * ADC system + */ +#include "pios_adc_priv.h" +extern void PIOS_ADC_handler(void); +void DMA1_Channel1_IRQHandler() __attribute__ ((alias("PIOS_ADC_handler"))); +// Remap the ADC DMA handler to this one +static const struct pios_adc_cfg pios_adc_cfg = { + .dma = { + .ahb_clk = RCC_AHBPeriph_DMA1, + .irq = { + .flags = (DMA1_FLAG_TC1 | DMA1_FLAG_TE1 | DMA1_FLAG_HT1 | DMA1_FLAG_GL1), + .init = { + .NVIC_IRQChannel = DMA1_Channel1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = { + .channel = DMA1_Channel1, + .init = { + .DMA_PeripheralBaseAddr = (uint32_t) & ADC1->DR, + .DMA_DIR = DMA_DIR_PeripheralSRC, + .DMA_PeripheralInc = DMA_PeripheralInc_Disable, + .DMA_MemoryInc = DMA_MemoryInc_Enable, + .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word, + .DMA_MemoryDataSize = DMA_MemoryDataSize_Word, + .DMA_Mode = DMA_Mode_Circular, + .DMA_Priority = DMA_Priority_High, + .DMA_M2M = DMA_M2M_Disable, + }, + } + }, + .half_flag = DMA1_IT_HT1, + .full_flag = DMA1_IT_TC1, +}; + +struct pios_adc_dev pios_adc_devs[] = { + { + .cfg = &pios_adc_cfg, + .callback_function = NULL, + }, +}; + +uint8_t pios_adc_num_devices = NELEMENTS(pios_adc_devs); + +void PIOS_ADC_handler() { + PIOS_ADC_DMA_Handler(); +} + +#endif /* PIOS_INCLUDE_ADC */ + +#if defined(PIOS_INCLUDE_USART) + +#include + +/* + * SERIAL USART + */ +static const struct pios_usart_cfg pios_usart_serial_cfg = +{ + .regs = USART1, + .init = + { + .USART_BaudRate = 57600, + .USART_WordLength = USART_WordLength_8b, + .USART_Parity = USART_Parity_No, + .USART_StopBits = USART_StopBits_1, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + .USART_Mode = USART_Mode_Rx | USART_Mode_Tx, + }, + .irq = + { + .init = + { + .NVIC_IRQChannel = USART1_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .rx = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_10, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_IPU, + }, + }, + .tx = + { + .gpio = GPIOA, + .init = + { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }, + }, +}; + +#endif /* PIOS_INCLUDE_USART */ + +#if defined(PIOS_INCLUDE_COM) + +#include + +#endif /* PIOS_INCLUDE_COM */ + +// *********************************************************************************** + +#if defined(PIOS_INCLUDE_USB) +#include "pios_usb_priv.h" + +static const struct pios_usb_cfg pios_usb_main_cfg = { + .irq = { + .init = { + .NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_LOW, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, +}; + +#include "pios_usb_board_data_priv.h" +#include "pios_usb_desc_hid_only_priv.h" + +#endif /* PIOS_INCLUDE_USB */ + +#if defined(PIOS_INCLUDE_USB_HID) +#include + +const struct pios_usb_hid_cfg pios_usb_hid_cfg = { + .data_if = 0, + .data_rx_ep = 1, + .data_tx_ep = 1, +}; + +#endif /* PIOS_INCLUDE_USB_HID */ From bfe6676eed6fe40e4b9a6271fd3b8c30f4e21845 Mon Sep 17 00:00:00 2001 From: Stacey Sheldon Date: Sun, 22 Jan 2012 23:23:41 -0500 Subject: [PATCH 50/72] exti: rewrite exti layer to improve portability The exti layer now allows drivers to register interrupt callbacks during board initialization. All details of the driver using a particular EXTI pin have been removed from the EXTI layer so it can now be used on any board without board-specific modification. This includes some nice refinements provided by Mike Smith during initial review. His original commits have been squashed into this one. --- flight/PiOS.posix/posix/pios_debug.c | 2 +- flight/PiOS/Boards/STM32103CB_CC_Rev1.h | 2 - flight/PiOS/Boards/STM3210E_OP.h | 2 - flight/PiOS/Common/pios_bmp085.c | 96 +++++--- flight/PiOS/Common/pios_hmc5843.c | 66 +++--- .../inc/stm32f10x_exti.h | 2 +- .../src/stm32f10x_exti.c | 2 +- flight/PiOS/STM32F10x/pios_exti.c | 222 ++++++++++++++---- flight/PiOS/inc/pios_exti.h | 15 ++ flight/PiOS/inc/pios_stm32.h | 4 + 10 files changed, 299 insertions(+), 114 deletions(-) diff --git a/flight/PiOS.posix/posix/pios_debug.c b/flight/PiOS.posix/posix/pios_debug.c index 5956a9d04..7f3dc99da 100644 --- a/flight/PiOS.posix/posix/pios_debug.c +++ b/flight/PiOS.posix/posix/pios_debug.c @@ -72,7 +72,7 @@ void PIOS_DEBUG_PinValue4BitL(uint8_t value) /** * Report a serious error and halt */ -void PIOS_DEBUG_Panic(const char *msg) +void PIOS_DEBUG_Panic(const char *msg) __attribute__ ((noreturn)) { #ifdef PIOS_COM_DEBUG register int *lr asm("lr"); // Link-register holds the PC of the caller diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index 7773b9092..aebd322cb 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -284,6 +284,4 @@ extern uint32_t pios_com_telem_usb_id; #define PIOS_USB_DETECT_GPIO_PORT GPIOC #define PIOS_USB_MAX_DEVS 1 #define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_15 -#define PIOS_USB_DETECT_EXTI_LINE EXTI_Line15 -#define PIOS_IRQ_USB_PRIORITY PIOS_IRQ_PRIO_MID #endif /* STM32103CB_AHRS_H_ */ diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index 7099234c6..6a166d0fd 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -316,8 +316,6 @@ extern uint32_t pios_com_aux_id; #define PIOS_USB_MAX_DEVS 1 #define PIOS_USB_HID_MAX_DEVS 1 #define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_4 -#define PIOS_USB_DETECT_EXTI_LINE EXTI_Line4 -#define PIOS_IRQ_USB_PRIORITY PIOS_IRQ_PRIO_MID /** * glue macros for file IO diff --git a/flight/PiOS/Common/pios_bmp085.c b/flight/PiOS/Common/pios_bmp085.c index 5a4b0cd94..cd294230b 100644 --- a/flight/PiOS/Common/pios_bmp085.c +++ b/flight/PiOS/Common/pios_bmp085.c @@ -36,19 +36,11 @@ #error PIOS_EXTI Must be included in the project! #endif /* PIOS_INCLUDE_EXTI */ +#include + /* Glocal Variables */ ConversionTypeTypeDef CurrentRead; -#ifdef PIOS_BMP085_HAS_GPIOS - -#if defined(PIOS_INCLUDE_FREERTOS) -xSemaphoreHandle PIOS_BMP085_EOC; -#else -int32_t PIOS_BMP085_EOC; -#endif - -#endif /* PIOS_BMP085_HAS_GPIOS */ - /* Local Variables */ static BMP085CalibDataTypeDef CalibData; @@ -60,18 +52,69 @@ static volatile uint32_t RawPressure; static volatile uint32_t Pressure; static volatile uint16_t Temperature; +#ifdef PIOS_BMP085_HAS_GPIOS + +#if defined(PIOS_INCLUDE_FREERTOS) +xSemaphoreHandle PIOS_BMP085_EOC; +#else +int32_t PIOS_BMP085_EOC; +#endif + +void PIOS_BMP085_EndOfConversion (void) +{ +#if defined(PIOS_INCLUDE_FREERTOS) + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; +#endif + + /* Read the ADC Value */ +#if defined(PIOS_INCLUDE_FREERTOS) + xSemaphoreGiveFromISR(PIOS_BMP085_EOC, &xHigherPriorityTaskWoken); +#else + PIOS_BMP085_EOC=1; +#endif + +#if defined(PIOS_INCLUDE_FREERTOS) + /* Yield From ISR if needed */ + portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); +#endif +} + +static const struct pios_exti_cfg pios_exti_bmp085_cfg __exti_config = { + .vector = PIOS_BMP085_EndOfConversion, + .line = PIOS_BMP085_EOC_EXTI_LINE, + .pin = { + .gpio = PIOS_BMP085_EOC_GPIO_PORT, + .init = { + .GPIO_Pin = PIOS_BMP085_EOC_GPIO_PIN, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .irq = { + .init = { + .NVIC_IRQChannel = PIOS_BMP085_EOC_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_BMP085_EOC_PRIO, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .exti = { + .init = { + .EXTI_Line = PIOS_BMP085_EOC_EXTI_LINE, + .EXTI_Mode = EXTI_Mode_Interrupt, + .EXTI_Trigger = EXTI_Trigger_Rising, + .EXTI_LineCmd = ENABLE, + }, + }, +}; + +#endif /* PIOS_BMP085_HAS_GPIOS */ /** * Initialise the BMP085 sensor */ void PIOS_BMP085_Init(void) { - #ifdef PIOS_BMP085_HAS_GPIOS - GPIO_InitTypeDef GPIO_InitStructure; - EXTI_InitTypeDef EXTI_InitStructure; - NVIC_InitTypeDef NVIC_InitStructure; - #if defined(PIOS_INCLUDE_FREERTOS) /* Semaphore used by ISR to signal End-Of-Conversion */ vSemaphoreCreateBinary(PIOS_BMP085_EOC); @@ -84,27 +127,12 @@ void PIOS_BMP085_Init(void) /* Enable EOC GPIO clock */ RCC_APB2PeriphClockCmd(PIOS_BMP085_EOC_CLK | RCC_APB2Periph_AFIO, ENABLE); - /* Configure EOC pin as input floating */ - GPIO_InitStructure.GPIO_Pin = PIOS_BMP085_EOC_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_Init(PIOS_BMP085_EOC_GPIO_PORT, &GPIO_InitStructure); - - /* Configure the End Of Conversion (EOC) interrupt */ - GPIO_EXTILineConfig(PIOS_BMP085_EOC_PORT_SOURCE, PIOS_BMP085_EOC_PIN_SOURCE); - EXTI_InitStructure.EXTI_Line = PIOS_BMP085_EOC_EXTI_LINE; - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; - EXTI_InitStructure.EXTI_LineCmd = ENABLE; - EXTI_Init(&EXTI_InitStructure); - - /* Enable and set EOC EXTI Interrupt to the lowest priority */ - NVIC_InitStructure.NVIC_IRQChannel = PIOS_BMP085_EOC_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_BMP085_EOC_PRIO; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + if (PIOS_EXTI_Init(&pios_exti_bmp085_cfg)) { + PIOS_Assert(0); + } /* Configure XCLR pin as push/pull alternate funtion output */ + GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = PIOS_BMP085_XCLR_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(PIOS_BMP085_XCLR_GPIO_PORT, &GPIO_InitStructure); diff --git a/flight/PiOS/Common/pios_hmc5843.c b/flight/PiOS/Common/pios_hmc5843.c index b62499d71..688d2e90f 100644 --- a/flight/PiOS/Common/pios_hmc5843.c +++ b/flight/PiOS/Common/pios_hmc5843.c @@ -34,6 +34,8 @@ #if defined(PIOS_INCLUDE_HMC5843) +#include + /* HMC5843 Addresses */ #define PIOS_HMC5843_I2C_ADDR 0x1E #define PIOS_HMC5843_CONFIG_REG_A (uint8_t)0x00 @@ -107,37 +109,48 @@ static void PIOS_HMC5843_Config(PIOS_HMC5843_ConfigTypeDef * HMC5843_Config_Stru static bool PIOS_HMC5843_Read(uint8_t address, uint8_t * buffer, uint8_t len); static bool PIOS_HMC5843_Write(uint8_t address, uint8_t buffer); +void PIOS_HMC5843_EndOfConversion (void) +{ + pios_hmc5843_data_ready = true; +} + +static const struct pios_exti_cfg pios_exti_hmc5843_cfg __exti_config = { + .vector = PIOS_HMC5843_EndOfConversion, + .line = PIOS_HMC5843_DRDY_EXTI_LINE, + .pin = { + .gpio = PIOS_HMC5843_DRDY_GPIO_PORT, + .init = { + .GPIO_Pin = PIOS_HMC5843_DRDY_GPIO_PIN, + .GPIO_Mode = GPIO_Mode_IN_FLOATING, + }, + }, + .irq = { + .init = { + .NVIC_IRQChannel = PIOS_HMC5843_DRDY_IRQn, + .NVIC_IRQChannelPreemptionPriority = PIOS_HMC5843_DRDY_PRIO, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .exti = { + .init = { + .EXTI_Line = PIOS_HMC5843_DRDY_EXTI_LINE, + .EXTI_Mode = EXTI_Mode_Interrupt, + .EXTI_Trigger = EXTI_Trigger_Rising, + .EXTI_LineCmd = ENABLE, + }, + }, +}; + /** - * @brieft Initialise the HMC5843 sensor + * @brief Initialise the HMC5843 sensor */ void PIOS_HMC5843_Init(void) { - GPIO_InitTypeDef GPIO_InitStructure; - EXTI_InitTypeDef EXTI_InitStructure; - NVIC_InitTypeDef NVIC_InitStructure; - /* Enable DRDY GPIO clock */ RCC_APB2PeriphClockCmd(PIOS_HMC5843_DRDY_CLK | RCC_APB2Periph_AFIO, ENABLE); - /* Configure EOC pin as input floating */ - GPIO_InitStructure.GPIO_Pin = PIOS_HMC5843_DRDY_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; - GPIO_Init(PIOS_HMC5843_DRDY_GPIO_PORT, &GPIO_InitStructure); - - /* Configure the End Of Conversion (EOC) interrupt */ - GPIO_EXTILineConfig(PIOS_HMC5843_DRDY_PORT_SOURCE, PIOS_HMC5843_DRDY_PIN_SOURCE); - EXTI_InitStructure.EXTI_Line = PIOS_HMC5843_DRDY_EXTI_LINE; - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; - EXTI_InitStructure.EXTI_LineCmd = ENABLE; - EXTI_Init(&EXTI_InitStructure); - - /* Enable and set EOC EXTI Interrupt to the lowest priority */ - NVIC_InitStructure.NVIC_IRQChannel = PIOS_HMC5843_DRDY_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_HMC5843_DRDY_PRIO; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + PIOS_EXTI_Init(&pios_exti_hmc5843_cfg); /* Configure the HMC5843 Sensor */ PIOS_HMC5843_ConfigTypeDef HMC5843_InitStructure; @@ -362,11 +375,6 @@ static bool PIOS_HMC5843_Write(uint8_t address, uint8_t buffer) return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list)); } -void PIOS_HMC5843_IRQHandler(void) -{ - pios_hmc5843_data_ready = true; -} - #endif /** diff --git a/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_exti.h b/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_exti.h index 29bed11cf..99084e3f3 100644 --- a/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_exti.h +++ b/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/inc/stm32f10x_exti.h @@ -155,7 +155,7 @@ typedef struct */ void EXTI_DeInit(void); -void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_Init(const EXTI_InitTypeDef* EXTI_InitStruct); void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); diff --git a/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c b/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c index f9467d0dc..73de195cb 100755 --- a/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c +++ b/flight/PiOS/STM32F10x/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_exti.c @@ -97,7 +97,7 @@ void EXTI_DeInit(void) * that contains the configuration information for the EXTI peripheral. * @retval None */ -void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) +void EXTI_Init(const EXTI_InitTypeDef* EXTI_InitStruct) { uint32_t tmp = 0; diff --git a/flight/PiOS/STM32F10x/pios_exti.c b/flight/PiOS/STM32F10x/pios_exti.c index 0b4a9a1ae..8b1d2dc32 100644 --- a/flight/PiOS/STM32F10x/pios_exti.c +++ b/flight/PiOS/STM32F10x/pios_exti.c @@ -5,7 +5,6 @@ * @{ * @addtogroup PIOS_EXTI External Interrupt Handlers * @brief External interrupt handler functions - * @note Currently deals with BMP085 readings * @{ * * @file pios_exti.c @@ -35,61 +34,196 @@ #if defined(PIOS_INCLUDE_EXTI) -/** -* Handle external lines 15 to 10 interrupt requests -*/ -void EXTI15_10_IRQHandler(void) +/* Map EXTI line to full config */ +#define EXTI_MAX_LINES 16 +#define PIOS_EXTI_INVALID 0xFF +static uint8_t pios_exti_line_to_cfg_map[EXTI_MAX_LINES] = { + [0 ... EXTI_MAX_LINES-1] = PIOS_EXTI_INVALID, +}; + +/* Table of exti configs registered at compile time */ +extern struct pios_exti_cfg __start__exti __attribute__((weak)); +extern struct pios_exti_cfg __stop__exti __attribute__((weak)); + +static uint8_t PIOS_EXTI_line_to_index (uint32_t line) { -#if defined(PIOS_INCLUDE_FREERTOS) - portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; -#endif - -#if defined(PIOS_INCLUDE_BMP085) && defined(PIOS_BMP085_HAS_GPIOS) - if (EXTI_GetITStatus(PIOS_BMP085_EOC_EXTI_LINE) != RESET) { - /* Read the ADC Value */ -#if defined(PIOS_INCLUDE_FREERTOS) - xSemaphoreGiveFromISR(PIOS_BMP085_EOC, &xHigherPriorityTaskWoken); -#else - PIOS_BMP085_EOC=1; -#endif - - /* Clear the EXTI line pending bit */ - EXTI_ClearITPendingBit(PIOS_BMP085_EOC_EXTI_LINE); + switch (line) { + case EXTI_Line0: return 0; + case EXTI_Line1: return 1; + case EXTI_Line2: return 2; + case EXTI_Line3: return 3; + case EXTI_Line4: return 4; + case EXTI_Line5: return 5; + case EXTI_Line6: return 6; + case EXTI_Line7: return 7; + case EXTI_Line8: return 8; + case EXTI_Line9: return 9; + case EXTI_Line10: return 10; + case EXTI_Line11: return 11; + case EXTI_Line12: return 12; + case EXTI_Line13: return 13; + case EXTI_Line14: return 14; + case EXTI_Line15: return 15; } -#endif -#if defined(PIOS_INCLUDE_FREERTOS) - /* Yield From ISR if needed */ - portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); -#endif + PIOS_Assert(0); + return 0xFF; } -/** -* Handle external lines 9 to 5 interrupt requests -*/ -extern void PIOS_HMC5843_IRQHandler(void); -void EXTI9_5_IRQHandler(void) +uint8_t PIOS_EXTI_gpio_port_to_exti_source_port(GPIO_TypeDef * gpio_port) { -#if defined(PIOS_INCLUDE_HMC5843) - if (EXTI_GetITStatus(PIOS_HMC5843_DRDY_EXTI_LINE) != RESET) { - PIOS_HMC5843_IRQHandler(); - EXTI_ClearITPendingBit(PIOS_HMC5843_DRDY_EXTI_LINE); + switch((uint32_t)gpio_port) { + case (uint32_t)GPIOA: return (GPIO_PortSourceGPIOA); + case (uint32_t)GPIOB: return (GPIO_PortSourceGPIOB); + case (uint32_t)GPIOC: return (GPIO_PortSourceGPIOC); + case (uint32_t)GPIOD: return (GPIO_PortSourceGPIOD); + case (uint32_t)GPIOE: return (GPIO_PortSourceGPIOE); + case (uint32_t)GPIOF: return (GPIO_PortSourceGPIOF); + case (uint32_t)GPIOG: return (GPIO_PortSourceGPIOG); } -#endif + + PIOS_Assert(0); + return 0xFF; } -/** -* Handle external line 4 interrupt requests -*/ -#if defined(PIOS_INCLUDE_USB) -void EXTI4_IRQHandler(void) +uint8_t PIOS_EXTI_gpio_pin_to_exti_source_pin(uint32_t gpio_pin) { - if (EXTI_GetITStatus(PIOS_USB_DETECT_EXTI_LINE) != RESET) { - /* Clear the EXTI line pending bit */ - EXTI_ClearITPendingBit(PIOS_USB_DETECT_EXTI_LINE); + switch((uint32_t)gpio_pin) { + case GPIO_Pin_0: return (GPIO_PinSource0); + case GPIO_Pin_1: return (GPIO_PinSource1); + case GPIO_Pin_2: return (GPIO_PinSource2); + case GPIO_Pin_3: return (GPIO_PinSource3); + case GPIO_Pin_4: return (GPIO_PinSource4); + case GPIO_Pin_5: return (GPIO_PinSource5); + case GPIO_Pin_6: return (GPIO_PinSource6); + case GPIO_Pin_7: return (GPIO_PinSource7); + case GPIO_Pin_8: return (GPIO_PinSource8); + case GPIO_Pin_9: return (GPIO_PinSource9); + case GPIO_Pin_10: return (GPIO_PinSource10); + case GPIO_Pin_11: return (GPIO_PinSource11); + case GPIO_Pin_12: return (GPIO_PinSource12); + case GPIO_Pin_13: return (GPIO_PinSource13); + case GPIO_Pin_14: return (GPIO_PinSource14); + case GPIO_Pin_15: return (GPIO_PinSource15); } + + PIOS_Assert(0); + return 0xFF; } -#endif + +int32_t PIOS_EXTI_Init(const struct pios_exti_cfg * cfg) +{ + PIOS_Assert(cfg); + PIOS_Assert(&__start__exti); + PIOS_Assert(cfg >= &__start__exti); + PIOS_Assert(cfg < &__stop__exti); + + uint8_t cfg_index = cfg - &__start__exti; + + /* Connect this config to the requested vector */ + uint8_t line_index = PIOS_EXTI_line_to_index(cfg->line); + + if (pios_exti_line_to_cfg_map[line_index] != PIOS_EXTI_INVALID) { + /* Someone else already has this mapped */ + goto out_fail; + } + + /* Bind the config to the exti line */ + pios_exti_line_to_cfg_map[line_index] = cfg_index; + + /* Initialize the GPIO pin */ + GPIO_Init(cfg->pin.gpio, &cfg->pin.init); + + /* Set up the EXTI interrupt source */ + uint8_t exti_source_port = PIOS_EXTI_gpio_port_to_exti_source_port(cfg->pin.gpio); + uint8_t exti_source_pin = PIOS_EXTI_gpio_pin_to_exti_source_pin(cfg->pin.init.GPIO_Pin); + GPIO_EXTILineConfig(exti_source_port, exti_source_pin); + EXTI_Init(&cfg->exti.init); + + /* Enable the interrupt channel */ + NVIC_Init(&cfg->irq.init); + + return 0; + +out_fail: + return -1; +} + +static void PIOS_EXTI_generic_irq_handler(uint8_t line_index) +{ + uint8_t cfg_index = pios_exti_line_to_cfg_map[line_index]; + + PIOS_Assert(&__start__exti); + + if (cfg_index > NELEMENTS(pios_exti_line_to_cfg_map) || + cfg_index == PIOS_EXTI_INVALID) { + /* Unconfigured interrupt just fired! */ + return; + } + + struct pios_exti_cfg * cfg = &__start__exti + cfg_index; + cfg->vector(); +} + +/* Bind Interrupt Handlers */ + +#define PIOS_EXTI_HANDLE_LINE(line) \ + if (EXTI_GetITStatus(EXTI_Line##line) != RESET) { \ + EXTI_ClearITPendingBit(EXTI_Line##line); \ + PIOS_EXTI_generic_irq_handler(line); \ + } + +static void PIOS_EXTI_0_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(0); +} +void EXTI0_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_0_irq_handler"))); + +static void PIOS_EXTI_1_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(1); +} +void EXTI1_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_1_irq_handler"))); + +static void PIOS_EXTI_2_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(2); +} +void EXTI2_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_2_irq_handler"))); + +static void PIOS_EXTI_3_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(3); +} +void EXTI3_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_3_irq_handler"))); + +static void PIOS_EXTI_4_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(4); +} +void EXTI4_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_4_irq_handler"))); + +static void PIOS_EXTI_9_5_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(5); + PIOS_EXTI_HANDLE_LINE(6); + PIOS_EXTI_HANDLE_LINE(7); + PIOS_EXTI_HANDLE_LINE(8); + PIOS_EXTI_HANDLE_LINE(9); +} +void EXTI9_5_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_9_5_irq_handler"))); + +static void PIOS_EXTI_15_10_irq_handler (void) +{ + PIOS_EXTI_HANDLE_LINE(10); + PIOS_EXTI_HANDLE_LINE(11); + PIOS_EXTI_HANDLE_LINE(12); + PIOS_EXTI_HANDLE_LINE(13); + PIOS_EXTI_HANDLE_LINE(14); + PIOS_EXTI_HANDLE_LINE(15); +} +void EXTI15_10_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_15_10_irq_handler"))); + #endif /** diff --git a/flight/PiOS/inc/pios_exti.h b/flight/PiOS/inc/pios_exti.h index fdccc6bf2..73a3bb556 100644 --- a/flight/PiOS/inc/pios_exti.h +++ b/flight/PiOS/inc/pios_exti.h @@ -33,6 +33,21 @@ /* Public Functions */ +#include + +struct pios_exti_cfg { + void (* vector)(void); + uint32_t line; /* use EXTI_LineN macros */ + struct stm32_gpio pin; + struct stm32_irq irq; + struct stm32_exti exti; +}; + +/* must be added to any pios_exti_cfg definition for it to be valid */ +#define __exti_config __attribute__((section("_exti"))) + +extern int32_t PIOS_EXTI_Init(const struct pios_exti_cfg * cfg); + #endif /* PIOS_EXTI_H */ /** diff --git a/flight/PiOS/inc/pios_stm32.h b/flight/PiOS/inc/pios_stm32.h index fb9163208..4e63d6937 100644 --- a/flight/PiOS/inc/pios_stm32.h +++ b/flight/PiOS/inc/pios_stm32.h @@ -36,6 +36,10 @@ struct stm32_irq { NVIC_InitTypeDef init; }; +struct stm32_exti { + EXTI_InitTypeDef init; +}; + struct stm32_dma_chan { DMA_Channel_TypeDef *channel; DMA_InitTypeDef init; From da650cee607b194b6057d9f42498f82ba4813ca6 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Tue, 24 Jan 2012 11:31:00 +0200 Subject: [PATCH 51/72] gcscontrol: keep joystick image aspect ratio OP-619 --- ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp index 0596b22c1..571b07068 100644 --- a/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp +++ b/ground/openpilotgcs/src/plugins/gcscontrol/joystickcontrol.cpp @@ -149,7 +149,7 @@ void JoystickControl::paintEvent(QPaintEvent *event) void JoystickControl::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); - fitInView(m_background, Qt::IgnoreAspectRatio ); + fitInView(m_background, Qt::KeepAspectRatio); } /** From f029567e66ce86c631d3c1d607cba1e6c781bd5a Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 24 Jan 2012 10:39:35 -0600 Subject: [PATCH 52/72] Remove meaningless settings from CC config file --- flight/CopterControl/System/inc/pios_config.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/flight/CopterControl/System/inc/pios_config.h b/flight/CopterControl/System/inc/pios_config.h index de954b666..1d701a1af 100644 --- a/flight/CopterControl/System/inc/pios_config.h +++ b/flight/CopterControl/System/inc/pios_config.h @@ -83,10 +83,6 @@ /* A really shitty setting saving implementation */ #define PIOS_INCLUDE_FLASH_SECTOR_SETTINGS -/* Defaults for Logging */ -#define LOG_FILENAME "PIOS.LOG" -#define STARTUP_LOG_ENABLED 1 - /* Alarm Thresholds */ #define HEAP_LIMIT_WARNING 220 #define HEAP_LIMIT_CRITICAL 40 From 2c4ed09707d213be2c64186b75d924b82a611458 Mon Sep 17 00:00:00 2001 From: zedamota Date: Tue, 24 Jan 2012 22:29:08 +0000 Subject: [PATCH 53/72] added new Transmitter artwork to the input wizard. --- .../src/plugins/config/configgadget.qrc | 1 + .../src/plugins/config/configinputwidget.cpp | 6 +- .../src/plugins/config/images/TX2.svg | 2852 +++++++++++++++++ 3 files changed, 2856 insertions(+), 3 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/config/images/TX2.svg diff --git a/ground/openpilotgcs/src/plugins/config/configgadget.qrc b/ground/openpilotgcs/src/plugins/config/configgadget.qrc index f24cb68b8..6eb11f079 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadget.qrc +++ b/ground/openpilotgcs/src/plugins/config/configgadget.qrc @@ -17,5 +17,6 @@ images/gyroscope.png images/TX.svg images/camera.png + images/TX2.svg diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 863104447..2f3b83754 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -41,8 +41,8 @@ #include #include -#define ACCESS_MIN_MOVE -6 -#define ACCESS_MAX_MOVE 6 +#define ACCESS_MIN_MOVE -3 +#define ACCESS_MAX_MOVE 3 #define STICK_MIN_MOVE -8 #define STICK_MAX_MOVE 8 @@ -108,7 +108,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_renderer = new QSvgRenderer(); QGraphicsScene *l_scene = m_config->graphicsView->scene(); m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); - if (QFile::exists(":/configgadget/images/TX.svg") && m_renderer->load(QString(":/configgadget/images/TX.svg")) && m_renderer->isValid()) + if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer->load(QString(":/configgadget/images/TX2.svg")) && m_renderer->isValid()) { l_scene->clear(); // Deletes all items contained in the scene as well. diff --git a/ground/openpilotgcs/src/plugins/config/images/TX2.svg b/ground/openpilotgcs/src/plugins/config/images/TX2.svg new file mode 100644 index 000000000..a6c8a533a --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/images/TX2.svg @@ -0,0 +1,2852 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 242bfe6c69413996089cb6721f1fdd5c3f12848d Mon Sep 17 00:00:00 2001 From: zedamota Date: Tue, 24 Jan 2012 22:29:08 +0000 Subject: [PATCH 54/72] added new Transmitter artwork to the input wizard. --- .../src/plugins/config/configgadget.qrc | 1 + .../src/plugins/config/configinputwidget.cpp | 6 +- .../src/plugins/config/images/TX2.svg | 2852 +++++++++++++++++ 3 files changed, 2856 insertions(+), 3 deletions(-) create mode 100644 ground/openpilotgcs/src/plugins/config/images/TX2.svg diff --git a/ground/openpilotgcs/src/plugins/config/configgadget.qrc b/ground/openpilotgcs/src/plugins/config/configgadget.qrc index f24cb68b8..6eb11f079 100644 --- a/ground/openpilotgcs/src/plugins/config/configgadget.qrc +++ b/ground/openpilotgcs/src/plugins/config/configgadget.qrc @@ -17,5 +17,6 @@ images/gyroscope.png images/TX.svg images/camera.png + images/TX2.svg diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 863104447..2f3b83754 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -41,8 +41,8 @@ #include #include -#define ACCESS_MIN_MOVE -6 -#define ACCESS_MAX_MOVE 6 +#define ACCESS_MIN_MOVE -3 +#define ACCESS_MAX_MOVE 3 #define STICK_MIN_MOVE -8 #define STICK_MAX_MOVE 8 @@ -108,7 +108,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_renderer = new QSvgRenderer(); QGraphicsScene *l_scene = m_config->graphicsView->scene(); m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); - if (QFile::exists(":/configgadget/images/TX.svg") && m_renderer->load(QString(":/configgadget/images/TX.svg")) && m_renderer->isValid()) + if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer->load(QString(":/configgadget/images/TX2.svg")) && m_renderer->isValid()) { l_scene->clear(); // Deletes all items contained in the scene as well. diff --git a/ground/openpilotgcs/src/plugins/config/images/TX2.svg b/ground/openpilotgcs/src/plugins/config/images/TX2.svg new file mode 100644 index 000000000..a6c8a533a --- /dev/null +++ b/ground/openpilotgcs/src/plugins/config/images/TX2.svg @@ -0,0 +1,2852 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 81fea31b34467085204e5a805d86689825146e6d Mon Sep 17 00:00:00 2001 From: zedamota Date: Fri, 27 Jan 2012 17:54:14 +0000 Subject: [PATCH 55/72] made the input wizard background transparent --- .../openpilotgcs/src/plugins/config/configinputwidget.cpp | 1 - ground/openpilotgcs/src/plugins/config/input.ui | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 2f3b83754..3e8cf0c87 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -107,7 +107,6 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_config->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); m_renderer = new QSvgRenderer(); QGraphicsScene *l_scene = m_config->graphicsView->scene(); - m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer->load(QString(":/configgadget/images/TX2.svg")) && m_renderer->isValid()) { l_scene->clear(); // Deletes all items contained in the scene as well. diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 2fac45ec9..30c0cd80d 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -90,7 +90,11 @@ - + + + background:transparent + + From 0a1645587c39e526eecea6dfc4b196942fbb079a Mon Sep 17 00:00:00 2001 From: David Ankers Date: Sun, 29 Jan 2012 04:30:43 +1100 Subject: [PATCH 56/72] Update deluxe dials --- .../Dials/deluxe/lineardial-horizontal.svg | 135 +++++------ artwork/Dials/deluxe/lineardial-vertical.svg | 219 ++++++++++-------- .../dials/deluxe/lineardial-horizontal.svg | 135 +++++------ .../dials/deluxe/lineardial-vertical.svg | 219 ++++++++++-------- 4 files changed, 352 insertions(+), 356 deletions(-) mode change 100644 => 100755 artwork/Dials/deluxe/lineardial-horizontal.svg mode change 100644 => 100755 artwork/Dials/deluxe/lineardial-vertical.svg mode change 100644 => 100755 ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-horizontal.svg mode change 100644 => 100755 ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-vertical.svg diff --git a/artwork/Dials/deluxe/lineardial-horizontal.svg b/artwork/Dials/deluxe/lineardial-horizontal.svg old mode 100644 new mode 100755 index 2f6f71b17..e37172ec0 --- a/artwork/Dials/deluxe/lineardial-horizontal.svg +++ b/artwork/Dials/deluxe/lineardial-horizontal.svg @@ -14,8 +14,8 @@ height="70.597504" id="svg10068" version="1.1" - inkscape:version="0.48.1 " - sodipodi:docname="lineardial-horizontal.svg" + inkscape:version="0.48.2 r9819" + sodipodi:docname="lineardial-horizontal-old2.svg" inkscape:export-filename="H:\Documents\Hobbies\W433\My Gauges\vbat-001.png" inkscape:export-xdpi="103.61" inkscape:export-ydpi="103.61" @@ -25,15 +25,19 @@ + offset="0.31684026" + style="stop-color:#a3a3a3;stop-opacity:1;" /> + @@ -57,15 +61,11 @@ + style="stop-color:#8a8a8a;stop-opacity:1;" /> - + id="stop4391" /> @@ -237,15 +237,15 @@ + style="stop-color:#676767;stop-opacity:1;" /> + style="stop-color:#7d7d7d;stop-opacity:1;" /> @@ -425,46 +425,34 @@ - + offset="0" + style="stop-color:#ffc001;stop-opacity:1;" /> - - + offset="0" + style="stop-color:#e60000;stop-opacity:1;" /> @@ -687,7 +675,7 @@ x2="87.074203" y2="168.83261" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,0.99999995,-0.99999975,0,-11.23354,-270.8763)" /> + gradientTransform="matrix(0,1.0110991,-1.0062411,0,-10.360287,-272.19756)" /> + gradientTransform="matrix(0,1.0224134,-1.0048488,0,-10.554719,-273.54528)" /> + gradientTransform="matrix(0,1,-1.0055415,0,-10.459485,-270.8763)" /> + transform="translate(-368.2988,-507.08981)"> @@ -1225,17 +1212,16 @@ id="layer5" inkscape:label="Green Zone" style="display:inline" - transform="translate(-140.85549,-141.35611)" - sodipodi:insensitive="true"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="matrix(0,1,-1,0,0,0)" + ry="2.5494981" + rx="1.9392394" /> + + + + + style="stop-color:#656565;stop-opacity:1;" /> + style="stop-color:#757575;stop-opacity:1;" /> @@ -83,15 +94,19 @@ + style="stop-color:#9c9c9c;stop-opacity:0;" /> + id="stop3921" + offset="0.359375" + style="stop-color:#6c6c6c;stop-opacity:0.88793105;" /> + + style="stop-color:#9c9c9c;stop-opacity:0;" /> @@ -215,46 +230,34 @@ - + offset="0" + style="stop-color:#ffc001;stop-opacity:1;" /> - - + offset="0" + style="stop-color:#e60000;stop-opacity:1;" /> @@ -475,7 +478,8 @@ y1="132.84332" x2="-58.661255" y2="169.46072" - gradientUnits="userSpaceOnUse" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0045664,0,0,0.98072534,3.8285685,3.8328979)" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0048708,0,0,1.0000284,3.816285,2.2385824)" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0057658,0,0,0.99502095,3.8176724,2.8357789)" /> + y2="412.00528" + gradientTransform="matrix(1,0,0,0.98663274,0,3.8538758)" /> + x2="-136.75557" + y2="74.015358" /> + image/svg+xml - + Edouard Lafargue @@ -779,8 +796,7 @@ inkscape:label="Dark background" id="g2932" inkscape:groupmode="layer" - transform="translate(-357.06525,-236.21351)" - sodipodi:insensitive="true"> + transform="translate(-357.06525,-236.21351)"> @@ -789,39 +805,39 @@ style="fill:url(#linearGradient5344);fill-opacity:1;stroke:none" id="rect2936" width="318.58304" - height="46.756046" + height="46.131046" x="-556.79657" - y="358.44128" - ry="3.4504199" + y="357.50378" + ry="3.4042974" inkscape:export-filename="H:\Documents\Hobbies\W433\g9905.png" inkscape:export-xdpi="88.809998" inkscape:export-ydpi="88.809998" /> - + style="fill:url(#linearGradient3900);fill-opacity:1;stroke:none" /> + + transform="translate(-129.62194,129.52019)"> + style="display:inline" + transform="translate(-129.62194,129.52019)"> + transform="translate(-129.62194,129.52019)"> + width="34.173222" + height="5.9349518" + x="136.20108" + y="-114.68695" + inkscape:label="#rect5246" + ry="2.4981377" /> + transform="translate(-129.62194,129.52019)"> diff --git a/ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-horizontal.svg b/ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-horizontal.svg old mode 100644 new mode 100755 index 2f6f71b17..e37172ec0 --- a/ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-horizontal.svg +++ b/ground/openpilotgcs/share/openpilotgcs/dials/deluxe/lineardial-horizontal.svg @@ -14,8 +14,8 @@ height="70.597504" id="svg10068" version="1.1" - inkscape:version="0.48.1 " - sodipodi:docname="lineardial-horizontal.svg" + inkscape:version="0.48.2 r9819" + sodipodi:docname="lineardial-horizontal-old2.svg" inkscape:export-filename="H:\Documents\Hobbies\W433\My Gauges\vbat-001.png" inkscape:export-xdpi="103.61" inkscape:export-ydpi="103.61" @@ -25,15 +25,19 @@ + offset="0.31684026" + style="stop-color:#a3a3a3;stop-opacity:1;" /> + @@ -57,15 +61,11 @@ + style="stop-color:#8a8a8a;stop-opacity:1;" /> - + id="stop4391" /> @@ -237,15 +237,15 @@ + style="stop-color:#676767;stop-opacity:1;" /> + style="stop-color:#7d7d7d;stop-opacity:1;" /> @@ -425,46 +425,34 @@ - + offset="0" + style="stop-color:#ffc001;stop-opacity:1;" /> - - + offset="0" + style="stop-color:#e60000;stop-opacity:1;" /> @@ -687,7 +675,7 @@ x2="87.074203" y2="168.83261" gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0,0.99999995,-0.99999975,0,-11.23354,-270.8763)" /> + gradientTransform="matrix(0,1.0110991,-1.0062411,0,-10.360287,-272.19756)" /> + gradientTransform="matrix(0,1.0224134,-1.0048488,0,-10.554719,-273.54528)" /> + gradientTransform="matrix(0,1,-1.0055415,0,-10.459485,-270.8763)" /> + transform="translate(-368.2988,-507.08981)"> @@ -1225,17 +1212,16 @@ id="layer5" inkscape:label="Green Zone" style="display:inline" - transform="translate(-140.85549,-141.35611)" - sodipodi:insensitive="true"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="translate(-140.85549,-141.35611)"> + transform="matrix(0,1,-1,0,0,0)" + ry="2.5494981" + rx="1.9392394" /> + + + + + style="stop-color:#656565;stop-opacity:1;" /> + style="stop-color:#757575;stop-opacity:1;" /> @@ -83,15 +94,19 @@ + style="stop-color:#9c9c9c;stop-opacity:0;" /> + id="stop3921" + offset="0.359375" + style="stop-color:#6c6c6c;stop-opacity:0.88793105;" /> + + style="stop-color:#9c9c9c;stop-opacity:0;" /> @@ -215,46 +230,34 @@ - + offset="0" + style="stop-color:#ffc001;stop-opacity:1;" /> - - + offset="0" + style="stop-color:#e60000;stop-opacity:1;" /> @@ -475,7 +478,8 @@ y1="132.84332" x2="-58.661255" y2="169.46072" - gradientUnits="userSpaceOnUse" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0045664,0,0,0.98072534,3.8285685,3.8328979)" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0048708,0,0,1.0000284,3.816285,2.2385824)" /> + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0057658,0,0,0.99502095,3.8176724,2.8357789)" /> + y2="412.00528" + gradientTransform="matrix(1,0,0,0.98663274,0,3.8538758)" /> + x2="-136.75557" + y2="74.015358" /> + image/svg+xml - + Edouard Lafargue @@ -779,8 +796,7 @@ inkscape:label="Dark background" id="g2932" inkscape:groupmode="layer" - transform="translate(-357.06525,-236.21351)" - sodipodi:insensitive="true"> + transform="translate(-357.06525,-236.21351)"> @@ -789,39 +805,39 @@ style="fill:url(#linearGradient5344);fill-opacity:1;stroke:none" id="rect2936" width="318.58304" - height="46.756046" + height="46.131046" x="-556.79657" - y="358.44128" - ry="3.4504199" + y="357.50378" + ry="3.4042974" inkscape:export-filename="H:\Documents\Hobbies\W433\g9905.png" inkscape:export-xdpi="88.809998" inkscape:export-ydpi="88.809998" /> - + style="fill:url(#linearGradient3900);fill-opacity:1;stroke:none" /> + + transform="translate(-129.62194,129.52019)"> + style="display:inline" + transform="translate(-129.62194,129.52019)"> + transform="translate(-129.62194,129.52019)"> + width="34.173222" + height="5.9349518" + x="136.20108" + y="-114.68695" + inkscape:label="#rect5246" + ry="2.4981377" /> + transform="translate(-129.62194,129.52019)"> From e1d471dc63281fc6e4e820da4f63d135b3b2f4ad Mon Sep 17 00:00:00 2001 From: zedamota Date: Sat, 28 Jan 2012 21:25:38 +0000 Subject: [PATCH 57/72] Fixes scopegadget loading issues with Qt versions > 4.7.4 --- ground/openpilotgcs/src/libs/qwt/qwtconfig.pri | 8 ++++++++ ground/openpilotgcs/src/libs/qwt/src/qwt_global.h | 7 ++----- ground/openpilotgcs/src/libs/qwt/src/src.pro | 9 +++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri b/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri index 82754c682..bcc921911 100644 --- a/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri +++ b/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri @@ -30,6 +30,14 @@ VVERSION = $$[QT_VERSION] CONFIG += QwtPlot +###################################################################### +# Build the static/shared libraries. +# If QwtDll is enabled, a shared library is built, otherwise +# it will be a static library. +###################################################################### + +QWT_CONFIG += QwtDll + ###################################################################### # QwtWidgets enables all classes, that are needed to use the all other # widgets (sliders, dials, ...), beside QwtPlot. diff --git a/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h b/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h index baf371f49..5fba57e27 100644 --- a/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h +++ b/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h @@ -29,17 +29,14 @@ #pragma warning(disable: 4660) #endif // _MSC_VER -#ifdef QWT_DLL #if defined(QWT_MAKEDLL) // create a Qwt DLL library -#define QWT_EXPORT __declspec(dllexport) +#define QWT_EXPORT Q_DECL_EXPORT #define QWT_TEMPLATEDLL #else // use a Qwt DLL library -#define QWT_EXPORT __declspec(dllimport) +#define QWT_EXPORT Q_DECL_IMPORT #endif -#endif // QWT_DLL - #endif // Q_WS_WIN #ifndef QWT_EXPORT diff --git a/ground/openpilotgcs/src/libs/qwt/src/src.pro b/ground/openpilotgcs/src/libs/qwt/src/src.pro index 133f92b0f..15c1d04e5 100644 --- a/ground/openpilotgcs/src/libs/qwt/src/src.pro +++ b/ground/openpilotgcs/src/libs/qwt/src/src.pro @@ -4,9 +4,14 @@ DEFINES += QWT_LIBRARY include(../../../openpilotgcslibrary.pri) include( ../qwtconfig.pri ) -#VVERSION = $$[QT_VERSION] - +contains(QWT_CONFIG, QwtDll) { + CONFIG += dll + win32|symbian: DEFINES += QT_DLL QWT_DLL QWT_MAKEDLL +} +else { + CONFIG += staticlib +} HEADERS += \ qwt.h \ qwt_abstract_scale_draw.h \ From fdcea011000710fc5ed71c8e43726896f1f9906f Mon Sep 17 00:00:00 2001 From: naiiawah Date: Thu, 5 Jan 2012 02:10:05 -0700 Subject: [PATCH 58/72] numberOfDevices could be left unitialized if sendData or receiveData fail in findDevices or if no one ever calls findDevices. Added init of var. --- ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp index 961103d22..f30fca1b5 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp @@ -37,6 +37,7 @@ DFUObject::DFUObject(bool _debug,bool _use_serial,QString portname): debug(_debug),use_serial(_use_serial),mready(true) { info = NULL; + numberOfDevices = 0; qRegisterMetaType("Status"); From 3d896ffaf500dffe33e58fea5d09384667f763ae Mon Sep 17 00:00:00 2001 From: zedamota Date: Sat, 28 Jan 2012 21:25:38 +0000 Subject: [PATCH 59/72] Fixes scopegadget loading issues with Qt versions > 4.7.4 --- ground/openpilotgcs/src/libs/qwt/qwtconfig.pri | 8 ++++++++ ground/openpilotgcs/src/libs/qwt/src/qwt_global.h | 7 ++----- ground/openpilotgcs/src/libs/qwt/src/src.pro | 9 +++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri b/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri index 82754c682..bcc921911 100644 --- a/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri +++ b/ground/openpilotgcs/src/libs/qwt/qwtconfig.pri @@ -30,6 +30,14 @@ VVERSION = $$[QT_VERSION] CONFIG += QwtPlot +###################################################################### +# Build the static/shared libraries. +# If QwtDll is enabled, a shared library is built, otherwise +# it will be a static library. +###################################################################### + +QWT_CONFIG += QwtDll + ###################################################################### # QwtWidgets enables all classes, that are needed to use the all other # widgets (sliders, dials, ...), beside QwtPlot. diff --git a/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h b/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h index baf371f49..5fba57e27 100644 --- a/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h +++ b/ground/openpilotgcs/src/libs/qwt/src/qwt_global.h @@ -29,17 +29,14 @@ #pragma warning(disable: 4660) #endif // _MSC_VER -#ifdef QWT_DLL #if defined(QWT_MAKEDLL) // create a Qwt DLL library -#define QWT_EXPORT __declspec(dllexport) +#define QWT_EXPORT Q_DECL_EXPORT #define QWT_TEMPLATEDLL #else // use a Qwt DLL library -#define QWT_EXPORT __declspec(dllimport) +#define QWT_EXPORT Q_DECL_IMPORT #endif -#endif // QWT_DLL - #endif // Q_WS_WIN #ifndef QWT_EXPORT diff --git a/ground/openpilotgcs/src/libs/qwt/src/src.pro b/ground/openpilotgcs/src/libs/qwt/src/src.pro index 133f92b0f..15c1d04e5 100644 --- a/ground/openpilotgcs/src/libs/qwt/src/src.pro +++ b/ground/openpilotgcs/src/libs/qwt/src/src.pro @@ -4,9 +4,14 @@ DEFINES += QWT_LIBRARY include(../../../openpilotgcslibrary.pri) include( ../qwtconfig.pri ) -#VVERSION = $$[QT_VERSION] - +contains(QWT_CONFIG, QwtDll) { + CONFIG += dll + win32|symbian: DEFINES += QT_DLL QWT_DLL QWT_MAKEDLL +} +else { + CONFIG += staticlib +} HEADERS += \ qwt.h \ qwt_abstract_scale_draw.h \ From c5a2afcc2c91657b79c0815381a955cd05845f38 Mon Sep 17 00:00:00 2001 From: zedamota Date: Fri, 27 Jan 2012 17:54:14 +0000 Subject: [PATCH 60/72] made the input wizard background transparent --- .../openpilotgcs/src/plugins/config/configinputwidget.cpp | 1 - ground/openpilotgcs/src/plugins/config/input.ui | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 2f3b83754..3e8cf0c87 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -107,7 +107,6 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_config->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); m_renderer = new QSvgRenderer(); QGraphicsScene *l_scene = m_config->graphicsView->scene(); - m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer->load(QString(":/configgadget/images/TX2.svg")) && m_renderer->isValid()) { l_scene->clear(); // Deletes all items contained in the scene as well. diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 2fac45ec9..30c0cd80d 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -90,7 +90,11 @@ - + + + background:transparent + + From 6c030482a5e0025687d3be2d4ac34e5498099adc Mon Sep 17 00:00:00 2001 From: David Ankers Date: Mon, 30 Jan 2012 04:51:11 +1100 Subject: [PATCH 61/72] Fix 64 bit compile --- ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp index d4913ed97..7b3da6d31 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp +++ b/ground/openpilotgcs/src/plugins/notify/notifytablemodel.cpp @@ -209,7 +209,7 @@ bool NotifyTableModel::dropMimeData( const QMimeData * data, Qt::DropAction acti int rows = beginRow; // read next item from input MIME and drop into the table line by line while(!stream.atEnd()) { - qint32 ptr; + quintptr ptr; stream >> ptr; NotificationItem* item = reinterpret_cast(ptr); int dragged = _list.indexOf(item); @@ -247,7 +247,7 @@ QMimeData* NotifyTableModel::mimeData(const QModelIndexList& indexes) const int rows = 0; foreach (const QModelIndex& index, indexes) { if (!index.column()) { - qint32 item = reinterpret_cast(_list.at(index.row())); + quintptr item = reinterpret_cast(_list.at(index.row())); stream << item; ++rows; } From 01c910cd2b3a2dd607812301f6b3a7eba120f4f8 Mon Sep 17 00:00:00 2001 From: zedamota Date: Sun, 29 Jan 2012 21:49:11 +0000 Subject: [PATCH 62/72] OP-616 Fixes wrong HW version being displayed. --- ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp | 2 +- .../openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp index cf4315596..f1d28ec90 100644 --- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp @@ -111,7 +111,7 @@ void deviceWidget::populate() // display a nice icon: myDevice->gVDevice->scene()->clear(); myDevice->lblDevName->setText(deviceDescriptorStruct::idToBoardName(id)); - myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x0011, 16)); + myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x00FF, 16)); devicePic = new QGraphicsSvgItem(); devicePic->setSharedRenderer(new QSvgRenderer()); diff --git a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp index fcde00125..9cb351bc1 100644 --- a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp @@ -73,7 +73,7 @@ void runningDeviceWidget::populate() myDevice->lblDeviceID->setText(QString("Device ID: ") + QString::number(id, 16)); myDevice->lblBoardName->setText(deviceDescriptorStruct::idToBoardName(id)); - myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x0011, 16)); + myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x00FF, 16)); qDebug()<<"CRC"<getFirmwareCRC(); myDevice->lblCRC->setText(QString(tr("Firmware CRC: "))+QVariant(utilMngr->getFirmwareCRC()).toString()); // DeviceID tells us what sort of HW we have detected: From 911f8fde033dc89d030700e2a4e51c7511efa831 Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Mon, 2 Jan 2012 14:21:01 +0200 Subject: [PATCH 63/72] Add "Reset To Defaults" button to Stabilization configuration tab Also add tootips to Reset/Apply/Save buttons. --- .../config/configstabilizationwidget.cpp | 50 +- .../config/configstabilizationwidget.h | 4 +- .../src/plugins/config/stabilization.ui | 1601 +++++++++-------- 3 files changed, 863 insertions(+), 792 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp index cbe554f4e..69b0427e3 100644 --- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp @@ -42,8 +42,7 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa m_stabilization = new Ui_StabilizationWidget(); m_stabilization->setupUi(this); - - setupButtons(m_stabilization->saveStabilizationToRAM,m_stabilization->saveStabilizationToSD); + setupButtons(m_stabilization->saveStabilizationToRAM, m_stabilization->saveStabilizationToSD); addUAVObject("StabilizationSettings"); @@ -71,8 +70,6 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa connect(m_stabilization->pitchKi, SIGNAL(valueChanged(double)), this, SLOT(updatePitchKI(double))); connect(m_stabilization->pitchILimit, SIGNAL(valueChanged(double)), this, SLOT(updatePitchILimit(double))); - // Connect the help button - connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp())); addWidget(m_stabilization->rateRollKp); addWidget(m_stabilization->rateRollKi); addWidget(m_stabilization->rateRollILimit); @@ -102,6 +99,9 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa addWidget(m_stabilization->maximumYaw); addWidget(m_stabilization->lowThrottleZeroIntegral); + // Connect buttons + connect(m_stabilization->stabilizationResetToDefaults, SIGNAL(clicked()), this, SLOT(resetToDefaults())); + connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp())); } ConfigStabilizationWidget::~ConfigStabilizationWidget() @@ -195,21 +195,17 @@ void ConfigStabilizationWidget::updatePitchILimit(double val) } } - /******************************* * Stabilization Settings *****************************/ /** - Request stabilization settings from the board + * Refresh UI with new settings of StabilizationSettings object + * (either from active configuration or just loaded defaults + * to be applied or saved) */ -void ConfigStabilizationWidget::refreshWidgetsValues() +void ConfigStabilizationWidget::refreshUIValues(StabilizationSettings::DataFields &stabData) { - bool dirty=isDirty(); - // Not needed anymore as this slot is only called whenever we get - // a signal that the object was just updated - // stabSettings->requestUpdate(); - StabilizationSettings::DataFields stabData = stabSettings->getData(); // Now fill in all the fields, this is fairly tedious: m_stabilization->rateRollKp->setValue(stabData.RollRatePID[StabilizationSettings::ROLLRATEPID_KP]); m_stabilization->rateRollKi->setValue(stabData.RollRatePID[StabilizationSettings::ROLLRATEPID_KI]); @@ -247,15 +243,25 @@ void ConfigStabilizationWidget::refreshWidgetsValues() m_stabilization->maximumPitch->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH]); m_stabilization->maximumYaw->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW]); m_stabilization->lowThrottleZeroIntegral->setChecked(stabData.LowThrottleZeroIntegral==StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE ? true : false); - - setDirty(dirty); } +/** + Request stabilization settings from the board + */ +void ConfigStabilizationWidget::refreshWidgetsValues() +{ + bool dirty=isDirty(); + // Not needed anymore as this slot is only called whenever we get + // a signal that the object was just updated + // stabSettings->requestUpdate(); + StabilizationSettings::DataFields stabData = stabSettings->getData(); + refreshUIValues(stabData); + setDirty(dirty); +} /** Send telemetry settings to the board */ - void ConfigStabilizationWidget::updateObjectsFromWidgets() { StabilizationSettings::DataFields stabData = stabSettings->getData(); @@ -298,7 +304,6 @@ void ConfigStabilizationWidget::updateObjectsFromWidgets() stabData.LowThrottleZeroIntegral = (m_stabilization->lowThrottleZeroIntegral->isChecked() ? StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE :StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_FALSE); - stabSettings->setData(stabData); // this is atomic } @@ -311,9 +316,16 @@ void ConfigStabilizationWidget::realtimeUpdateToggle(bool state) } } -void ConfigStabilizationWidget::openHelp() +void ConfigStabilizationWidget::resetToDefaults() { - - QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Stabilization+panel", QUrl::StrictMode) ); + StabilizationSettings stabDefaults; + StabilizationSettings::DataFields defaults = stabDefaults.getData(); + bool dirty=isDirty(); + refreshUIValues(defaults); + setDirty(dirty); } +void ConfigStabilizationWidget::openHelp() +{ + QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Stabilization+panel", QUrl::StrictMode) ); +} diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h index e512c5097..b502dd25e 100644 --- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h @@ -49,11 +49,13 @@ private: Ui_StabilizationWidget *m_stabilization; StabilizationSettings* stabSettings; QTimer updateTimer; + void refreshUIValues(StabilizationSettings::DataFields &stabData); private slots: virtual void refreshWidgetsValues(); void updateObjectsFromWidgets(); void realtimeUpdateToggle(bool); + void resetToDefaults(); void openHelp(); void updateRateRollKP(double); @@ -73,4 +75,4 @@ private slots: void updatePitchILimit(double); }; -#endif // ConfigStabilizationWidget_H +#endif // CONFIGSTABILIZATIONWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/stabilization.ui b/ground/openpilotgcs/src/plugins/config/stabilization.ui index 5c2de727e..f99b35b94 100644 --- a/ground/openpilotgcs/src/plugins/config/stabilization.ui +++ b/ground/openpilotgcs/src/plugins/config/stabilization.ui @@ -1,772 +1,829 @@ - - - StabilizationWidget - - - - 0 - 0 - 683 - 685 - - - - Form - - - - - - - 0 - 1 - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 665 - 627 - - - - - 0 - 0 - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 150 - - - - Rate Stabilization Coefficients (Inner Loop) - - - - - - Kp - - - Qt::AlignCenter - - - - - - - Ki - - - Qt::AlignCenter - - - - - - - ILimit - - - Qt::AlignCenter - - - - - - - Roll - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - - - 6 - - - 0.000100000000000 - - - - - - - I factor for rate stabilization is usually very low or even zero. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - If checked, the Roll and Pitch factors will be identical. -When you change one, the other is updated. - - - Link - - - - - - - Pitch - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - - - 6 - - - 0.000100000000000 - - - - - - - I factor for rate stabilization is usually very low or even zero. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - Yaw - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - -You can usually go for higher values for Yaw factors. - - - 6 - - - 0.000100000000000 - - - - - - - As a rule of thumb, you can set YawRate Ki at roughly the same -value as YawRate Kp. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - - 0 - 0 - - - - - 0 - 150 - - - - Attitude Stabization Coefficients (Outer Loop) - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - Kp - - - Qt::AlignCenter - - - - - - - Ki - - - Qt::AlignCenter - - - - - - - ILimit - - - Qt::AlignCenter - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Yaw - - - - - - - Pitch - - - - - - - Roll - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - If checked, the Roll and Pitch factors will be identical. -When you change one, the other is updated. - - - Link - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Stick range and limits - - - - QLayout::SetMinAndMaxSize - - - - - Roll - - - Qt::AlignCenter - - - - - - - Pitch - - - Qt::AlignCenter - - - - - - - Yaw - - - Qt::AlignCenter - - - - - - - 180 - - - - - - - 180 - - - - - - - 180 - - - - - - - - 150 - 0 - - - - - 50 - false - - - - Full stick angle (deg) - - - - - - - - 150 - 0 - - - - - 50 - false - - - - Full stick rate (deg/s) - - - - - - - 500 - - - - - - - 500 - - - - - - - 500 - - - - - - - - 150 - 0 - - - - - 50 - false - - - - - - - Maximum rate in attitude mode (deg/s) - - - - - - - 500 - - - - - - - 500 - - - - - - - 500 - - - - - - - - - - Zero the integral when throttle is low - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - - - If you check this, the GCS will udpate the stabilization factors -automatically every 300ms, which will help for fast tuning. - - - Update in real time - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - - - - - :/core/images/helpicon.svg:/core/images/helpicon.svg - - - - 32 - 32 - - - - true - - - - - - - Apply - - - - - - - Save - - - - - - - - - - - - + + + StabilizationWidget + + + + 0 + 0 + 683 + 685 + + + + Form + + + + + + + 0 + 1 + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 665 + 627 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 150 + + + + Rate Stabilization Coefficients (Inner Loop) + + + + + + Kp + + + Qt::AlignCenter + + + + + + + Ki + + + Qt::AlignCenter + + + + + + + ILimit + + + Qt::AlignCenter + + + + + + + Roll + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + + + 6 + + + 0.000100000000000 + + + + + + + I factor for rate stabilization is usually very low or even zero. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + If checked, the Roll and Pitch factors will be identical. +When you change one, the other is updated. + + + Link + + + + + + + Pitch + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + + + 6 + + + 0.000100000000000 + + + + + + + I factor for rate stabilization is usually very low or even zero. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + Yaw + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + +You can usually go for higher values for Yaw factors. + + + 6 + + + 0.000100000000000 + + + + + + + As a rule of thumb, you can set YawRate Ki at roughly the same +value as YawRate Kp. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + + + + + 0 + 0 + + + + + 0 + 150 + + + + Attitude Stabization Coefficients (Outer Loop) + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + Kp + + + Qt::AlignCenter + + + + + + + Ki + + + Qt::AlignCenter + + + + + + + ILimit + + + Qt::AlignCenter + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Yaw + + + + + + + Pitch + + + + + + + Roll + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + If checked, the Roll and Pitch factors will be identical. +When you change one, the other is updated. + + + Link + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Stick range and limits + + + + QLayout::SetMinAndMaxSize + + + + + Roll + + + Qt::AlignCenter + + + + + + + Pitch + + + Qt::AlignCenter + + + + + + + Yaw + + + Qt::AlignCenter + + + + + + + 180 + + + + + + + 180 + + + + + + + 180 + + + + + + + + 150 + 0 + + + + + 50 + false + + + + Full stick angle (deg) + + + + + + + + 150 + 0 + + + + + 50 + false + + + + Full stick rate (deg/s) + + + + + + + 500 + + + + + + + 500 + + + + + + + 500 + + + + + + + + 150 + 0 + + + + + 50 + false + + + + + + + Maximum rate in attitude mode (deg/s) + + + + + + + 500 + + + + + + + 500 + + + + + + + 500 + + + + + + + + + + Zero the integral when throttle is low + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + + + If you check this, the GCS will udpate the stabilization factors +automatically every 300ms, which will help for fast tuning. + + + Update in real time + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + + + + :/core/images/helpicon.svg:/core/images/helpicon.svg + + + + 32 + 32 + + + + true + + + + + + + Load default Stabilization settings + +Loaded settings are not applied automatically. You have to click the +Apply or Save button afterwards. + + + Reset To Defaults + + + + + + + Send settings to the board but do not save to the non-volatile memory + + + Apply + + + + + + + Send settings to the board and save to the non-volatile memory + + + Save + + + + + + + + + scrollArea + rateRollKp + rateRollKi + rateRollILimit + linkRateRP + ratePitchKp + ratePitchKi + ratePitchILimit + rateYawKp + rateYawKi + rateYawILimit + rollKp + rollKi + rollILimit + linkAttitudeRP + pitchKp + pitchKi + pitchILimit + yawKp + yawKi + yawILimit + rollMax + pitchMax + yawMax + manualRoll + manualPitch + manualYaw + maximumRoll + maximumPitch + maximumYaw + lowThrottleZeroIntegral + realTimeUpdates + stabilizationHelp + stabilizationResetToDefaults + saveStabilizationToRAM + saveStabilizationToSD + + + + + + From 369629ad342550c89747d4a133b612c267f6117b Mon Sep 17 00:00:00 2001 From: Oleg Semyonov Date: Mon, 2 Jan 2012 14:21:01 +0200 Subject: [PATCH 64/72] Add "Reset To Defaults" button to Stabilization configuration tab Also add tootips to Reset/Apply/Save buttons. --- .../config/configstabilizationwidget.cpp | 50 +- .../config/configstabilizationwidget.h | 4 +- .../src/plugins/config/stabilization.ui | 1601 +++++++++-------- 3 files changed, 863 insertions(+), 792 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp index cbe554f4e..69b0427e3 100644 --- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.cpp @@ -42,8 +42,7 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa m_stabilization = new Ui_StabilizationWidget(); m_stabilization->setupUi(this); - - setupButtons(m_stabilization->saveStabilizationToRAM,m_stabilization->saveStabilizationToSD); + setupButtons(m_stabilization->saveStabilizationToRAM, m_stabilization->saveStabilizationToSD); addUAVObject("StabilizationSettings"); @@ -71,8 +70,6 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa connect(m_stabilization->pitchKi, SIGNAL(valueChanged(double)), this, SLOT(updatePitchKI(double))); connect(m_stabilization->pitchILimit, SIGNAL(valueChanged(double)), this, SLOT(updatePitchILimit(double))); - // Connect the help button - connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp())); addWidget(m_stabilization->rateRollKp); addWidget(m_stabilization->rateRollKi); addWidget(m_stabilization->rateRollILimit); @@ -102,6 +99,9 @@ ConfigStabilizationWidget::ConfigStabilizationWidget(QWidget *parent) : ConfigTa addWidget(m_stabilization->maximumYaw); addWidget(m_stabilization->lowThrottleZeroIntegral); + // Connect buttons + connect(m_stabilization->stabilizationResetToDefaults, SIGNAL(clicked()), this, SLOT(resetToDefaults())); + connect(m_stabilization->stabilizationHelp, SIGNAL(clicked()), this, SLOT(openHelp())); } ConfigStabilizationWidget::~ConfigStabilizationWidget() @@ -195,21 +195,17 @@ void ConfigStabilizationWidget::updatePitchILimit(double val) } } - /******************************* * Stabilization Settings *****************************/ /** - Request stabilization settings from the board + * Refresh UI with new settings of StabilizationSettings object + * (either from active configuration or just loaded defaults + * to be applied or saved) */ -void ConfigStabilizationWidget::refreshWidgetsValues() +void ConfigStabilizationWidget::refreshUIValues(StabilizationSettings::DataFields &stabData) { - bool dirty=isDirty(); - // Not needed anymore as this slot is only called whenever we get - // a signal that the object was just updated - // stabSettings->requestUpdate(); - StabilizationSettings::DataFields stabData = stabSettings->getData(); // Now fill in all the fields, this is fairly tedious: m_stabilization->rateRollKp->setValue(stabData.RollRatePID[StabilizationSettings::ROLLRATEPID_KP]); m_stabilization->rateRollKi->setValue(stabData.RollRatePID[StabilizationSettings::ROLLRATEPID_KI]); @@ -247,15 +243,25 @@ void ConfigStabilizationWidget::refreshWidgetsValues() m_stabilization->maximumPitch->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_PITCH]); m_stabilization->maximumYaw->setValue(stabData.MaximumRate[StabilizationSettings::MAXIMUMRATE_YAW]); m_stabilization->lowThrottleZeroIntegral->setChecked(stabData.LowThrottleZeroIntegral==StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE ? true : false); - - setDirty(dirty); } +/** + Request stabilization settings from the board + */ +void ConfigStabilizationWidget::refreshWidgetsValues() +{ + bool dirty=isDirty(); + // Not needed anymore as this slot is only called whenever we get + // a signal that the object was just updated + // stabSettings->requestUpdate(); + StabilizationSettings::DataFields stabData = stabSettings->getData(); + refreshUIValues(stabData); + setDirty(dirty); +} /** Send telemetry settings to the board */ - void ConfigStabilizationWidget::updateObjectsFromWidgets() { StabilizationSettings::DataFields stabData = stabSettings->getData(); @@ -298,7 +304,6 @@ void ConfigStabilizationWidget::updateObjectsFromWidgets() stabData.LowThrottleZeroIntegral = (m_stabilization->lowThrottleZeroIntegral->isChecked() ? StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_TRUE :StabilizationSettings::LOWTHROTTLEZEROINTEGRAL_FALSE); - stabSettings->setData(stabData); // this is atomic } @@ -311,9 +316,16 @@ void ConfigStabilizationWidget::realtimeUpdateToggle(bool state) } } -void ConfigStabilizationWidget::openHelp() +void ConfigStabilizationWidget::resetToDefaults() { - - QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Stabilization+panel", QUrl::StrictMode) ); + StabilizationSettings stabDefaults; + StabilizationSettings::DataFields defaults = stabDefaults.getData(); + bool dirty=isDirty(); + refreshUIValues(defaults); + setDirty(dirty); } +void ConfigStabilizationWidget::openHelp() +{ + QDesktopServices::openUrl( QUrl("http://wiki.openpilot.org/display/Doc/Stabilization+panel", QUrl::StrictMode) ); +} diff --git a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h index e512c5097..b502dd25e 100644 --- a/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h +++ b/ground/openpilotgcs/src/plugins/config/configstabilizationwidget.h @@ -49,11 +49,13 @@ private: Ui_StabilizationWidget *m_stabilization; StabilizationSettings* stabSettings; QTimer updateTimer; + void refreshUIValues(StabilizationSettings::DataFields &stabData); private slots: virtual void refreshWidgetsValues(); void updateObjectsFromWidgets(); void realtimeUpdateToggle(bool); + void resetToDefaults(); void openHelp(); void updateRateRollKP(double); @@ -73,4 +75,4 @@ private slots: void updatePitchILimit(double); }; -#endif // ConfigStabilizationWidget_H +#endif // CONFIGSTABILIZATIONWIDGET_H diff --git a/ground/openpilotgcs/src/plugins/config/stabilization.ui b/ground/openpilotgcs/src/plugins/config/stabilization.ui index 5c2de727e..f99b35b94 100644 --- a/ground/openpilotgcs/src/plugins/config/stabilization.ui +++ b/ground/openpilotgcs/src/plugins/config/stabilization.ui @@ -1,772 +1,829 @@ - - - StabilizationWidget - - - - 0 - 0 - 683 - 685 - - - - Form - - - - - - - 0 - 1 - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 665 - 627 - - - - - 0 - 0 - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 150 - - - - Rate Stabilization Coefficients (Inner Loop) - - - - - - Kp - - - Qt::AlignCenter - - - - - - - Ki - - - Qt::AlignCenter - - - - - - - ILimit - - - Qt::AlignCenter - - - - - - - Roll - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - - - 6 - - - 0.000100000000000 - - - - - - - I factor for rate stabilization is usually very low or even zero. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - If checked, the Roll and Pitch factors will be identical. -When you change one, the other is updated. - - - Link - - - - - - - Pitch - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - - - 6 - - - 0.000100000000000 - - - - - - - I factor for rate stabilization is usually very low or even zero. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - Yaw - - - - - - - Slowly raise Kp until you start seeing clear oscillations when you fly. -Then lower the value by 20% or so. - -You can usually go for higher values for Yaw factors. - - - 6 - - - 0.000100000000000 - - - - - - - As a rule of thumb, you can set YawRate Ki at roughly the same -value as YawRate Kp. - - - 6 - - - 0.000100000000000 - - - - - - - 6 - - - 0.000100000000000 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - - 0 - 0 - - - - - 0 - 150 - - - - Attitude Stabization Coefficients (Outer Loop) - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - Kp - - - Qt::AlignCenter - - - - - - - Ki - - - Qt::AlignCenter - - - - - - - ILimit - - - Qt::AlignCenter - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. - - - - 6 - - - 0.100000000000000 - - - - - - - Yaw - - - - - - - Pitch - - - - - - - Roll - - - - - - - Ki can usually be almost identical to Kp. - - - 6 - - - 0.100000000000000 - - - - - - - ILimit can be equal to three to four times Ki, but you can adjust -depending on whether your airframe is well balanced, and your -flying style. - - - 6 - - - 0.100000000000000 - - - - - - - If checked, the Roll and Pitch factors will be identical. -When you change one, the other is updated. - - - Link - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Stick range and limits - - - - QLayout::SetMinAndMaxSize - - - - - Roll - - - Qt::AlignCenter - - - - - - - Pitch - - - Qt::AlignCenter - - - - - - - Yaw - - - Qt::AlignCenter - - - - - - - 180 - - - - - - - 180 - - - - - - - 180 - - - - - - - - 150 - 0 - - - - - 50 - false - - - - Full stick angle (deg) - - - - - - - - 150 - 0 - - - - - 50 - false - - - - Full stick rate (deg/s) - - - - - - - 500 - - - - - - - 500 - - - - - - - 500 - - - - - - - - 150 - 0 - - - - - 50 - false - - - - - - - Maximum rate in attitude mode (deg/s) - - - - - - - 500 - - - - - - - 500 - - - - - - - 500 - - - - - - - - - - Zero the integral when throttle is low - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - - - If you check this, the GCS will udpate the stabilization factors -automatically every 300ms, which will help for fast tuning. - - - Update in real time - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - - - - - :/core/images/helpicon.svg:/core/images/helpicon.svg - - - - 32 - 32 - - - - true - - - - - - - Apply - - - - - - - Save - - - - - - - - - - - - + + + StabilizationWidget + + + + 0 + 0 + 683 + 685 + + + + Form + + + + + + + 0 + 1 + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 665 + 627 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 150 + + + + Rate Stabilization Coefficients (Inner Loop) + + + + + + Kp + + + Qt::AlignCenter + + + + + + + Ki + + + Qt::AlignCenter + + + + + + + ILimit + + + Qt::AlignCenter + + + + + + + Roll + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + + + 6 + + + 0.000100000000000 + + + + + + + I factor for rate stabilization is usually very low or even zero. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + If checked, the Roll and Pitch factors will be identical. +When you change one, the other is updated. + + + Link + + + + + + + Pitch + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + + + 6 + + + 0.000100000000000 + + + + + + + I factor for rate stabilization is usually very low or even zero. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + Yaw + + + + + + + Slowly raise Kp until you start seeing clear oscillations when you fly. +Then lower the value by 20% or so. + +You can usually go for higher values for Yaw factors. + + + 6 + + + 0.000100000000000 + + + + + + + As a rule of thumb, you can set YawRate Ki at roughly the same +value as YawRate Kp. + + + 6 + + + 0.000100000000000 + + + + + + + 6 + + + 0.000100000000000 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + + + + + 0 + 0 + + + + + 0 + 150 + + + + Attitude Stabization Coefficients (Outer Loop) + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + Kp + + + Qt::AlignCenter + + + + + + + Ki + + + Qt::AlignCenter + + + + + + + ILimit + + + Qt::AlignCenter + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Once Rate stabilization is done, you should increase the Kp factor until the airframe oscillates again, and go back down 20% or so. + + + + 6 + + + 0.100000000000000 + + + + + + + Yaw + + + + + + + Pitch + + + + + + + Roll + + + + + + + Ki can usually be almost identical to Kp. + + + 6 + + + 0.100000000000000 + + + + + + + ILimit can be equal to three to four times Ki, but you can adjust +depending on whether your airframe is well balanced, and your +flying style. + + + 6 + + + 0.100000000000000 + + + + + + + If checked, the Roll and Pitch factors will be identical. +When you change one, the other is updated. + + + Link + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Stick range and limits + + + + QLayout::SetMinAndMaxSize + + + + + Roll + + + Qt::AlignCenter + + + + + + + Pitch + + + Qt::AlignCenter + + + + + + + Yaw + + + Qt::AlignCenter + + + + + + + 180 + + + + + + + 180 + + + + + + + 180 + + + + + + + + 150 + 0 + + + + + 50 + false + + + + Full stick angle (deg) + + + + + + + + 150 + 0 + + + + + 50 + false + + + + Full stick rate (deg/s) + + + + + + + 500 + + + + + + + 500 + + + + + + + 500 + + + + + + + + 150 + 0 + + + + + 50 + false + + + + + + + Maximum rate in attitude mode (deg/s) + + + + + + + 500 + + + + + + + 500 + + + + + + + 500 + + + + + + + + + + Zero the integral when throttle is low + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + + + If you check this, the GCS will udpate the stabilization factors +automatically every 300ms, which will help for fast tuning. + + + Update in real time + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + + + + :/core/images/helpicon.svg:/core/images/helpicon.svg + + + + 32 + 32 + + + + true + + + + + + + Load default Stabilization settings + +Loaded settings are not applied automatically. You have to click the +Apply or Save button afterwards. + + + Reset To Defaults + + + + + + + Send settings to the board but do not save to the non-volatile memory + + + Apply + + + + + + + Send settings to the board and save to the non-volatile memory + + + Save + + + + + + + + + scrollArea + rateRollKp + rateRollKi + rateRollILimit + linkRateRP + ratePitchKp + ratePitchKi + ratePitchILimit + rateYawKp + rateYawKi + rateYawILimit + rollKp + rollKi + rollILimit + linkAttitudeRP + pitchKp + pitchKi + pitchILimit + yawKp + yawKi + yawILimit + rollMax + pitchMax + yawMax + manualRoll + manualPitch + manualYaw + maximumRoll + maximumPitch + maximumYaw + lowThrottleZeroIntegral + realTimeUpdates + stabilizationHelp + stabilizationResetToDefaults + saveStabilizationToRAM + saveStabilizationToSD + + + + + + From e3f89eb9580ed2d1f5368f940c16c00b3e8c4a9b Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 11:24:19 -0600 Subject: [PATCH 65/72] Input config: Increase the delay after detecting a channel to ask for next one --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 3e8cf0c87..cc79bc706 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -717,7 +717,7 @@ void ConfigInputWidget::identifyControls() m_config->wzText->clear(); setTxMovement(nothing); - QTimer::singleShot(500, this, SLOT(wzNext())); + QTimer::singleShot(2500, this, SLOT(wzNext())); } void ConfigInputWidget::identifyLimits() From 3a66f70eaecf0ddf77f299945e14af71be139f43 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 11:24:19 -0600 Subject: [PATCH 66/72] Input config: Increase the delay after detecting a channel to ask for next one --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 3e8cf0c87..cc79bc706 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -717,7 +717,7 @@ void ConfigInputWidget::identifyControls() m_config->wzText->clear(); setTxMovement(nothing); - QTimer::singleShot(500, this, SLOT(wzNext())); + QTimer::singleShot(2500, this, SLOT(wzNext())); } void ConfigInputWidget::identifyLimits() From d07b386beb09ecb263fe71b77e4351a358b57973 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 13:09:01 -0600 Subject: [PATCH 67/72] Revert "made the input wizard background transparent" This reverts commit c5a2afcc2c91657b79c0815381a955cd05845f38. --- .../openpilotgcs/src/plugins/config/configinputwidget.cpp | 1 + ground/openpilotgcs/src/plugins/config/input.ui | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index cc79bc706..3b48e4652 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -107,6 +107,7 @@ ConfigInputWidget::ConfigInputWidget(QWidget *parent) : ConfigTaskWidget(parent) m_config->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); m_renderer = new QSvgRenderer(); QGraphicsScene *l_scene = m_config->graphicsView->scene(); + m_config->graphicsView->setBackgroundBrush(QBrush(Utils::StyleHelper::baseColor())); if (QFile::exists(":/configgadget/images/TX2.svg") && m_renderer->load(QString(":/configgadget/images/TX2.svg")) && m_renderer->isValid()) { l_scene->clear(); // Deletes all items contained in the scene as well. diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 30c0cd80d..2fac45ec9 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -90,11 +90,7 @@ - - - background:transparent - - + From 318354a1151f614d4a3e1a2b9eb79524ca7a84c9 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 13:31:14 -0600 Subject: [PATCH 68/72] Fix resizing issue with input wizard --- ground/openpilotgcs/src/plugins/config/configinputwidget.cpp | 1 + ground/openpilotgcs/src/plugins/config/input.ui | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp index 3b48e4652..4387d10f4 100644 --- a/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp +++ b/ground/openpilotgcs/src/plugins/config/configinputwidget.cpp @@ -401,6 +401,7 @@ void ConfigInputWidget::wizardSetUpStep(enum wizardSteps step) case wizardChooseMode: { m_config->graphicsView->setVisible(true); + m_config->graphicsView->fitInView(m_txBackground, Qt::KeepAspectRatio ); setTxMovement(nothing); m_config->wzText->setText(tr("Please choose your transmiter type.\n" "Mode 1 means your throttle stick is on the right\n" diff --git a/ground/openpilotgcs/src/plugins/config/input.ui b/ground/openpilotgcs/src/plugins/config/input.ui index 2fac45ec9..5b591089f 100644 --- a/ground/openpilotgcs/src/plugins/config/input.ui +++ b/ground/openpilotgcs/src/plugins/config/input.ui @@ -76,7 +76,7 @@ 0 - 70 + 90 From a2979125b7bd40bedd87e7497bc1aeb83734db86 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 14:11:04 -0600 Subject: [PATCH 69/72] Remove the hardcoded .svg from the QLabel and load it dynamically. This will be useful for CC3D. --- .../src/plugins/config/cc_hw_settings.ui | 610 +++++++++--------- .../plugins/config/config_cc_hw_widget.cpp | 3 + 2 files changed, 306 insertions(+), 307 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui index 929c9053d..6da1e703a 100644 --- a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui +++ b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui @@ -1,307 +1,303 @@ - - - CC_HW_Widget - - - - 0 - 0 - 517 - 487 - - - - Form - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - :/configgadget/images/coptercontrol.svg - - - true - - - - - - - - - - - - - MainPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - - - - - FlexiPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - RcvrPort - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - Telemetry speed: - - - - - - - - 55 - 0 - - - - GPS speed: - - - - - - - Select the speed here. - - - - - - - Select the speed here. - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 75 - true - - - - - - - Qt::AutoText - - - true - - - - - - - - 75 - true - - - - Changes on this page only take effect after board reset or power cycle - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - - 32 - 32 - - - - - - - - :/core/images/helpicon.svg:/core/images/helpicon.svg - - - - 32 - 32 - - - - true - - - - - - - Send to OpenPilot but don't write in SD. -Beware of not locking yourself out! - - - true - - - - - - Apply - - - false - - - - - - - Applies and Saves all settings to SD. -Beware of not locking yourself out! - - - false - - - - - - Save - - - - - - - - - - - - - - - - + + + CC_HW_Widget + + + + 0 + 0 + 517 + 487 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + true + + + + + + + + + + + + + MainPort + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + + + + + FlexiPort + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + RcvrPort + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + Telemetry speed: + + + + + + + + 55 + 0 + + + + GPS speed: + + + + + + + Select the speed here. + + + + + + + Select the speed here. + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 75 + true + + + + + + + Qt::AutoText + + + true + + + + + + + + 75 + true + + + + Changes on this page only take effect after board reset or power cycle + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + :/core/images/helpicon.svg:/core/images/helpicon.svg + + + + 32 + 32 + + + + true + + + + + + + Send to OpenPilot but don't write in SD. +Beware of not locking yourself out! + + + true + + + + + + Apply + + + false + + + + + + + Applies and Saves all settings to SD. +Beware of not locking yourself out! + + + false + + + + + + Save + + + + + + + + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.cpp b/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.cpp index 1d0f723d0..1b8a7eb70 100644 --- a/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.cpp +++ b/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.cpp @@ -40,6 +40,9 @@ ConfigCCHWWidget::ConfigCCHWWidget(QWidget *parent) : ConfigTaskWidget(parent) { m_telemetry = new Ui_CC_HW_Widget(); m_telemetry->setupUi(this); + + m_telemetry->label_2->setPixmap(QPixmap(":/configgadget/images/coptercontrol.svg")); + setupButtons(m_telemetry->saveTelemetryToRAM,m_telemetry->saveTelemetryToSD); addUAVObjectToWidgetRelation("HwSettings","CC_FlexiPort",m_telemetry->cbFlexi); addUAVObjectToWidgetRelation("HwSettings","CC_MainPort",m_telemetry->cbTele); From 7990d209a8e13559964e0435d772e3de33ee6166 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 14:46:58 -0600 Subject: [PATCH 70/72] Fix package deployment script for OSX to make sure the SVG pixmap shows up --- .../src/plugins/config/config_cc_hw_widget.h | 1 + package/osx/libraries | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.h b/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.h index f815786fb..7c74043b3 100644 --- a/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.h +++ b/ground/openpilotgcs/src/plugins/config/config_cc_hw_widget.h @@ -50,6 +50,7 @@ private slots: private: Ui_CC_HW_Widget *m_telemetry; + QSvgRenderer *m_renderer; }; #endif // CONFIGCCHWWIDGET_H diff --git a/package/osx/libraries b/package/osx/libraries index 5c87ba15b..fc21721e9 100755 --- a/package/osx/libraries +++ b/package/osx/libraries @@ -5,7 +5,7 @@ PLUGINS="${APP}/Contents/Plugins" OP_PLUGINS="${APP}/Contents/Plugins/OpenPilot" QT_LIBS="QtGui QtTest QtCore QtSvg QtSql QtOpenGL QtNetwork QtXml QtDBus QtScript phonon" QT_DIR=$(otool -L "${APP}/Contents/MacOS/OpenPilot GCS" | sed -n -e 's/\/QtCore\.framework.*//p' | sed -n -E 's:^.::p') -QT_EXTRA="accessible/libqtaccessiblewidgets.dylib bearer/libqgenericbearer.dylib codecs/libqcncodecs.dylib codecs/libqjpcodecs.dylib codecs/libqkrcodecs.dylib codecs/libqtwcodecs.dylib graphicssystems/libqtracegraphicssystem.dylib imageformats/libqgif.dylib imageformats/libqico.dylib imageformats/libqjpeg.dylib imageformats/libqmng.dylib imageformats/libqtiff.dylib qmltooling/libqmldbg_inspector.dylib qmltooling/libqmldbg_tcp.dylib" +QT_EXTRA="accessible/libqtaccessiblewidgets.dylib bearer/libqgenericbearer.dylib codecs/libqcncodecs.dylib codecs/libqjpcodecs.dylib codecs/libqkrcodecs.dylib codecs/libqtwcodecs.dylib graphicssystems/libqtracegraphicssystem.dylib imageformats/libqgif.dylib imageformats/libqico.dylib imageformats/libqjpeg.dylib imageformats/libqmng.dylib imageformats/libqtiff.dylib imageformats/libqsvg.dylib qmltooling/libqmldbg_inspector.dylib qmltooling/libqmldbg_tcp.dylib" echo "Qt library directory is \"${QT_DIR}\"" @@ -50,10 +50,21 @@ done for f in ${QT_EXTRA} do + echo "Copying package ${f}" + cp "${QT_DIR}/../plugins/${f}" "${APP}/Contents/Plugins/${f}" echo "Changing package identification of ${f}" install_name_tool -id \ @executable_path/../Plugins/${f} \ "${PLUGINS}/${f}" + + echo "Changing package linkages" + for g in $QT_LIBS + do + install_name_tool -change \ + "${QT_DIR}/${g}.framework/Versions/4/${g}" \ + @executable_path/../Frameworks/${g}.framework/Versions/4/${g} \ + "${APP}/Contents/Plugins/${f}" + done done echo "Copying SDL" From c69717edd84253af7797812d5b150da2e68905f8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 17:29:29 -0600 Subject: [PATCH 71/72] DOS2UNIX cc_hw_settings.ui to make merge work --- .../src/plugins/config/cc_hw_settings.ui | 706 +++++++++--------- 1 file changed, 353 insertions(+), 353 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui index 118acb6e4..4f12b4384 100644 --- a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui +++ b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui @@ -1,353 +1,353 @@ - - - CC_HW_Widget - - - - 0 - 0 - 517 - 487 - - - - Form - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - - - :/configgadget/images/coptercontrol.svg - - - true - - - - - - - - - - - - - MainPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - - - - - FlexiPort - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - USB HID Port - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - USB VCP Port - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - RcvrPort - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - Telemetry speed: - - - - - - - - 55 - 0 - - - - GPS speed: - - - - - - - - 55 - 0 - - - - ComUsbBridge speed: - - - - - - - Select the speed here. - - - - - - - Select the speed here. - - - - - - - Select the speed here. - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 75 - true - - - - - - - Qt::AutoText - - - true - - - - - - - - 75 - true - - - - Changes on this page only take effect after board reset or power cycle - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 32 - 32 - - - - - 32 - 32 - - - - - - - - :/core/images/helpicon.svg:/core/images/helpicon.svg - - - - 32 - 32 - - - - true - - - - - - - Send to OpenPilot but don't write in SD. -Beware of not locking yourself out! - - - true - - - - - - Apply - - - false - - - - - - - Applies and Saves all settings to SD. -Beware of not locking yourself out! - - - false - - - - - - Save - - - - - - - - - - - - - - - - + + + CC_HW_Widget + + + + 0 + 0 + 517 + 487 + + + + Form + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + :/configgadget/images/coptercontrol.svg + + + true + + + + + + + + + + + + + MainPort + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + + + + + FlexiPort + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + USB HID Port + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + USB VCP Port + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + + + RcvrPort + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + Telemetry speed: + + + + + + + + 55 + 0 + + + + GPS speed: + + + + + + + + 55 + 0 + + + + ComUsbBridge speed: + + + + + + + Select the speed here. + + + + + + + Select the speed here. + + + + + + + Select the speed here. + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 75 + true + + + + + + + Qt::AutoText + + + true + + + + + + + + 75 + true + + + + Changes on this page only take effect after board reset or power cycle + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 32 + 32 + + + + + 32 + 32 + + + + + + + + :/core/images/helpicon.svg:/core/images/helpicon.svg + + + + 32 + 32 + + + + true + + + + + + + Send to OpenPilot but don't write in SD. +Beware of not locking yourself out! + + + true + + + + + + Apply + + + false + + + + + + + Applies and Saves all settings to SD. +Beware of not locking yourself out! + + + false + + + + + + Save + + + + + + + + + + + + + + + + From bd77b7e5a22283cfb80bb14d8103bfe31612cd58 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 31 Jan 2012 19:26:48 -0600 Subject: [PATCH 72/72] Fix stupid commit on my part. Thanks for heads up brian. --- .../src/plugins/config/cc_hw_settings.ui | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui index 92af8e26d..e64800124 100644 --- a/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui +++ b/ground/openpilotgcs/src/plugins/config/cc_hw_settings.ui @@ -68,11 +68,7 @@ -<<<<<<< HEAD -======= - ->>>>>>> master Qt::Horizontal @@ -85,7 +81,6 @@ -<<<<<<< HEAD @@ -112,8 +107,6 @@ -======= ->>>>>>> master @@ -153,7 +146,6 @@ -<<<<<<< HEAD @@ -167,8 +159,6 @@ -======= ->>>>>>> master @@ -183,7 +173,6 @@ -<<<<<<< HEAD @@ -191,8 +180,6 @@ -======= ->>>>>>> master @@ -356,10 +343,7 @@ Beware of not locking yourself out! -<<<<<<< HEAD -======= ->>>>>>> master