renew gpio and pwm classes

This commit is contained in:
Simon Stürz 2016-04-27 13:28:04 +02:00 committed by Michael Zanetti
parent f5ee163c48
commit 4191b8f37c
15 changed files with 846 additions and 660 deletions

View File

@ -40,8 +40,6 @@
No Resource required. No Resource required.
\value HardwareResourceRadio433 \value HardwareResourceRadio433
Refers to the 433 MHz radio. Refers to the 433 MHz radio.
\value HardwareResourceRadio868
Refers to the 868 MHz radio.
\value HardwareResourceTimer \value HardwareResourceTimer
Refers to the global timer managed by the \l{DeviceManager}. Plugins should not create their own timers, Refers to the global timer managed by the \l{DeviceManager}. Plugins should not create their own timers,
but rather request the global timer using the hardware resources. but rather request the global timer using the hardware resources.
@ -207,7 +205,6 @@ DeviceManager::DeviceManager(QObject *parent) :
connect(&m_pluginTimer, &QTimer::timeout, this, &DeviceManager::timerEvent); connect(&m_pluginTimer, &QTimer::timeout, this, &DeviceManager::timerEvent);
m_radio433 = new Radio433(this); m_radio433 = new Radio433(this);
connect(m_radio433, &Radio433::dataReceived, this, &DeviceManager::radio433SignalReceived);
m_radio433->enable(); m_radio433->enable();
// TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something... // TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something...

View File

