From 8d1369c7ef2d3a4df8f704fb97c21da1405992bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 4 Sep 2019 12:46:11 +0200 Subject: [PATCH] Add basic structure for gpio monitor --- .gitignore | 2 + gpiomonitor.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++++ gpiomonitor.h | 51 +++++++++++++++++++++ libnymea-gpio.pro | 7 +-- 4 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 gpiomonitor.cpp create mode 100644 gpiomonitor.h diff --git a/.gitignore b/.gitignore index 5291a38..8176148 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,5 @@ target_wrapper.* # QtCreator CMake CMakeLists.txt.user* + +.crossbuilder diff --git a/gpiomonitor.cpp b/gpiomonitor.cpp new file mode 100644 index 0000000..48f69c6 --- /dev/null +++ b/gpiomonitor.cpp @@ -0,0 +1,110 @@ +#include "gpiomonitor.h" + +#include + +GpioMonitor::GpioMonitor(int gpio, QObject *parent) : + QThread(parent) +{ + m_gpio = new Gpio(gpio, this); + connect(this, &GpioMonitor::started, this, &GpioMonitor::onThreadStarted); + connect(this, &GpioMonitor::finished, this, &GpioMonitor::onThreadFinished); +} + +GpioMonitor::~GpioMonitor() +{ + disable(); + wait(); +} + +Gpio::Value GpioMonitor::value() +{ + QMutexLocker valueLocker(&m_valueMutex); + return m_value; +} + +bool GpioMonitor::enabled() const +{ + return m_enabled; +} + +void GpioMonitor::setValue(Gpio::Value value) +{ + QMutexLocker valueLocker(&m_valueMutex); + if (m_value == value) + return; + + m_value = value; + emit valueChanged(m_value); +} + +void GpioMonitor::setEnabled(bool enabled) +{ + if (m_enabled == enabled) + return; + + m_enabled = enabled; + emit enabledChanged(m_enabled); +} + +void GpioMonitor::run() +{ + // Poll the GPIO value until the stop is true + while (true) { + + // Note: the setValue() method takes care about the mutex locking + setValue(m_gpio->value()); + + // Check if we should stop the thread + QMutexLocker stopLocker(&m_stopMutex); + if (m_stop) break; + msleep(50); + } +} + +void GpioMonitor::onThreadStarted() +{ + setEnabled(true); +} + +void GpioMonitor::onThreadFinished() +{ + setEnabled(false); +} + +bool GpioMonitor::enable() +{ + if (isRunning()) { + qCWarning(dcGpio()) << "This GPIO monitor is already running."; + return true; + } + + QMutexLocker locker(&m_stopMutex); + m_stop = false; + + if (!m_gpio->exportGpio()) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor."; + return false; + } + + if (!m_gpio->setDirection(Gpio::DirectionInput)) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor."; + return false; + } + + if (!m_gpio->setEdgeInterrupt(Gpio::EdgeBoth)) { + qCWarning(dcGpio()) << "Could not enable GPIO monitor."; + return false; + } + + // Everything went fine, lets start the poll thread and inform about the result + start(); + return true; +} + +void GpioMonitor::disable() +{ + // Stop the thread if not already disabled + QMutexLocker locker(&m_stopMutex); + if (m_stop) return; + m_stop = true; +} diff --git a/gpiomonitor.h b/gpiomonitor.h new file mode 100644 index 0000000..da234f3 --- /dev/null +++ b/gpiomonitor.h @@ -0,0 +1,51 @@ +#ifndef GPIOMONITOR_H +#define GPIOMONITOR_H + +#include +#include +#include + +#include "gpio.h" + +class GpioMonitor : public QThread +{ + Q_OBJECT +public: + explicit GpioMonitor(int gpio, QObject *parent = nullptr); + ~GpioMonitor() override; + + Gpio::Value value(); + bool enabled() const; + +private: + Gpio *m_gpio = nullptr; + bool m_enabled = false; + + // Thread stuff + QMutex m_valueMutex; + Gpio::Value m_value = Gpio::ValueInvalid; + + QMutex m_stopMutex; + bool m_stop = false; + + void setValue(Gpio::Value value); + void setEnabled(bool enabled); + +protected: + void run() override; + +signals: + void valueChanged(bool value); + void enabledChanged(bool enabled); + +private slots: + void onThreadStarted(); + void onThreadFinished(); + +public slots: + bool enable(); + void disable(); + +}; + +#endif // GPIOMONITOR_H diff --git a/libnymea-gpio.pro b/libnymea-gpio.pro index ee75995..4d36cfc 100644 --- a/libnymea-gpio.pro +++ b/libnymea-gpio.pro @@ -8,14 +8,15 @@ QMAKE_LFLAGS *= -std=c++11 VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"') - DEFINES += LIBNYMEAGPIO_LIBRARY SOURCES += \ - gpio.cpp + gpio.cpp \ + gpiomonitor.cpp HEADERS += \ - gpio.h + gpio.h \ + gpiomonitor.h target.path = $$[QT_INSTALL_LIBS] INSTALLS += target