From 3ffc015c014d3501b9a702b17e0427ce7e5dd58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Sun, 7 Dec 2014 10:35:36 +0100 Subject: [PATCH] added GpioMonitor --- libguh/hardware/gpio.cpp | 88 ++++++++++++++---- libguh/hardware/gpio.h | 58 ++++++------ libguh/hardware/gpiomonitor.cpp | 92 +++++++++++++++++++ libguh/hardware/gpiomonitor.h | 40 ++++++++ libguh/hardware/radio433/radio433receiver.cpp | 4 + libguh/libguh.pro | 6 +- .../deviceplugins/elro/devicepluginelro.cpp | 3 +- 7 files changed, 241 insertions(+), 50 deletions(-) create mode 100644 libguh/hardware/gpiomonitor.cpp create mode 100644 libguh/hardware/gpiomonitor.h diff --git a/libguh/hardware/gpio.cpp b/libguh/hardware/gpio.cpp index 6782259a..2fe74dbd 100644 --- a/libguh/hardware/gpio.cpp +++ b/libguh/hardware/gpio.cpp @@ -53,17 +53,19 @@ Gpio::~Gpio() /*! Returns true if the GPIO could be exported in the system file "/sys/class/gpio/export".*/ bool Gpio::exportGpio() { + unexportGpio(); + char buf[64]; int fd = open("/sys/class/gpio/export", O_WRONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio/export"; + qDebug() << "ERROR: could not open /sys/class/gpio/export"; return false; } ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); if(write(fd, buf, len) != len){ - qDebug() << "ERROR: could not set edge interrupt"; + qDebug() << "ERROR: could not write to gpio (export)"; close(fd); return false; } @@ -78,13 +80,13 @@ bool Gpio::unexportGpio() int fd = open("/sys/class/gpio/unexport", O_WRONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio/unexport"; + qDebug() << "ERROR: could not open /sys/class/gpio/unexport"; return false; } ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); if(write(fd, buf, len) != len){ - qDebug() << "ERROR: could not set edge interrupt"; + //qDebug() << "ERROR: could not write to gpio (unexport)"; close(fd); return false; } @@ -101,7 +103,7 @@ int Gpio::openGpio() int fd = open(buf, O_RDONLY | O_NONBLOCK ); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; return fd; } return fd; @@ -129,12 +131,12 @@ bool Gpio::setDirection(int dir) int fd = open(buf, O_WRONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction"; return false; } if(dir == INPUT){ if(write(fd, "in", 3) != 3){ - qDebug() << "ERROR: could not write to gpio"; + qDebug() << "ERROR: could not write to gpio (set INPUT)"; close(fd); return false; } @@ -144,7 +146,7 @@ bool Gpio::setDirection(int dir) } if(dir == OUTPUT){ if(write(fd, "out", 4) != 4){ - qDebug() << "ERROR: could not write to gpio"; + qDebug() << "ERROR: could not write to gpio (set OUTPUT)"; close(fd); return false; } @@ -155,6 +157,7 @@ bool Gpio::setDirection(int dir) close(fd); return false; } + /*! Returns true, if the digital \a value of the GPIO could be set correctly. * * Possible \a value 's are: @@ -179,13 +182,13 @@ bool Gpio::setValue(unsigned int value) int fd = open(buf, O_WRONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; return false; } if(value == LOW){ if(write(fd, "0", 2) != 2){ - qDebug() << "ERROR: could not write to gpio"; + qDebug() << "ERROR: could not write to gpio (set LOW)"; close(fd); return false; } @@ -194,7 +197,7 @@ bool Gpio::setValue(unsigned int value) } if(value == HIGH){ if(write(fd, "1", 2) != 2){ - qDebug() << "ERROR: could not write to gpio"; + qDebug() << "ERROR: could not write to gpio (set HIGH)"; close(fd); return false; } @@ -204,10 +207,11 @@ bool Gpio::setValue(unsigned int value) close(fd); return false; }else{ - qDebug() << "ERROR: Gpio" << m_gpio << "is not a OUTPUT."; + qDebug() << "ERROR: Gpio" << m_gpio << "is not an OUTPUT."; return false; } } + /*! Returns the current digital value of the GPIO. * * Possible values are: @@ -231,7 +235,7 @@ int Gpio::getValue() int fd = open(buf, O_RDONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value"; return -1; } char ch; @@ -248,8 +252,6 @@ int Gpio::getValue() value = 0; } close(fd); - - //qDebug() << "gpio" << m_gpio << "value = " << value; return value; } @@ -279,13 +281,13 @@ bool Gpio::setEdgeInterrupt(int edge) int fd = open(buf, O_WRONLY); if (fd < 0) { - //qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge"; + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge"; return false; } if(edge == EDGE_FALLING){ if(write(fd, "falling", 8) != 8){ - qDebug() << "ERROR: could not set edge interrupt"; + qDebug() << "ERROR: could not write to gpio (set EDGE_FALLING)"; close(fd); return false; } @@ -294,7 +296,7 @@ bool Gpio::setEdgeInterrupt(int edge) } if(edge == EDGE_RISING){ if(write(fd, "rising", 7) != 7){ - qDebug() << "ERROR: could not set edge interrupt"; + qDebug() << "ERROR: could not write to gpio (set EDGE_RISING)"; close(fd); return false; } @@ -303,7 +305,7 @@ bool Gpio::setEdgeInterrupt(int edge) } if(edge == EDGE_BOTH){ if(write(fd, "both", 5) != 5){ - qDebug() << "ERROR: could not set edge interrupt"; + qDebug() << "ERROR: could not write to gpio (set EDGE_BOTH)"; close(fd); return false; } @@ -313,3 +315,51 @@ bool Gpio::setEdgeInterrupt(int edge) close(fd); return false; } + +bool Gpio::setActiveLow(bool activeLow) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/active_low", m_gpio); + int fd = open(buf, O_WRONLY); + if (fd < 0) { + qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/active_low"; + return false; + } + + if(activeLow){ + if(write(fd, "0", 2) != 2){ + qDebug() << "ERROR: could not write to gpio (set Active LOW)"; + close(fd); + return false; + } + close(fd); + return true; + } + if(!activeLow){ + if(write(fd, "1", 2) != 2){ + qDebug() << "ERROR: could not write to gpio (set Active HIGH)"; + close(fd); + return false; + } + close(fd); + return true; + } + close(fd); + return false; +} + +int Gpio::gpioPin() +{ + return m_gpio; +} + +int Gpio::gpioDirection() +{ + return m_dir; +} + +bool Gpio::isAvailable() +{ + QDir gpioDirectory("/sys/class/gpio"); + return gpioDirectory.exists(); +} diff --git a/libguh/hardware/gpio.h b/libguh/hardware/gpio.h index 2118913d..e02fb7a8 100644 --- a/libguh/hardware/gpio.h +++ b/libguh/hardware/gpio.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -41,30 +42,31 @@ #define EDGE_RISING 1 #define EDGE_BOTH 2 + /********************************** - * Raspberry Pi Rev. 2.0 - * ______________________ - * |______________________| - * | File NR. | PIN NR. | - * |___________|__________| - * | GPIO 2 | 3 | - * | GPIO 3 | 5 | - * | GPIO 4 | 7 | - * | GPIO 7 | 26 | - * | GPIO 8 | 24 | - * | GPIO 9 | 21 | - * | GPIO 10 | 19 | - * | GPIO 11 | 23 | - * | GPIO 14 | 8 | - * | GPIO 15 | 10 | - * | GPIO 17 | 11 | - * | GPIO 18 | 12 | - * | GPIO 22 | 15 | - * | GPIO 23 | 16 | - * | GPIO 24 | 18 | - * | GPIO 25 | 22 | - * | GPIO 27 | 13 | - * |___________|__________| + * Raspberry Pi Rev. 2.0 P1 Header Raspberry Pi Rev. 2.0 P5 Header + * __________________________________ __________________________________ + * |______________________|__________| |______________________|__________| + * | Name | PIN NR. | Function | | Name | PIN NR. | Function | + * |___________|__________|__________| |___________|__________|__________| + * | GPIO 2 | 3 | SDA | | GPIO 28 | 3 | SDA | + * | GPIO 3 | 5 | SCL | | GPIO 29 | 4 | SCL | + * | GPIO 4 | 7 | | | GPIO 30 | 5 | | + * | GPIO 7 | 26 | CE1 | | GPIO 31 | 6 | | + * | GPIO 8 | 24 | CE0 | |___________|__________|__________| + * | GPIO 9 | 21 | MISO | + * | GPIO 10 | 19 | MOSI | + * | GPIO 11 | 23 | SCLK | + * | GPIO 14 | 8 | TXD | + * | GPIO 15 | 10 | RXD | + * | GPIO 17 | 11 | | + * | GPIO 18 | 12 | PCM_CLK | + * | GPIO 22 | 15 | | + * | GPIO 23 | 16 | | + * | GPIO 24 | 18 | | + * | GPIO 25 | 22 | | + * | GPIO 27 | 13 | | + * |___________|__________|__________| * ********************************** */ @@ -86,15 +88,17 @@ public: int getValue(); bool setEdgeInterrupt(int edge); + bool setActiveLow(bool activeLow); + + int gpioPin(); + int gpioDirection(); + + bool isAvailable(); private: int m_gpio; int m_dir; -signals: - -public slots: - }; #endif // GPIO_H diff --git a/libguh/hardware/gpiomonitor.cpp b/libguh/hardware/gpiomonitor.cpp new file mode 100644 index 00000000..ee909837 --- /dev/null +++ b/libguh/hardware/gpiomonitor.cpp @@ -0,0 +1,92 @@ +#include "gpiomonitor.h" + +GpioMonitor::GpioMonitor(QObject *parent) : + QThread(parent) +{ +} + +GpioMonitor::~GpioMonitor() +{ + foreach (Gpio* gpio, m_gpioList) { + gpio->unexportGpio(); + } + quit(); + wait(); + deleteLater(); +} + +void GpioMonitor::stop() +{ + m_enabledMutex.lock(); + m_enabled = false; + m_enabledMutex.unlock(); +} + +bool GpioMonitor::addGpio(Gpio *gpio, bool activeLow) +{ + if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(activeLow)) { + return false; + } + m_gpioListMutex.lock(); + m_gpioList.append(gpio); + m_gpioListMutex.unlock(); + return true; +} + +QList GpioMonitor::gpioList() +{ + m_gpioListMutex.lock(); + QList gpioList = m_gpioList; + m_gpioListMutex.unlock(); + return gpioList; +} + +void GpioMonitor::run() +{ + struct pollfd *fds; + char val; + int ret; + int retVal; + + fds = (pollfd*) malloc(sizeof(pollfd) * m_gpioList.size()); + m_gpioListMutex.lock(); + for (int i = 0; i < m_gpioList.size(); i++) { + fds[i].fd = m_gpioList[i]->openGpio(); + fds[i].events = POLLPRI | POLLERR; + } + m_gpioListMutex.unlock(); + + bool enabled = true; + + m_enabledMutex.lock(); + m_enabled = true; + m_enabledMutex.unlock(); + + while (enabled) { + m_gpioListMutex.lock(); + ret = poll(fds, m_gpioList.size(), 2000); + + if (ret > 0) { + for (int i=0; i < m_gpioList.size(); i++) { + if ((fds[i].revents & POLLPRI) || (fds[i].revents & POLLERR)) { + lseek(fds[i].fd, 0, SEEK_SET); + retVal = read(fds[i].fd, &val, 1); + + emit changed(m_gpioList[i]->gpioPin(), m_gpioList[i]->getValue()); + + if (retVal < 0) { + qWarning() << "ERROR: poll failed"; + } + } + } + } else if (ret < 0) { + qWarning() << "ERROR: poll failed: " << errno; + } + m_gpioListMutex.unlock(); + + m_enabledMutex.lock(); + enabled = m_enabled; + m_enabledMutex.unlock(); + } + free(fds); +} diff --git a/libguh/hardware/gpiomonitor.h b/libguh/hardware/gpiomonitor.h new file mode 100644 index 00000000..ae319b51 --- /dev/null +++ b/libguh/hardware/gpiomonitor.h @@ -0,0 +1,40 @@ +#ifndef GPIOMONITOR_H +#define GPIOMONITOR_H + +#include +#include +#include +#include +#include +#include + +#include "hardware/gpio.h" + +class GpioMonitor : public QThread +{ + Q_OBJECT +public: + explicit GpioMonitor(QObject *parent = 0); + ~GpioMonitor(); + + void stop(); + bool addGpio(Gpio *gpio, bool activeLow); + QList gpioList(); + + +private: + QMutex m_enabledMutex; + bool m_enabled; + + QMutex m_gpioListMutex; + QList m_gpioList; + +protected: + void run(); + +signals: + void changed(const int &gpioPin, const int &value); + +}; + +#endif // GPIOMONITOR_H diff --git a/libguh/hardware/radio433/radio433receiver.cpp b/libguh/hardware/radio433/radio433receiver.cpp index 4cc024db..705e862b 100644 --- a/libguh/hardware/radio433/radio433receiver.cpp +++ b/libguh/hardware/radio433/radio433receiver.cpp @@ -33,6 +33,10 @@ Radio433Receiver::Radio433Receiver(QObject *parent, int gpio) : m_enabled = false; m_mutex.unlock(); + if(Gpio::isAvailable()){ + + } + connect(this, &Radio433Receiver::timingReady, this, &Radio433Receiver::handleTiming, Qt::DirectConnection); } diff --git a/libguh/libguh.pro b/libguh/libguh.pro index 1b8b3a08..269445b9 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -29,7 +29,8 @@ SOURCES += plugin/device.cpp \ types/paramtype.cpp \ types/param.cpp \ types/paramdescriptor.cpp \ - types/statedescriptor.cpp + types/statedescriptor.cpp \ + hardware/gpiomonitor.cpp HEADERS += plugin/device.h \ plugin/deviceclass.h \ @@ -54,5 +55,6 @@ HEADERS += plugin/device.h \ types/param.h \ types/paramdescriptor.h \ types/statedescriptor.h \ - typeutils.h + typeutils.h \ + hardware/gpiomonitor.h diff --git a/plugins/deviceplugins/elro/devicepluginelro.cpp b/plugins/deviceplugins/elro/devicepluginelro.cpp index 516749fc..ea8621bd 100644 --- a/plugins/deviceplugins/elro/devicepluginelro.cpp +++ b/plugins/deviceplugins/elro/devicepluginelro.cpp @@ -71,8 +71,7 @@ DeviceManager::HardwareResources DevicePluginElro::requiredHardware() const } DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action) -{ - +{ QList rawData; QByteArray binCode;