@ -57,13 +57,12 @@ class LIBGUH_EXPORT DeviceManager : public QObject
public: public:
enum HardwareResource { enum HardwareResource {
HardwareResourceNone = 0x00, HardwareResourceNone = 0,
HardwareResourceRadio433 = 0x01, HardwareResourceRadio433 = 1,
HardwareResourceRadio868 = 0x02, HardwareResourceTimer = 2,
HardwareResourceTimer = 0x04, HardwareResourceNetworkManager = 4,
HardwareResourceNetworkManager = 0x08, HardwareResourceUpnpDisovery = 8,
HardwareResourceUpnpDisovery = 0x10, HardwareResourceBluetoothLE = 16
HardwareResourceBluetoothLE = 0x20
}; };
Q_DECLARE_FLAGS(HardwareResources, HardwareResource) Q_DECLARE_FLAGS(HardwareResources, HardwareResource)

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> * * Copyright (C) 2015 -2016 Simon Stürz <simon.stuerz@guh.guru> *
* * * *
* This file is part of guh. * * This file is part of guh. *
* * * *
@ -37,32 +37,44 @@
General Purpose Input/Output (a.k.a. GPIO) is a generic pin on a chip whose General Purpose Input/Output (a.k.a. GPIO) is a generic pin on a chip whose
behavior (including whether it is an input or output pin) can be controlled behavior (including whether it is an input or output pin) can be controlled
through this class. An object of of the Gpio class represents a pin. through this class. An object of of the Gpio class represents a pin.
*/
\chapter Example /*! \enum Gpio::Direction
Following example shows how to initialize and interact with a GPIO. The GPIO will be configured as an input, This enum type specifies the dirction a \l{Gpio}.
set active high and the edge interrupt will be set to EDGE_BOTH.
\code \value DirectionInput
Gpio *gpio = new Gpio(this, 22); The \l{Gpio} is configured as \b input.
if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(true)) { \value DirectionOutput
return; The \l{Gpio} is configured as \b output.
} \value DirectionInvalid
int value = gpio->getValue(); The direction is not valid.
qDebug() << "value = " << value; */
\endcode
\chapter Raspberry Pi GPIOs /*! \enum Gpio::Value
In following table is a list of all GPIO's of the Raspberry Pi Rev. 2.0:
\image Raspberry_Pi_GPIO_Map.png "Raspberry Pi GPIO map" This enum type specifies the value a \l{Gpio}.
Valid GPIO's for this class are those with a GPIO number (for example GPIO 22, which is on pin Nr. 15) \value ValueLow
The \l{Gpio} is low.
\value ValueHigh
The \l{Gpio} is high.
\value ValueInvalid
The value is not valid.
*/
\chapter Beaglebone Black GPIOs /*! \enum Gpio::Edge
In following table is a list of all GPIO's of the Beaglebone Black (\l{http://pix.cs.olemiss.edu/csci581/BBBlackGPIOMap.png}{Source}):
\image Beaglebone_Black_GPIO_Map.png "Beaglebone Black GPIO map" This enum type specifies the edge interrupt type of a \l{Gpio}.
\value EdgeFalling
The \l{Gpio} reacts on falling edge interrupt.
\value EdgeRising
The \l{Gpio} reacts on rising edge interrupt.
\value EdgeBoth
The \l{Gpio} reacts on both, rising and falling edge interrupt.
\value EdgeNone
The \l{Gpio} does not react on interrupts.
*/ */
@ -71,339 +83,299 @@
#include <QDebug> #include <QDebug>
/*! Constructs a \l{Gpio} object to represent a GPIO with the given \a gpio number and the \a parent. */ /*! Constructs a \l{Gpio} object to represent a GPIO with the given \a gpio number and \a parent. */
Gpio::Gpio(QObject *parent, int gpio) : Gpio::Gpio(int gpio, QObject *parent) :
QObject(parent),m_gpio(gpio) QObject(parent),
m_gpio(gpio)
{ {
m_gpioDirectory = QDir(QString("/sys/class/gpio/gpio%1/").arg(QString::number(m_gpio)));
} }
/*! Destroys the Gpio object and unexports the GPIO. */ /*! Destroys and unexports the \l{Gpio}. */
Gpio::~Gpio() Gpio::~Gpio()
{ {
unexportGpio(); unexportGpio();
} }
/*! Returns true if this GPIO could be exported in the system file "/sys/class/gpio/export". */ /*! Returns true if the directory \tt {/sys/class/gpio} does exist. */
bool Gpio::isAvailable()
{
return QDir("/sys/class/gpio").exists();
}
/*! Returns true if this \l{Gpio} could be exported in the system file \tt {/sys/class/gpio/export}. */
bool Gpio::exportGpio() bool Gpio::exportGpio()
{ {
unexportGpio(); QFile exportFile("/sys/class/gpio/export");
if (!exportFile.open(QIODevice::WriteOnly)) {
char buf[64]; qCWarning(dcHardware()) << "Could not export GPIO" << m_gpio;
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
//qCWarning(dcHardware) << "could not open /sys/class/gpio/export";
return false; return false;
} }
ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); QTextStream out(&exportFile);
if(write(fd, buf, len) != len){ out << m_gpio;
qCWarning(dcHardware) << "could not write to gpio (export)"; exportFile.close();
close(fd);
return false;
}
close(fd);
return true; return true;
} }
/*! Returns true if this GPIO could be unexported in the system file "/sys/class/gpio/unexport". */ /*! Returns true if this \l{Gpio} could be unexported in the system file \tt {/sys/class/gpio/unexport}. */
bool Gpio::unexportGpio() bool Gpio::unexportGpio()
{ {
char buf[64]; QFile unexportFile("/sys/class/gpio/unexport");
if (!unexportFile.open(QIODevice::WriteOnly)) {
int fd = open("/sys/class/gpio/unexport", O_WRONLY); qCWarning(dcHardware()) << "Could not unexport GPIO" << m_gpio;
if (fd < 0) {
//qCWarning(dcHardware) << "could not open /sys/class/gpio/unexport";
return false; return false;
} }
ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); QTextStream out(&unexportFile);
if(write(fd, buf, len) != len){ out << m_gpio;
//qCWarning(dcHardware) << "could not write to gpio (unexport)"; unexportFile.close();
close(fd);
return false;
}
close(fd);
return true; return true;
} }
/*! Returns true if the file of this GPIO could be opend.*/ /*! Returns true if the \a direction of this GPIO could be set. */
int Gpio::openGpio() bool Gpio::setDirection(Gpio::Direction direction)
{ {
char buf[64]; QFile directionFile(m_gpioDirectory.path() + "/direction");
if (!directionFile.open(QIODevice::WriteOnly)) {
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio); qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "direction file.";
int fd = open(buf, O_RDONLY | O_NONBLOCK );
if (fd < 0) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/direction";
return fd;
}
return fd;
}
/*! Returns true if the direction \a dir of this GPIO could be set correctly.
*
* Possible directions are:
*
* \table
* \header
* \li {2,1} Pin directions
* \row
* \li 0
* \li INPUT
* \row
* \li 1
* \li OUTPUT
* \endtable
*/
bool Gpio::setDirection(int dir)
{
char buf[64];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", m_gpio);
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/direction";
return false; return false;
} }
if(dir == INPUT){
if(write(fd, "in", 3) != 3){ QTextStream out(&directionFile);
qCWarning(dcHardware) << "could not write to gpio (set INPUT)"; switch (direction) {
close(fd); case DirectionInput:
return false; out << "in";
} break;
m_dir = INPUT; case DirectionOutput:
close(fd); out << "out";
return true; break;
default:
directionFile.close();
return false;
} }
if(dir == OUTPUT){
if(write(fd, "out", 4) != 4){ directionFile.close();
qCWarning(dcHardware) << "could not write to gpio (set OUTPUT)"; return true;
close(fd); }
return false;
} /*! Returns the direction of this \l{Gpio}. */
m_dir = OUTPUT; Gpio::Direction Gpio::direction()
close(fd); {
return true; QFile directionFile(m_gpioDirectory.path() + "/direction");
if (!directionFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "direction file.";
return Gpio::DirectionInvalid;
} }
close(fd);
QString direction;
QTextStream in(&directionFile);
in >> direction;
directionFile.close();
if (direction == "in") {
m_direction = DirectionInput;
return Gpio::DirectionInput;
} else if (direction == "out") {
m_direction = DirectionOutput;
return Gpio::DirectionOutput;
}
return Gpio::DirectionInvalid;
}
/*! Returns true if the digital \a value of this \l{Gpio} could be set correctly. */
bool Gpio::setValue(Gpio::Value value)
{
if (value == Gpio::ValueInvalid || m_direction == Gpio::DirectionInput)
return false;
QFile valueFile(m_gpioDirectory.path() + "/value");
if (!valueFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "value file.";
return false;
}
QTextStream out(&valueFile);
switch (value) {
case ValueLow:
out << "0";
break;
case ValueHigh:
out << "1";
break;
default:
valueFile.close();
return false;
}
valueFile.close();
return true;
}
/*! Returns the current digital value of this \l{Gpio}. */
Gpio::Value Gpio::value()
{
QFile valueFile(m_gpioDirectory.path() + "/value");
if (!valueFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "value file.";
return Gpio::ValueInvalid;
}
QString value;
QTextStream in(&valueFile);
in >> value;
valueFile.close();
if (value == "0") {
return Gpio::ValueLow;
} else if (value == "1") {
return Gpio::ValueHigh;
}
return Gpio::ValueInvalid;
}
/*! This method allows to invert the logic of this \l{Gpio}. Returns true, if the GPIO could be set \a activeLow. */
bool Gpio::setActiveLow(bool activeLow)
{
QFile activeLowFile(m_gpioDirectory.path() + "/active_low");
if (!activeLowFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "active_low file.";
return false;
}
QTextStream out(&activeLowFile);
if (activeLow) {
out << "0";
} else {
out << "1";
}
activeLowFile.close();
return true;
}
/*! Returns true if the logic of this \l{Gpio} is inverted (1 = low, 0 = high). */
bool Gpio::activeLow()
{
QFile activeLowFile(m_gpioDirectory.path() + "/active_low");
if (!activeLowFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "active_low file.";
return false;
}
QString value;
QTextStream in(&activeLowFile);
in >> value;
activeLowFile.close();
if (value == "0")
return true;
return false; return false;
} }
/*! Returns the direction of this GPIO.
* \sa setDirection()
*/
int Gpio::getDirection()
{
return m_dir;
}
/*! Returns true if the digital \a value of the GPIO could be set correctly.
*
* Possible \a value 's are:
*
* \table
* \header
* \li {2,1} Pin value
* \row
* \li 0
* \li LOW
* \row
* \li 1
* \li HIGH
* \endtable
*/
bool Gpio::setValue(unsigned int value)
{
// check if gpio is a output
if( m_dir == OUTPUT){
char buf[64];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio);
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/value";
return false;
}
if(value == LOW){
if(write(fd, "0", 2) != 2){
qCWarning(dcHardware) << "could not write to gpio (set LOW)";
close(fd);
return false;
}
close(fd);
return true;
}
if(value == HIGH){
if(write(fd, "1", 2) != 2){
qCWarning(dcHardware) << "could not write to gpio (set HIGH)";
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
}else{
qCWarning(dcHardware) << "Gpio" << m_gpio << "is not an OUTPUT.";
return false;
}
}
/*! Returns the current digital value of the GPIO.
*
* Possible values are:
*
* \table
* \header
* \li {2,1} Pin directions
* \row
* \li 0
* \li LOW
* \row
* \li 1
* \li HIGH
* \endtable
*/
int Gpio::getValue()
{
char buf[64];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio);
int fd = open(buf, O_RDONLY);
if (fd < 0) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/value";
return -1;
}
char ch;
int value = -1;
ssize_t len = read(fd, &ch, 1);
if(len != 1){
close(fd);
return -1;
}
if (ch != '0') {
value = 1;
}else{
value = 0;
}
close(fd);
return value;
}
/*! Returns true if the \a edge of this GPIO could be set correctly. The \a edge parameter specifies, /*! Returns true if the \a edge of this GPIO could be set correctly. The \a edge parameter specifies,
* when an interrupt occurs. * when an interrupt occurs. */
* bool Gpio::setEdgeInterrupt(Gpio::Edge edge)
* Possible values are:
*
* \table
* \header
* \li {2,1} Edge possibilitys
* \row
* \li 0
* \li EDGE_FALLING
* \row
* \li 1
* \li EDGE_RISING
* \row
* \li 2
* \li EDGE_BOTH
* \endtable
*/
bool Gpio::setEdgeInterrupt(int edge)
{ {
char buf[64]; if (m_direction == Gpio::DirectionOutput) {
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/edge", m_gpio); qCWarning(dcHardware()) << "Could not set edge interrupt, GPIO is configured as an output.";
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/edge";
return false; return false;
} }
if(edge == EDGE_FALLING){ QFile edgeFile(m_gpioDirectory.path() + "/edge");
if(write(fd, "falling", 8) != 8){ if (!edgeFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware) << "could not write to gpio (set EDGE_FALLING)"; qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "edge file.";
close(fd);
return false;
}
close(fd);
return true;
}
if(edge == EDGE_RISING){
if(write(fd, "rising", 7) != 7){
qCWarning(dcHardware) << "could not write to gpio (set EDGE_RISING)";
close(fd);
return false;
}
close(fd);
return true;
}
if(edge == EDGE_BOTH){
if(write(fd, "both", 5) != 5){
qCWarning(dcHardware) << "could not write to gpio (set EDGE_BOTH)";
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
}
/*! This method allows to invert the logic of this GPIO.
* Returns true, if the GPIO could be set \a activeLow.
*/
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) {
qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/active_low";
return false; return false;
} }
if(activeLow){ QTextStream out(&edgeFile);
if(write(fd, "0", 2) != 2){ switch (edge) {
qCWarning(dcHardware) << "could not write to gpio (set Active LOW)"; case EdgeFalling:
close(fd); out << "falling";
return false; break;
} case EdgeRising:
close(fd); out << "rising";
return true; break;
case EdgeBoth:
out << "both";
break;
case EdgeNone:
out << "none";
break;
default:
return false;
} }
if(!activeLow){
if(write(fd, "1", 2) != 2){ edgeFile.close();
qCWarning(dcHardware) << "could not write to gpio (set Active HIGH)"; return true;
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
} }
/*! Returns the number of this GPIO. /*! Returns the edge interrupt of this \l{Gpio}. */
* \sa Gpio::Gpio() Gpio::Edge Gpio::edgeInterrupt()
*/ {
int Gpio::gpioNumber() QFile edgeFile(m_gpioDirectory.path() + "/edge");
if (!edgeFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "edge file.";
return Gpio::EdgeNone;
}
QString edge;
QTextStream in(&edgeFile);
in >> edge;
edgeFile.close();
if (edge.contains("falling")) {
return Gpio::EdgeFalling;
} else if (edge.contains("rising")) {
return Gpio::EdgeRising;
} else if (edge.contains("both")) {
return Gpio::EdgeBoth;
} else if (edge.contains("none")) {
return Gpio::EdgeNone;
}
return Gpio::EdgeNone;
}
/*! Returns the number of this \l{Gpio}. */
int Gpio::gpioNumber() const
{ {
return m_gpio; return m_gpio;
} }
/*! Returns true if the directory /sys/class/gpio does exist.
*/ QDebug operator<<(QDebug d, Gpio *gpio)
bool Gpio::isAvailable()
{ {
QDir gpioDirectory("/sys/class/gpio"); d << "-----------------------------------";
return gpioDirectory.exists(); d << "\n--> gpio" << gpio->gpioNumber() << ":";
d << "\n------------------";
if (gpio->direction() == Gpio::DirectionInput) {
d << "\n direction: input";
} else if (gpio->direction() == Gpio::DirectionOutput) {
d << "\n direction: output";
}
d << "\n value:" << gpio->value();
d << "\n active low:" << gpio->activeLow();
switch (gpio->edgeInterrupt()) {
case Gpio::EdgeFalling:
d << "\n edge interrupt:" << "falling";
break;
case Gpio::EdgeRising:
d << "\n edge interrupt:" << "rising";
break;
case Gpio::EdgeBoth:
d << "\n edge interrupt:" << "both";
break;
case Gpio::EdgeNone:
d << "\n edge interrupt:" << "none";
break;
default:
break;
}
d << "\n-----------------------------------\n";
return d;
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> * * Copyright (C) 2015 -2016 Simon Stürz <simon.stuerz@guh.guru> *
* * * *
* This file is part of guh. * * This file is part of guh. *
* * * *
@ -22,86 +22,65 @@
#define GPIO_H #define GPIO_H
#include <QObject> #include <QObject>
#include <QThread> #include <QDebug>
#include <QMutex>
#include <QMutexLocker>
#include <QDir> #include <QDir>
#include <QFile>
#include <QTextStream>
#include "libguh.h" #include "libguh.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#define INPUT 0
#define OUTPUT 1
#define LOW 0
#define HIGH 1
#define EDGE_FALLING 0
#define EDGE_RISING 1
#define EDGE_BOTH 2
/**********************************
* 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 | |
* |___________|__________|__________|
*
**********************************
*/
class LIBGUH_EXPORT Gpio : public QObject class LIBGUH_EXPORT Gpio : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Gpio(QObject *parent = 0, int gpio = 0); enum Direction {
DirectionInput,
DirectionOutput,
DirectionInvalid
};
enum Value {
ValueLow = 0,
ValueHigh = 1,
ValueInvalid = -1
};
enum Edge {
EdgeFalling,
EdgeRising,
EdgeBoth,
EdgeNone
};
explicit Gpio(int gpio = 0, QObject *parent = 0);
~Gpio(); ~Gpio();
static bool isAvailable();
bool exportGpio(); bool exportGpio();
bool unexportGpio(); bool unexportGpio();
int openGpio(); bool setDirection(Gpio::Direction direction);
bool setDirection(int dir); Gpio::Direction direction();
int getDirection();
bool setValue(unsigned int value); bool setValue(Gpio::Value value);
int getValue(); Gpio::Value value();
bool setEdgeInterrupt(int edge);
bool setActiveLow(bool activeLow); bool setActiveLow(bool activeLow);
bool activeLow();
int gpioNumber(); bool setEdgeInterrupt(Gpio::Edge edge);
bool isAvailable(); Gpio::Edge edgeInterrupt();
int gpioNumber() const;
private: private:
int m_gpio; int m_gpio;
int m_dir; Gpio::Direction m_direction;
QDir m_gpioDirectory;
}; };
QDebug operator<< (QDebug d, Gpio *gpio);
#endif // GPIO_H #endif // GPIO_H

