added GpioMonitor

This commit is contained in:
Simon Stürz 2014-12-07 10:35:36 +01:00 committed by Michael Zanetti
parent 477a95477b
commit 3ffc015c01
7 changed files with 241 additions and 50 deletions

View File

@ -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();
}

View File

@ -23,6 +23,7 @@
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QDir>
#include <stdio.h>
#include <stdlib.h>
@ -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

View File

@ -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<Gpio *> GpioMonitor::gpioList()
{
m_gpioListMutex.lock();
QList<Gpio*> 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);
}

View File

@ -0,0 +1,40 @@
#ifndef GPIOMONITOR_H
#define GPIOMONITOR_H
#include <QThread>
#include <QDebug>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h>
#include <errno.h>
#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<Gpio*> gpioList();
private:
QMutex m_enabledMutex;
bool m_enabled;
QMutex m_gpioListMutex;
QList<Gpio*> m_gpioList;
protected:
void run();
signals:
void changed(const int &gpioPin, const int &value);
};
#endif // GPIOMONITOR_H

View File

@ -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);
}

View File

@ -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

View File

@ -71,8 +71,7 @@ DeviceManager::HardwareResources DevicePluginElro::requiredHardware() const
}
DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action)
{
{
QList<int> rawData;
QByteArray binCode;