diff options
Diffstat (limited to 'metawatch')
-rw-r--r-- | metawatch/metawatch.cpp | 202 | ||||
-rw-r--r-- | metawatch/metawatch.h | 77 | ||||
-rw-r--r-- | metawatch/metawatchplugin.cpp | 2 | ||||
-rw-r--r-- | metawatch/metawatchplugin.h | 2 |
4 files changed, 207 insertions, 76 deletions
diff --git a/metawatch/metawatch.cpp b/metawatch/metawatch.cpp index 5e6a8fb..a429083 100644 --- a/metawatch/metawatch.cpp +++ b/metawatch/metawatch.cpp @@ -9,6 +9,13 @@ QTM_USE_NAMESPACE #define SINGLE_LINE_UPDATE 0 +const char MetaWatch::watchToBtn[8] = { + 0, 1, 2, 3, -1, 4, 5, -1 +}; +const char MetaWatch::btnToWatch[8] = { + 0, 1, 2, 3, 5, 6, -1, -1 +}; + const int MetaWatch::connectRetryTimes[] = { 5, 10, 30, 60, 120, 300 }; @@ -74,21 +81,17 @@ const quint16 MetaWatch::crcTable[256] = { } #endif -MetaWatch::MetaWatch(const QBluetoothAddress& address, QObject *parent) : +MetaWatch::MetaWatch(const QBluetoothAddress& address, QSettings* settings, QObject* parent) : Watch(parent), + _nMails(0), _nCalls(0), _nIms(0), _nSms(0), _nMms(0), + _idleTimer(new QTimer(this)), _ringTimer(new QTimer(this)), + _currentMode(IdleMode), _paintMode(IdleMode), _paintEngine(0), - _address(address), - _socket(0), - _24hMode(true), _dayMonthOrder(true), _notificationTimeout(10), - _connectRetries(0), - _connected(false), + _connectRetries(0), _connected(false), _connectTimer(new QTimer(this)), _connectAlignedTimer(new QSystemAlignedTimer(this)), - _sendTimer(new QTimer(this)), - _currentMode(IdleMode), - _paintMode(IdleMode), - _nMails(0), _nCalls(0), _nIms(0), _nSms(0), _nMms(0), - _idleTimer(new QTimer(this)), _ringTimer(new QTimer(this)) + _address(address), _socket(0), + _sendTimer(new QTimer(this)) { QImage baseImage(screenWidth, screenHeight, QImage::Format_MonoLSB); baseImage.setColor(0, QColor(Qt::white).rgb()); @@ -97,13 +100,13 @@ MetaWatch::MetaWatch(const QBluetoothAddress& address, QObject *parent) : _image[ApplicationMode] = baseImage; _image[NotificationMode] = baseImage; - _connectTimer->setSingleShot(true); - _connectAlignedTimer->setSingleShot(true); - connect(_connectTimer, SIGNAL(timeout()), SLOT(retryConnect())); - connect(_connectAlignedTimer, SIGNAL(timeout()), SLOT(retryConnect())); + _buttonNames << "A" << "B" << "C" << "D" << "E" << "F"; - _sendTimer->setInterval(10); - connect(_sendTimer, SIGNAL(timeout()), SLOT(timedSend())); + if (settings) { + _24hMode = settings->value("24hMode", false).toBool(); + _dayMonthOrder = settings->value("DayMonthOrder", false).toBool(); + _notificationTimeout = settings->value("NotificationTimeout", 10).toInt(); + } _idleTimer->setInterval(_notificationTimeout * 1000); _idleTimer->setSingleShot(true); @@ -112,6 +115,14 @@ MetaWatch::MetaWatch(const QBluetoothAddress& address, QObject *parent) : _ringTimer->setInterval(2000); connect(_ringTimer, SIGNAL(timeout()), SLOT(timedRing())); + _connectTimer->setSingleShot(true); + _connectAlignedTimer->setSingleShot(true); + connect(_connectTimer, SIGNAL(timeout()), SLOT(retryConnect())); + connect(_connectAlignedTimer, SIGNAL(timeout()), SLOT(retryConnect())); + + _sendTimer->setInterval(10); + connect(_sendTimer, SIGNAL(timeout()), SLOT(timedSend())); + retryConnect(); } @@ -161,6 +172,11 @@ QString MetaWatch::model() const return "metawatch-digital"; } +QStringList MetaWatch::buttons() const +{ + return _buttonNames; +} + bool MetaWatch::isConnected() const { return _connected; @@ -199,32 +215,6 @@ void MetaWatch::setDateTime(const QDateTime &dateTime) send(msg); } -void MetaWatch::updateNotificationCount(Notification::Type type, int count) -{ - switch (type) { - case Notification::MissedCallNotification: - _nCalls = count; - break; - case Notification::EmailNotification: - _nMails = count; - break; - case Notification::ImNotification: - _nIms = count; - break; - case Notification::SmsNotification: - _nSms = count; - break; - case Notification::MmsNotification: - _nMms = count; - break; - default: - // Ignore - break; - } - - renderIdleCounts(); -} - void MetaWatch::displayIdleScreen() { _currentMode = IdleMode; @@ -234,7 +224,6 @@ void MetaWatch::displayIdleScreen() updateDisplay(IdleMode); // Usually, idle screen is kept updated, so we can show it already. qDebug() << "displayIdle"; - } void MetaWatch::displayNotification(Notification *n) @@ -313,6 +302,42 @@ void MetaWatch::displayApplication() qDebug() << "displayApplication"; } +void MetaWatch::grabButton(int button) +{ + grabButton(_currentMode, (Button) button); +} + +void MetaWatch::ungrabButton(int button) +{ + ungrabButton(_currentMode, (Button) button); +} + +void MetaWatch::updateNotificationCount(Notification::Type type, int count) +{ + switch (type) { + case Notification::MissedCallNotification: + _nCalls = count; + break; + case Notification::EmailNotification: + _nMails = count; + break; + case Notification::ImNotification: + _nIms = count; + break; + case Notification::SmsNotification: + _nSms = count; + break; + case Notification::MmsNotification: + _nMms = count; + break; + default: + // Ignore + break; + } + + renderIdleCounts(); +} + MetaWatch::Mode MetaWatch::currentMode() const { return _currentMode; @@ -353,6 +378,18 @@ void MetaWatch::clear(Mode mode, bool black) loadTemplate(mode, black ? 1 : 0); } +void MetaWatch::grabButton(Mode mode, Button button) +{ + enableButton(mode, button, PressOnly); + enableButton(mode, button, PressAndRelease); +} + +void MetaWatch::ungrabButton(Mode mode, Button button) +{ + disableButton(mode, button, PressOnly); + disableButton(mode, button, PressAndRelease); +} + void MetaWatch::renderIdleScreen() { QImage idle_call(QString(":/metawatch/graphics/idle_call.bmp")); @@ -602,19 +639,66 @@ void MetaWatch::loadTemplate(Mode mode, int templ) send(msg); } +void MetaWatch::enableButton(Mode mode, Button button, ButtonPress press) +{ + Message msg(EnableButton, QByteArray(5, 0)); + + Q_ASSERT(button >= 0 && button < 8); + + msg.data[0] = mode; + msg.data[1] = btnToWatch[button]; + msg.data[2] = press; + msg.data[3] = ButtonEvent; + msg.data[4] = 0x80 | ((press << 4) & 0x30) | (button & 0xF); + + send(msg); +} + +void MetaWatch::disableButton(Mode mode, Button button, ButtonPress press) +{ + Message msg(DisableButton, QByteArray(3, 0)); + + Q_ASSERT(button >= 0 && button < 8); + + msg.data[0] = mode; + msg.data[1] = btnToWatch[button]; + msg.data[2] = press; + + send(msg); +} + void MetaWatch::handleStatusChange(const Message &msg) { - qDebug() << "watch status changed" << msg.options << msg.data.at(0); + QString s; + qDebug() << "watch status changed" << s.sprintf("0x%hx", msg.options) << s.sprintf("0x%hx", msg.data.at(0)); } void MetaWatch::handleButtonEvent(const Message &msg) { - if (msg.data.size() < 1) return; - quint8 button = msg.data[0]; + if (!(msg.options & 0x80)) { + // We didn't configure this button, reject. + return; + } + + quint8 watchBtn = msg.options & 0xF; + ButtonPress press = (ButtonPress) ((msg.options & 0x30) >> 4); + int button = -1; - qDebug() << "button event" << msg.data.size() << msg.options << msg.data.at(0); + if (watchBtn < 8) { + button = watchToBtn[watchBtn]; + } + if (button == -1) { + qWarning() << "Unknown watch button" << watchBtn; + return; + } + + qDebug() << "button event" << button << press; - emit buttonPressed(button); // TODO This is completely broken + if (press == PressOnly) { + emit buttonPressed(button); + } else if (press == PressAndRelease) { + emit buttonReleased(button); + } } void MetaWatch::socketConnected() @@ -628,11 +712,23 @@ void MetaWatch::socketConnected() _partialReceived.data.clear(); _currentMode = IdleMode; _paintMode = IdleMode; - _buttonState = 0; setDateTime(QDateTime::currentDateTime()); configureIdleSystemArea(false); + grabButton(ApplicationMode, BtnA); + grabButton(ApplicationMode, BtnB); + grabButton(ApplicationMode, BtnC); + grabButton(ApplicationMode, BtnD); + grabButton(ApplicationMode, BtnE); + grabButton(ApplicationMode, BtnF); + grabButton(NotificationMode, BtnA); + grabButton(NotificationMode, BtnB); + grabButton(NotificationMode, BtnC); + grabButton(NotificationMode, BtnD); + grabButton(NotificationMode, BtnE); + grabButton(NotificationMode, BtnF); + renderIdleScreen(); renderNotificationScreen(); @@ -673,12 +769,14 @@ void MetaWatch::socketData() qint64 dataRead; if (_partialReceived.type == 0) { + /* Still not received even the packet type */ + /* Receive the full header, 4 bytes. */ if (_socket->bytesAvailable() < 4) return; /* Wait for more. */ char header[4]; dataRead = _socket->read(header, 4); if (dataRead < 4 || header[0] != 0x01) { - qWarning() << "TODO: Resync/Handle Garbage"; + qWarning() << "TODO: Resync / Handle Garbage"; return; } @@ -686,6 +784,8 @@ void MetaWatch::socketData() _partialReceived.data.resize(header[1] - 6); _partialReceived.options = header[3]; } + + /* Got the header; now, try to get the complete packet. */ if (_socket->bytesAvailable() < _partialReceived.data.size() + 2) { return; /* Wait for more. */ } diff --git a/metawatch/metawatch.h b/metawatch/metawatch.h index da0f323..0a9123a 100644 --- a/metawatch/metawatch.h +++ b/metawatch/metawatch.h @@ -3,6 +3,7 @@ #include <QtCore/QQueue> #include <QtCore/QTimer> +#include <QtCore/QSettings> #include <QtConnectivity/QBluetoothAddress> #include <QtConnectivity/QBluetoothSocket> #include <QtSystemInfo/QSystemAlignedTimer> @@ -20,10 +21,9 @@ class MetaWatchPaintEngine; class MetaWatch : public Watch { Q_OBJECT - Q_ENUMS(MessageType Mode) public: - explicit MetaWatch(const QBluetoothAddress& address, QObject *parent = 0); + explicit MetaWatch(const QBluetoothAddress& address, QSettings* settings = 0, QObject *parent = 0); ~MetaWatch(); static const int screenWidth = 96; @@ -66,28 +66,49 @@ public: NotificationMode = 2 }; + enum Button { + BtnA = 0, + BtnB, + BtnC, + BtnD, + BtnE, + BtnF + }; + + enum ButtonPress { + PressOnly = 0, + PressAndRelease = 1, + HoldAndRelease = 2, + LongHoldAndRelease = 3 + }; + QPaintEngine* paintEngine() const; int metric(PaintDeviceMetric metric) const; QString model() const; + QStringList buttons() const; bool isConnected() const; bool busy() const; QDateTime dateTime(); void setDateTime(const QDateTime& dateTime); - void updateNotificationCount(Notification::Type type, int count); - void displayIdleScreen(); void displayNotification(Notification *n); void displayApplication(); + void grabButton(int button); + void ungrabButton(int button); + + void updateNotificationCount(Notification::Type type, int count); Mode currentMode() const; Mode paintTargetMode() const; QImage* imageFor(Mode mode); void clear(Mode mode, bool black = false); void update(Mode mode, const QList<QRect>& rects = QList<QRect>()); + void grabButton(Mode mode, Button button); + void ungrabButton(Mode mode, Button button); void renderIdleScreen(); void renderIdleWeather(); @@ -97,18 +118,32 @@ public: QImage iconForNotification(const Notification *n); protected: - mutable MetaWatchPaintEngine* _paintEngine; - QImage _image[3]; - - QBluetoothAddress _address; - QBluetoothSocket* _socket; - - /* Some configurable stuff. */ + // Some configurable stuff. bool _24hMode : 1; bool _dayMonthOrder : 1; - short _notificationTimeout; + // Notifications: Unread count + uint _nMails, _nCalls, _nIms, _nSms, _nMms; + + // Notifications: timers + QTimer* _idleTimer; + QTimer* _ringTimer; + + // Buttons + static const char watchToBtn[8]; + static const char btnToWatch[8]; + QStringList _buttonNames; + + // Current watch state + Mode _currentMode; + Mode _paintMode; + + // For QPaintDevice + mutable MetaWatchPaintEngine* _paintEngine; + QImage _image[3]; + + // Timers to retry the connection when the watch is not found. static const int connectRetryTimesSize = 6; static const int connectRetryTimes[connectRetryTimesSize]; short _connectRetries; @@ -116,6 +151,11 @@ protected: QTimer* _connectTimer; QSystemAlignedTimer* _connectAlignedTimer; + // Connection stuff + QBluetoothAddress _address; + QBluetoothSocket* _socket; + + // Base watch protocol stuff struct Message { MessageType type; quint8 options; @@ -129,17 +169,6 @@ protected: QTimer* _sendTimer; Message _partialReceived; - Mode _currentMode; - Mode _paintMode; - quint8 _buttonState; - - // Notifications: Unread count - uint _nMails, _nCalls, _nIms, _nSms, _nMms; - - // Notifications: timers - QTimer* _idleTimer; - QTimer* _ringTimer; - static const quint8 bitRevTable[16]; static const quint16 crcTable[256]; quint16 calcCrc(const QByteArray& data, int size); @@ -156,6 +185,8 @@ protected: void configureIdleSystemArea(bool entireScreen); void updateDisplay(Mode mode, bool copy = true); void loadTemplate(Mode mode, int templ); + void enableButton(Mode mode, Button button, ButtonPress press); + void disableButton(Mode mode, Button button, ButtonPress press); void handleStatusChange(const Message& msg); void handleButtonEvent(const Message& msg); diff --git a/metawatch/metawatchplugin.cpp b/metawatch/metawatchplugin.cpp index 6a97297..23a4f63 100644 --- a/metawatch/metawatchplugin.cpp +++ b/metawatch/metawatchplugin.cpp @@ -36,7 +36,7 @@ Watch* MetaWatchPlugin::getWatch(const QString& driver, QSettings& settings, QOb { if (driver == "metawatch-digital") { QBluetoothAddress address(settings.value("address").toString()); - return new MetaWatch(address, parent); + return new MetaWatch(address, &settings, parent); } else { return 0; } diff --git a/metawatch/metawatchplugin.h b/metawatch/metawatchplugin.h index 57b1029..6834247 100644 --- a/metawatch/metawatchplugin.h +++ b/metawatch/metawatchplugin.h @@ -15,7 +15,7 @@ public: ~MetaWatchPlugin(); virtual QStringList drivers(); - virtual Watch* getWatch(const QString& driver, QSettings& settings, QObject *parent = 0); + virtual Watch* getWatch(const QString& driver, QSettings& settings, QObject* parent = 0); protected: static bool fontsLoaded; |