View File

@ -19,246 +19,144 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*! /*!
\class GpioMonitor \class GpioMonitor
\brief The GpioMonitor class allows to monitor GPIOs. \brief The GpioMonitor class allows to monitor GPIOs.
\ingroup hardware \ingroup hardware
\inmodule libguh \inmodule libguh
An instance of this class creates a thread, which monitors each of the added GPIOs. The object An instance of this class creates a thread, which monitors each of the added GPIOs. The object
emits a signal if one of the added GPIOs changes its value. The GpioMonitor configures a GPIO as an emits a signal if one of the added GPIOs changes its value. The GpioMonitor configures a GPIO as an
input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}). input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}).
\chapter Example \chapter Example
Following example shows how to use the GpioMonitor class for a button on the Raspberry Pi. There are two possibilitys Following example shows how to use the GpioMonitor class for a button on the Raspberry Pi. There are two possibilitys
to connect a button. Following picture shows the schematics: to connect a button. Following picture shows the schematics:
\image Raspberry_Pi_Button_Example.png "Raspberry Pi button example" \image Raspberry_Pi_Button_Example.png "Raspberry Pi button example"
Button A represents a clean solutin with a 10 k\unicode{0x2126} resistor (set up as activeLow = false). Button A represents a clean solutin with a 10 k\unicode{0x2126} resistor (set up as activeLow = false).
Button B represents a "dirty" solution, were the 3.3V will be directly connected to the GPIO if the button is pressed (set activeLow = true). Button B represents a "dirty" solution, were the 3.3V will be directly connected to the GPIO if the button is pressed (set activeLow = true).
Here is the code example for a button class: Here is the code example for a button class:
\code
Button::Button(QObject *parent) :
QObject(parent)
{
m_button = new GpioMonitor(110, this);
connect(m_button, &GpioMonitor::valueChanged, this, &Button::stateChanged);
}
\tt{guhbutton.h} bool Button::init()
\code {
#include <QObject> return m_button->enable();
#include <QDebug> }
#include <QTimer>
#include "hardware/gpiomonitor.h" void Button::stateChanged(const bool &value)
{
class GuhButton : public QObject if (m_pressed != value) {
{ m_pressed = value;
Q_OBJECT if (value) {
public: emit buttonPressed();
explicit GuhButton(QObject *parent = 0, int gpio = 4); } else {
bool enable(); emit buttonReleased();
void disable(); }
}
private: }
GpioMonitor *m_monitor; \endcode
int m_gpioPin;
Gpio *m_gpio;
bool m_buttonPressed;
QTimer *m_longpressedTimer;
QTimer *m_debounceTimer;
signals:
void buttonPressed();
void buttonReleased();
void buttonLongPressed();
private slots:
void gpioChanged(const int &gpioPin, const int &value);
};
\endcode
\tt{guhbutton.cpp}
\code
#include "guhbutton.h"
GuhButton::GuhButton(QObject *parent, int gpio) :
QObject(parent), m_gpioPin(gpio)
{
m_buttonPressed = false;
}
bool GuhButton::enable()
{
qDebug() << "setup button on GPIO " << m_gpioPin;
m_monitor = new GpioMonitor(this);
m_gpio = new Gpio(this, m_gpioPin);
if(!m_monitor->addGpio(m_gpio, false)){
return false;
}
connect(m_monitor, &GpioMonitor::changed, this, &GuhButton::gpioChanged);
// Timer to generate the long pressed signal
m_longpressedTimer = new QTimer(this);
m_longpressedTimer->setInterval(500);
m_longpressedTimer->setSingleShot(true);
connect(m_longpressedTimer, &QTimer::timeout, this, &GuhButton::buttonLongPressed);
// Timer to debounce the button
m_debounceTimer = new QTimer(this);
m_debounceTimer->setSingleShot(true);
m_debounceTimer->setInterval(50);
m_monitor->enable();
return true;
}
void GuhButton::disable()
{
m_monitor->disable();
}
void GuhButton::gpioChanged(const int &gpioPin, const int &value)
{
if (gpioPin == m_gpioPin){
if(m_debounceTimer->isActive()){
return;
}
// check button state
bool buttonState = !QVariant(value).toBool();
if (m_buttonPressed != buttonState) {
if (buttonState) {
emit buttonPressed();
m_longpressedTimer->start();
m_debounceTimer->start();
} else {
emit buttonReleased();
m_longpressedTimer->stop();
}
m_buttonPressed = buttonState;
}
}
}
\endcode
*/ */
/*! \fn void GpioMonitor::changed(const int &gpioPin, const int &value); /*! \fn void GpioMonitor::valueChanged(const bool &value);
* This signal will be emited, if one of the monitored \l{Gpio}{Gpios} changed his \a value. The \a gpioPin * This signal will be emited, if the monitored \l{Gpio}{Gpios} changed his \a value. */
* paramter describes which \l{Gpio} changed his \a value.
* \sa Gpio::gpioNumber()
*/
#include "gpiomonitor.h" #include "gpiomonitor.h"
#include "loggingcategories.h" #include "loggingcategories.h"
/*! Constructs a \l{GpioMonitor} object with the given \a parent. */ /*! Constructs a \l{GpioMonitor} object with the given \a gpio number and \a parent. */
GpioMonitor::GpioMonitor(QObject *parent) : GpioMonitor::GpioMonitor(int gpio, QObject *parent) :
QThread(parent) QObject(parent),
m_gpioNumber(gpio)
{ {
m_valueFile.setFileName("/sys/class/gpio/gpio" + QString::number(m_gpioNumber) + "/value");
} }
/*! Destructs the object of this \l{GpioMonitor}.*/ /*! Returns true if this \l{GpioMonitor} could be enabled successfully. With the \a activeLow parameter the values can be inverted.
GpioMonitor::~GpioMonitor() With the \a edgeInterrupt parameter the interrupt type can be specified. */
bool GpioMonitor::enable(bool activeLow, Gpio::Edge edgeInterrupt)
{ {
foreach (Gpio* gpio, m_gpioList) { if (!Gpio::isAvailable())
gpio->unexportGpio(); return false;
}
quit();
wait();
deleteLater();
}
/*! Starts the \l{GpioMonitor}. While the \l{GpioMonitor} is running there can not be added new \l{Gpio}{Gpios}. m_gpio = new Gpio(m_gpioNumber, this);
* \sa disable(), */ if (!m_gpio->exportGpio() ||
void GpioMonitor::enable() !m_gpio->setDirection(Gpio::DirectionInput) ||
{ !m_gpio->setActiveLow(activeLow) ||
m_enabledMutex.lock(); !m_gpio->setEdgeInterrupt(edgeInterrupt)) {
m_enabled = true; qDebug() << "ERROR: while initializing GPIO" << m_gpio->gpioNumber();
m_enabledMutex.unlock();
start();
}
/*! Stops the \l{GpioMonitor}. No changes on the \l{Gpio} will be recognized.*/
void GpioMonitor::disable()
{
m_enabledMutex.lock();
m_enabled = false;
m_enabledMutex.unlock();
}
/*! Adds the given \l{Gpio} \a gpio to the monitor. This function can only be called if the monitor is not running.
* The given \a gpio will be configured as \a activeLow.
* Return true if the gpio could be added and set up correctly.
* \sa Gpio::setActiveLow(), */
bool GpioMonitor::addGpio(Gpio *gpio, bool activeLow)
{
if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(activeLow)) {
return false; return false;
} }
m_gpioListMutex.lock();
m_gpioList.append(gpio); if (!m_valueFile.open(QFile::ReadOnly)) {
m_gpioListMutex.unlock(); qWarning() << "ERROR: could not open value file for gpio monitor" << m_gpio->gpioNumber();
return false;
}
m_notifier = new QSocketNotifier(m_valueFile.handle(), QSocketNotifier::Exception);
connect(m_notifier, &QSocketNotifier::activated, this, &GpioMonitor::readyReady);
m_notifier->setEnabled(true);
return true; return true;
} }
/*! Returns the list of \l{Gpio}{Gpios} which currently are monitored. /*! Disables this \l{GpioMonitor}. */
* \sa addGpio(), */ void GpioMonitor::disable()
QList<Gpio *> GpioMonitor::gpioList()
{ {
m_gpioListMutex.lock(); delete m_notifier;
QList<Gpio*> gpioList = m_gpioList; delete m_gpio;
m_gpioListMutex.unlock();
return gpioList; m_notifier = 0;
m_gpio = 0;
m_valueFile.close();
} }
/*! This method represents the reimplementation of the virtual void QThread::run() method. This method will be called from /*! Returns true if this \l{GpioMonitor} is running. */
* QThread by calling the method void QThread::start(). Never call this method directly. bool GpioMonitor::isRunning() const
* \sa enable(), */
void GpioMonitor::run()
{ {
struct pollfd *fds; if (!m_notifier) {
char val; return false;
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(); return m_notifier->isEnabled();
}
bool enabled = true;
/*! Returns the current value of this \l{GpioMonitor}. */
m_enabledMutex.lock(); bool GpioMonitor::value() const
m_enabled = true; {
m_enabledMutex.unlock(); return m_currentValue;
}
while (enabled) {
m_gpioListMutex.lock(); /*! Returns the \l{Gpio} of this \l{GpioMonitor}. */
ret = poll(fds, m_gpioList.size(), 2000); Gpio *GpioMonitor::gpio()
{
if (ret > 0) { return m_gpio;
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); void GpioMonitor::readyReady(const int &ready)
retVal = read(fds[i].fd, &val, 1); {
Q_UNUSED(ready)
emit changed(m_gpioList[i]->gpioNumber(), m_gpioList[i]->getValue());
m_valueFile.seek(0);
if (retVal < 0) { QByteArray data = m_valueFile.readAll();
qCWarning(dcHardware) << "GpioMonitor poll failed";
} bool value = false;
} if (data[0] == '1') {
} value = true;
} else if (ret < 0) { } else if (data[0] == '0') {
qCWarning(dcHardware) << "poll failed: " << errno; value = false;
} } else {
m_gpioListMutex.unlock(); return;
}
m_enabledMutex.lock();
enabled = m_enabled; m_currentValue = value;
m_enabledMutex.unlock(); emit valueChanged(value);
}
free(fds);
} }

View File

@ -21,41 +21,41 @@
#ifndef GPIOMONITOR_H #ifndef GPIOMONITOR_H
#define GPIOMONITOR_H #define GPIOMONITOR_H
#include <QThread> #include <QObject>
#include <QDebug> #include <QDebug>
#include <fcntl.h> #include <QSocketNotifier>
#include <stdio.h> #include <QFile>
#include <poll.h>
#include <errno.h>
#include "libguh.h" #include "libguh.h"
#include "hardware/gpio.h" #include "gpio.h"
class LIBGUH_EXPORT GpioMonitor : public QThread class LIBGUH_EXPORT GpioMonitor : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GpioMonitor(QObject *parent = 0); explicit GpioMonitor(int gpio, QObject *parent = 0);
~GpioMonitor();
void enable(); bool enable(bool activeLow = false, Gpio::Edge edgeInterrupt = Gpio::EdgeBoth);
void disable(); void disable();
bool addGpio(Gpio *gpio, bool activeLow);
QList<Gpio*> gpioList();
bool isRunning() const;
bool value() const;
Gpio* gpio();
private: private:
QMutex m_enabledMutex; int m_gpioNumber;
bool m_enabled; Gpio *m_gpio;
QSocketNotifier *m_notifier;
QMutex m_gpioListMutex; QFile m_valueFile;
QList<Gpio*> m_gpioList; bool m_currentValue;
protected:
void run();
signals: signals:
void changed(const int &gpioPin, const int &value); void valueChanged(const bool &value);
private slots:
void readyReady(const int &ready);
}; };

280
libguh/hardware/pwm.cpp Normal file
View File

@ -0,0 +1,280 @@
#include "pwm.h"
#include "loggingcategories.h"
Pwm::Pwm(int chipNumber, QObject *parent) :
QObject(parent),
m_chipNumber(chipNumber),
m_period(0),
m_dutyCycle(0)
{
m_pwmDirectory = QDir("/sys/class/pwm/pwmchip" + QString::number(chipNumber) + "/");
}
Pwm::~Pwm()
{
unexportPwm();
}
bool Pwm::isAvailable()
{
QDir pwmDirectory("/sys/class/pwm");
return pwmDirectory.exists() && !pwmDirectory.entryList().isEmpty();
}
bool Pwm::exportPwm()
{
QFile exportFile(m_pwmDirectory.path() + "/export");
if (!exportFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not export PWM" << m_chipNumber;
return false;
}
QTextStream out(&exportFile);
out << 0;
exportFile.close();
return true;
}
bool Pwm::enable()
{
QFile enableFile(m_pwmDirectory.path() + "/pwm0/enable");
if (!enableFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not enable PWM" << m_chipNumber;
return false;
}
QTextStream out(&enableFile);
out << 1;
enableFile.close();
return true;
}
bool Pwm::disable()
{
QFile enableFile(m_pwmDirectory.path() + "/pwm0/enable");
if (!enableFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not disable PWM" << m_chipNumber;
return false;
}
QTextStream out(&enableFile);
out << 0;
enableFile.close();
return true;
}
bool Pwm::isEnabled()
{
QFile enableFile(m_pwmDirectory.path() + "/pwm0/enable");
if (!enableFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "ERROR: could not read" << enableFile.fileName();
return false;
}
QString value;
QTextStream in(&enableFile);
in >> value;
enableFile.close();
if (value == "1")
return true;
return false;
}
int Pwm::chipNumber()
{
return m_chipNumber;
}
long Pwm::period()
{
// period = active + inactive time
QFile periodFile(m_pwmDirectory.path() + "/pwm0/period");
if (!periodFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << periodFile.fileName();
return false;
}
QString value;
QTextStream in(&periodFile);
in >> value;
periodFile.close();
m_period = value.toLong();
return m_period;
}
bool Pwm::setPeriod(long nanoSeconds)
{
// the current duty cycle can not be greater than the period
if (dutyCycle() > nanoSeconds && !setDutyCycle(nanoSeconds))
return false;
// period = active + inactive time
QFile periodFile(m_pwmDirectory.path() + "/pwm0/period");
if (!periodFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << periodFile.fileName();
return false;
}
QTextStream out(&periodFile);
out << QString::number(nanoSeconds);
periodFile.close();
m_period = nanoSeconds;
return true;
}
double Pwm::frequency()
{
return (100000000.0 / (period() * 1000));
}
bool Pwm::setFrequency(double kHz)
{
// p = 1 / f
long nanoSeconds = (long)(100000000 / (kHz * 1000));
return setPeriod(nanoSeconds);
}
// active time
long Pwm::dutyCycle()
{
QFile dutyCycleFile(m_pwmDirectory.path() + "/pwm0/duty_cycle");
if (!dutyCycleFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << dutyCycleFile.fileName();
return false;
}
QString value;
QTextStream in(&dutyCycleFile);
in >> value;
dutyCycleFile.close();
m_dutyCycle = value.toLong();
return m_dutyCycle;
}
bool Pwm::setDutyCycle(long nanoSeconds)
{
// can not be greater than period or negative
if (nanoSeconds > m_period || nanoSeconds < 0) {
qCWarning(dcHardware()) << "ERROR: duty cycle has to be positive and smaller than the period";
return false;
}
QFile dutyCycleFile(m_pwmDirectory.path() + "/pwm0/duty_cycle");
if (!dutyCycleFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << dutyCycleFile.fileName();
return false;
}
QTextStream out(&dutyCycleFile);
out << QString::number(nanoSeconds);
dutyCycleFile.close();
m_dutyCycle = nanoSeconds;
return true;
}
Pwm::Polarity Pwm::polarity()
{
QFile polarityFile(m_pwmDirectory.path() + "/pwm0/polarity");
if (!polarityFile.open(QIODevice::ReadOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << polarityFile.fileName();
return PolarityInvalid;
}
QString value;
QTextStream in(&polarityFile);
in >> value;
polarityFile.close();
if (value == "normal") {
return PolarityNormal;
} else if(value == "inversed") {
return PolarityInversed;
}
return PolarityInvalid;
}
bool Pwm::setPolarity(Pwm::Polarity polarity)
{
if (polarity == Pwm::PolarityInvalid)
return false;
// Note: the polarity can only be changed if the pwm is disabled.
bool wasEnabled = isEnabled();
if (wasEnabled && !disable())
return false;
QFile polarityFile(m_pwmDirectory.path() + "/pwm0/polarity");
if (!polarityFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not open" << polarityFile.fileName();
return false;
}
QTextStream out(&polarityFile);
switch (polarity) {
case PolarityNormal:
out << "normal";
break;
case PolarityInversed:
out << "inversed";
break;
default:
break;
}
polarityFile.close();
if (wasEnabled)
enable();
return true;
}
int Pwm::percentage()
{
return (int)(dutyCycle() * (100.0 / period()) + 0.5);
}
bool Pwm::setPercentage(int percentage)
{
long nanoSeconds = period() * (percentage / 100.0);
return setDutyCycle(nanoSeconds);
}
bool Pwm::unexportPwm()
{
QFile unexportFile(m_pwmDirectory.path() + "/unexport");
if (!unexportFile.open(QIODevice::WriteOnly)) {
qCWarning(dcHardware()) << "ERROR: could not unexport PWM" << m_chipNumber;
return false;
}
QTextStream out(&unexportFile);
out << 0;
unexportFile.close();
return true;
}
QDebug operator<<(QDebug d, Pwm *pwm)
{
d << "-----------------------------------";
d << "\n--> pwm0 on pwmChip" << pwm->chipNumber() << ":";
d << "\n------------------";
d << "\n enabled:" << pwm->isEnabled();
d << "\n period:" << pwm->period() << "[ns]";
d << "\n duty cycle:" << pwm->dutyCycle() << "[ns]";
d << "\n frequency:" << pwm->frequency() << "[kHz]";
d << "\n percentage:" << pwm->percentage() << "[%]";
switch (pwm->polarity()) {
case Pwm::PolarityNormal:
d << "\n polarity:" << "normal";
break;
case Pwm::PolarityInversed:
d << "\n polarity:" << "inversed";
break;
default:
d << "\n polarity:" << "invalid";
break;
}
d << "\n-----------------------------------\n";
return d;
}

88
libguh/hardware/pwm.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef PWM_H
#define PWM_H
#include <QObject>
#include <QDebug>
#include <QFile>
#include <QDir>
#include "libguh.h"
/* i.MX6 PWMs
*
* /sys/class/pwm/pwmchip0 -> pwm1 (npwm = 1)
* /sys/class/pwm/pwmchip1 -> pwm2 (npwm = 1)
* /sys/class/pwm/pwmchip2 -> pwm3 (npwm = 1)
* /sys/class/pwm/pwmchip3 -> pwm4 (npwm = 1)
*
* each chip has 1 pwm ( -> pwm0)
*
* example:
* echo 0 > /sys/class/pwm/pwmchip1/export
*
* ls -l /sys/class/pwm/pwmchip1/pwm0/
* duty_cycle => nano seconds active time
* enable => 0 = disable, 1 = enable
* period => nano seconds active + inactive
* polarity => "normal" or "inversed"
*
* |<--------- period --------->|
*
* |<--duty cycle -->|
* 1_ _________________ _________________ _____
* | | | | |
* 0_ _| |___________| |___________| .......
*
*/
class LIBGUH_EXPORT Pwm : public QObject
{
Q_OBJECT
public:
enum Polarity {
PolarityNormal,
PolarityInversed,
PolarityInvalid
};
explicit Pwm(int chipNumber, QObject *parent = 0);
~Pwm();
static bool isAvailable();
bool exportPwm();
bool enable();
bool disable();
bool isEnabled();
int chipNumber();
long period();
bool setPeriod(long nanoSeconds);
double frequency();
bool setFrequency(double kHz);
long dutyCycle();
bool setDutyCycle(long nanoSeconds);
Pwm::Polarity polarity();
bool setPolarity(Pwm::Polarity polarity);
int percentage();
bool setPercentage(int percentage);
private:
int m_chipNumber;
long m_period;
long m_dutyCycle;
QDir m_pwmDirectory;
bool unexportPwm();
};
QDebug operator<< (QDebug d, Pwm *pwm);
#endif // PWM_H

View File

@ -42,16 +42,13 @@
\note: Radio 433 on GPIO's is by default disabled. If you want to enable it, you need to compile the source with the qmake config \tt{CONFIG+=radio433gpio} \note: Radio 433 on GPIO's is by default disabled. If you want to enable it, you need to compile the source with the qmake config \tt{CONFIG+=radio433gpio}
*/ */
/*! \fn void Radio433::dataReceived(QList<int> rawData)
This signal is emitted when the receiver recognized a signal. The \a rawData parameter describes the signal.
*/
#include "radio433.h" #include "radio433.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "guhsettings.h" #include "guhsettings.h"
#include "hardware/gpio.h"
#include <QFileInfo> #include <QFileInfo>
@ -63,14 +60,10 @@ Radio433::Radio433(QObject *parent) :
GuhSettings settings(GuhSettings::SettingsRoleGlobal); GuhSettings settings(GuhSettings::SettingsRoleGlobal);
qCDebug(dcHardware) << "Loading GPIO settings from:" << settings.fileName(); qCDebug(dcHardware) << "Loading GPIO settings from:" << settings.fileName();
settings.beginGroup("GPIO"); settings.beginGroup("GPIO");
int receiverGpioNumber = settings.value("rf433rx",27).toInt();
int transmitterGpioNumber = settings.value("rf433tx",22).toInt(); int transmitterGpioNumber = settings.value("rf433tx",22).toInt();
settings.endGroup(); settings.endGroup();
m_receiver = new Radio433Receiver(this, receiverGpioNumber);
m_transmitter = new Radio433Trasmitter(this, transmitterGpioNumber); m_transmitter = new Radio433Trasmitter(this, transmitterGpioNumber);
connect(m_receiver, &Radio433Receiver::readingChanged, this, &Radio433::readingChanged);
connect(m_receiver, &Radio433Receiver::dataReceived, this, &Radio433::dataReceived);
#endif #endif
m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this); m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this);
@ -81,7 +74,6 @@ Radio433::Radio433(QObject *parent) :
Radio433::~Radio433() Radio433::~Radio433()
{ {
#ifdef GPIO433 #ifdef GPIO433
m_receiver->quit();
m_transmitter->quit(); m_transmitter->quit();
#endif #endif
} }
@ -94,24 +86,19 @@ bool Radio433::enable()
#ifdef GPIO433 #ifdef GPIO433
// check if GPIOs are available // check if GPIOs are available
QFileInfo gpioFile("/sys/class/gpio/export"); if (Gpio::isAvailable()) {
if (gpioFile.exists()) {
// bool receiverAvailable = m_receiver->startReceiver();
// if (!receiverAvailable) {
// //qWarning() << "ERROR: radio 433 MHz receiver not available on GPIO's";
// }
// bool transmitterAvailable = m_transmitter->startTransmitter(); bool transmitterAvailable = m_transmitter->startTransmitter();
// if (!transmitterAvailable) { if (!transmitterAvailable) {
// //qWarning() << "ERROR: radio 433 MHz transmitter not available on GPIO's"; //qCWarning(dcHardware) << "ERROR: radio 433 MHz transmitter not available on GPIO's";
// } }
// if (!receiverAvailable && !transmitterAvailable) { if (!transmitterAvailable) {
// qWarning() << "--> Radio 433 MHz GPIO's not available."; qCWarning(dcHardware) << "--> Radio 433 MHz GPIO's not available.";
// return false; return false;
// } }
} }
qCDebug(dcDeviceManager) << "--> Radio 433 MHz GPIO's enabled."; qCDebug(dcDeviceManager()) << "--> Radio 433 MHz GPIO's enabled.";
#endif #endif
return true; return true;
@ -121,22 +108,15 @@ bool Radio433::enable()
bool Radio433::disabel() bool Radio433::disabel()
{ {
m_brennenstuhlTransmitter->disable(); m_brennenstuhlTransmitter->disable();
#ifdef GPIO433
if (m_receiver->stopReceiver()) {
return true;
}
return false;
#endif
return true; return true;
} }
void Radio433::brennenstuhlAvailableChanged(const bool &available) void Radio433::brennenstuhlAvailableChanged(const bool &available)
{ {
if (available) { if (available) {
qCDebug(dcDeviceManager) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available."; qCDebug(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available.";
} else { } else {
qCWarning(dcHardware) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available."; qCWarning(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available.";
} }
} }

View File

@ -24,7 +24,6 @@
#include <QObject> #include <QObject>
#ifdef GPIO433 #ifdef GPIO433
#include "radio433receiver.h"
#include "radio433transmitter.h" #include "radio433transmitter.h"
#endif #endif
@ -43,15 +42,11 @@ public:
private: private:
#ifdef GPIO433 #ifdef GPIO433
Radio433Receiver *m_receiver;
Radio433Trasmitter *m_transmitter; Radio433Trasmitter *m_transmitter;
#endif #endif
Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter; Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter;
signals:
void dataReceived(QList<int> rawData);
private slots: private slots:
void brennenstuhlAvailableChanged(const bool &available); void brennenstuhlAvailableChanged(const bool &available);

View File

@ -52,17 +52,18 @@ void Radio433Trasmitter::run()
rawData = m_rawDataQueue.dequeue(); rawData = m_rawDataQueue.dequeue();
m_queueMutex.unlock(); m_queueMutex.unlock();
m_gpio->setValue(LOW); m_gpio->setValue(Gpio::ValueLow);
int flag=1; int flag=1;
foreach (int delay, rawData) { foreach (int delay, rawData) {
// 1 = High, 0 = Low // 1 = High, 0 = Low
m_gpio->setValue(flag %2); int value = flag %2;
m_gpio->setValue((Gpio::Value)value);
flag++; flag++;
usleep(delay); usleep(delay);
} }
m_gpio->setValue(LOW); m_gpio->setValue(Gpio::ValueLow);
} }
m_queueMutex.unlock(); m_queueMutex.unlock();
} }
@ -76,9 +77,9 @@ void Radio433Trasmitter::allowSending(bool sending)
bool Radio433Trasmitter::setUpGpio() bool Radio433Trasmitter::setUpGpio()
{ {
m_gpio = new Gpio(this,m_gpioPin); m_gpio = new Gpio(m_gpioPin, this);
if(!m_gpio->exportGpio() || !m_gpio->setDirection(OUTPUT) || !m_gpio->setValue(LOW)){ if(!m_gpio->exportGpio() || !m_gpio->setDirection(Gpio::DirectionOutput) || !m_gpio->setValue(Gpio::ValueLow)){
m_available = false; m_available = false;
return false; return false;
} }

View File

@ -28,7 +28,7 @@
#include <QDebug> #include <QDebug>
#include "libguh.h" #include "libguh.h"
#include "../gpio.h" #include "hardware/gpio.h"
class LIBGUH_EXPORT Radio433Trasmitter : public QThread class LIBGUH_EXPORT Radio433Trasmitter : public QThread

View File

@ -34,7 +34,6 @@ HEADERS += devicemanager.h \
hardware/gpiomonitor.h \ hardware/gpiomonitor.h \
hardware/radio433/radio433.h \ hardware/radio433/radio433.h \
hardware/radio433/radio433transmitter.h \ hardware/radio433/radio433transmitter.h \
hardware/radio433/radio433receiver.h \
hardware/radio433/radio433brennenstuhlgateway.h \ hardware/radio433/radio433brennenstuhlgateway.h \
network/upnpdiscovery/upnpdiscovery.h \ network/upnpdiscovery/upnpdiscovery.h \
network/upnpdiscovery/upnpdevice.h \ network/upnpdiscovery/upnpdevice.h \
@ -65,6 +64,7 @@ HEADERS += devicemanager.h \
types/ruleaction.h \ types/ruleaction.h \
types/ruleactionparam.h \ types/ruleactionparam.h \
types/statedescriptor.h \ types/statedescriptor.h \
hardware/pwm.h
SOURCES += devicemanager.cpp \ SOURCES += devicemanager.cpp \
@ -79,7 +79,6 @@ SOURCES += devicemanager.cpp \
hardware/gpiomonitor.cpp \ hardware/gpiomonitor.cpp \
hardware/radio433/radio433.cpp \ hardware/radio433/radio433.cpp \
hardware/radio433/radio433transmitter.cpp \ hardware/radio433/radio433transmitter.cpp \
hardware/radio433/radio433receiver.cpp \
hardware/radio433/radio433brennenstuhlgateway.cpp \ hardware/radio433/radio433brennenstuhlgateway.cpp \
network/upnpdiscovery/upnpdiscovery.cpp \ network/upnpdiscovery/upnpdiscovery.cpp \
network/upnpdiscovery/upnpdevice.cpp \ network/upnpdiscovery/upnpdevice.cpp \
@ -110,6 +109,7 @@ SOURCES += devicemanager.cpp \
types/ruleaction.cpp \ types/ruleaction.cpp \
types/ruleactionparam.cpp \ types/ruleactionparam.cpp \
types/statedescriptor.cpp \ types/statedescriptor.cpp \
hardware/pwm.cpp
# install plugininfo python script for libguh-dev # install plugininfo python script for libguh-dev

View File

@ -614,9 +614,6 @@ bool DevicePlugin::transmitData(int delay, QList<int> rawData, int repetitions)
switch (requiredHardware()) { switch (requiredHardware()) {
case DeviceManager::HardwareResourceRadio433: case DeviceManager::HardwareResourceRadio433:
return deviceManager()->m_radio433->sendData(delay, rawData, repetitions); return deviceManager()->m_radio433->sendData(delay, rawData, repetitions);
case DeviceManager::HardwareResourceRadio868:
qCDebug(dcDeviceManager) << "Radio868 not connected yet";
return false;
default: default:
qCWarning(dcDeviceManager) << "Unknown harware type. Cannot send."; qCWarning(dcDeviceManager) << "Unknown harware type. Cannot send.";
} }

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> * * Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.guru> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> * * Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* * * *
* This file is part of guh. * * This file is part of guh. *