From 4191b8f37c733e8f8a3d2bde4c0ebab9674f8302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 27 Apr 2016 13:28:04 +0200 Subject: [PATCH] renew gpio and pwm classes --- libguh/devicemanager.cpp | 3 - libguh/devicemanager.h | 13 +- libguh/hardware/gpio.cpp | 584 +++++++++--------- libguh/hardware/gpio.h | 99 ++- libguh/hardware/gpiomonitor.cpp | 324 ++++------ libguh/hardware/gpiomonitor.h | 42 +- libguh/hardware/pwm.cpp | 280 +++++++++ libguh/hardware/pwm.h | 88 +++ libguh/hardware/radio433/radio433.cpp | 46 +- libguh/hardware/radio433/radio433.h | 5 - .../hardware/radio433/radio433transmitter.cpp | 11 +- .../hardware/radio433/radio433transmitter.h | 2 +- libguh/libguh.pro | 4 +- libguh/plugin/deviceplugin.cpp | 3 - server/main.cpp | 2 +- 15 files changed, 846 insertions(+), 660 deletions(-) create mode 100644 libguh/hardware/pwm.cpp create mode 100644 libguh/hardware/pwm.h diff --git a/libguh/devicemanager.cpp b/libguh/devicemanager.cpp index d4b5d741..579946f6 100644 --- a/libguh/devicemanager.cpp +++ b/libguh/devicemanager.cpp @@ -40,8 +40,6 @@ No Resource required. \value HardwareResourceRadio433 Refers to the 433 MHz radio. - \value HardwareResourceRadio868 - Refers to the 868 MHz radio. \value HardwareResourceTimer 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. @@ -207,7 +205,6 @@ DeviceManager::DeviceManager(QObject *parent) : connect(&m_pluginTimer, &QTimer::timeout, this, &DeviceManager::timerEvent); m_radio433 = new Radio433(this); - connect(m_radio433, &Radio433::dataReceived, this, &DeviceManager::radio433SignalReceived); m_radio433->enable(); // TODO: error handling if no Radio433 detected (GPIO or network), disable radio433 plugins or something... diff --git a/libguh/devicemanager.h b/libguh/devicemanager.h index 435f80ca..0f654f6c 100644 --- a/libguh/devicemanager.h +++ b/libguh/devicemanager.h @@ -57,13 +57,12 @@ class LIBGUH_EXPORT DeviceManager : public QObject public: enum HardwareResource { - HardwareResourceNone = 0x00, - HardwareResourceRadio433 = 0x01, - HardwareResourceRadio868 = 0x02, - HardwareResourceTimer = 0x04, - HardwareResourceNetworkManager = 0x08, - HardwareResourceUpnpDisovery = 0x10, - HardwareResourceBluetoothLE = 0x20 + HardwareResourceNone = 0, + HardwareResourceRadio433 = 1, + HardwareResourceTimer = 2, + HardwareResourceNetworkManager = 4, + HardwareResourceUpnpDisovery = 8, + HardwareResourceBluetoothLE = 16 }; Q_DECLARE_FLAGS(HardwareResources, HardwareResource) diff --git a/libguh/hardware/gpio.cpp b/libguh/hardware/gpio.cpp index fdc703fe..98e40c8d 100644 --- a/libguh/hardware/gpio.cpp +++ b/libguh/hardware/gpio.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2015 -2016 Simon Stürz * * * * 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 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. +*/ - \chapter Example +/*! \enum Gpio::Direction - Following example shows how to initialize and interact with a GPIO. The GPIO will be configured as an input, - set active high and the edge interrupt will be set to EDGE_BOTH. + This enum type specifies the dirction a \l{Gpio}. - \code - Gpio *gpio = new Gpio(this, 22); - if (!gpio->exportGpio() || !gpio->setDirection(INPUT) || !gpio->setEdgeInterrupt(EDGE_BOTH) || !gpio->setActiveLow(true)) { - return; - } - int value = gpio->getValue(); - qDebug() << "value = " << value; - \endcode + \value DirectionInput + The \l{Gpio} is configured as \b input. + \value DirectionOutput + The \l{Gpio} is configured as \b output. + \value DirectionInvalid + The direction is not valid. +*/ - \chapter Raspberry Pi GPIOs - In following table is a list of all GPIO's of the Raspberry Pi Rev. 2.0: +/*! \enum Gpio::Value - \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 - In following table is a list of all GPIO's of the Beaglebone Black (\l{http://pix.cs.olemiss.edu/csci581/BBBlackGPIOMap.png}{Source}): +/*! \enum Gpio::Edge - \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 -/*! Constructs a \l{Gpio} object to represent a GPIO with the given \a gpio number and the \a parent. */ -Gpio::Gpio(QObject *parent, int gpio) : - QObject(parent),m_gpio(gpio) +/*! Constructs a \l{Gpio} object to represent a GPIO with the given \a gpio number and \a parent. */ +Gpio::Gpio(int gpio, QObject *parent) : + 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() { 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() { - unexportGpio(); - - char buf[64]; - - int fd = open("/sys/class/gpio/export", O_WRONLY); - if (fd < 0) { - //qCWarning(dcHardware) << "could not open /sys/class/gpio/export"; + QFile exportFile("/sys/class/gpio/export"); + if (!exportFile.open(QIODevice::WriteOnly)) { + qCWarning(dcHardware()) << "Could not export GPIO" << m_gpio; return false; } - ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); - if(write(fd, buf, len) != len){ - qCWarning(dcHardware) << "could not write to gpio (export)"; - close(fd); - return false; - } - close(fd); + QTextStream out(&exportFile); + out << m_gpio; + exportFile.close(); 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() { - char buf[64]; - - int fd = open("/sys/class/gpio/unexport", O_WRONLY); - if (fd < 0) { - //qCWarning(dcHardware) << "could not open /sys/class/gpio/unexport"; + QFile unexportFile("/sys/class/gpio/unexport"); + if (!unexportFile.open(QIODevice::WriteOnly)) { + qCWarning(dcHardware()) << "Could not unexport GPIO" << m_gpio; return false; } - ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio); - if(write(fd, buf, len) != len){ - //qCWarning(dcHardware) << "could not write to gpio (unexport)"; - close(fd); - return false; - } - close(fd); + QTextStream out(&unexportFile); + out << m_gpio; + unexportFile.close(); return true; } -/*! Returns true if the file of this GPIO could be opend.*/ -int Gpio::openGpio() +/*! Returns true if the \a direction of this GPIO could be set. */ +bool Gpio::setDirection(Gpio::Direction direction) { - char buf[64]; - - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", m_gpio); - - 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"; + QFile directionFile(m_gpioDirectory.path() + "/direction"); + if (!directionFile.open(QIODevice::WriteOnly)) { + qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "direction file."; return false; } - if(dir == INPUT){ - if(write(fd, "in", 3) != 3){ - qCWarning(dcHardware) << "could not write to gpio (set INPUT)"; - close(fd); - return false; - } - m_dir = INPUT; - close(fd); - return true; + + QTextStream out(&directionFile); + switch (direction) { + case DirectionInput: + out << "in"; + break; + case DirectionOutput: + out << "out"; + break; + default: + directionFile.close(); + return false; } - if(dir == OUTPUT){ - if(write(fd, "out", 4) != 4){ - qCWarning(dcHardware) << "could not write to gpio (set OUTPUT)"; - close(fd); - return false; - } - m_dir = OUTPUT; - close(fd); - return true; + + directionFile.close(); + return true; +} + +/*! Returns the direction of this \l{Gpio}. */ +Gpio::Direction Gpio::direction() +{ + 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; } -/*! 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, - * when an interrupt occurs. - * - * 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) + * when an interrupt occurs. */ +bool Gpio::setEdgeInterrupt(Gpio::Edge edge) { - char buf[64]; - snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/edge", m_gpio); - - int fd = open(buf, O_WRONLY); - if (fd < 0) { - qCWarning(dcHardware) << "could not open /sys/class/gpio" << m_gpio << "/edge"; + if (m_direction == Gpio::DirectionOutput) { + qCWarning(dcHardware()) << "Could not set edge interrupt, GPIO is configured as an output."; return false; } - if(edge == EDGE_FALLING){ - if(write(fd, "falling", 8) != 8){ - qCWarning(dcHardware) << "could not write to gpio (set EDGE_FALLING)"; - 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"; + QFile edgeFile(m_gpioDirectory.path() + "/edge"); + if (!edgeFile.open(QIODevice::WriteOnly)) { + qCWarning(dcHardware()) << "Could not open GPIO" << m_gpio << "edge file."; return false; } - if(activeLow){ - if(write(fd, "0", 2) != 2){ - qCWarning(dcHardware) << "could not write to gpio (set Active LOW)"; - close(fd); - return false; - } - close(fd); - return true; + QTextStream out(&edgeFile); + switch (edge) { + case EdgeFalling: + out << "falling"; + break; + case EdgeRising: + out << "rising"; + break; + case EdgeBoth: + out << "both"; + break; + case EdgeNone: + out << "none"; + break; + default: + return false; } - if(!activeLow){ - if(write(fd, "1", 2) != 2){ - qCWarning(dcHardware) << "could not write to gpio (set Active HIGH)"; - close(fd); - return false; - } - close(fd); - return true; - } - close(fd); - return false; + + edgeFile.close(); + return true; } -/*! Returns the number of this GPIO. - * \sa Gpio::Gpio() - */ -int Gpio::gpioNumber() +/*! Returns the edge interrupt of this \l{Gpio}. */ +Gpio::Edge Gpio::edgeInterrupt() +{ + 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; } -/*! Returns true if the directory /sys/class/gpio does exist. - */ -bool Gpio::isAvailable() + +QDebug operator<<(QDebug d, Gpio *gpio) { - QDir gpioDirectory("/sys/class/gpio"); - return gpioDirectory.exists(); + d << "-----------------------------------"; + 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; } diff --git a/libguh/hardware/gpio.h b/libguh/hardware/gpio.h index e7a3851f..19245215 100644 --- a/libguh/hardware/gpio.h +++ b/libguh/hardware/gpio.h @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stürz * + * Copyright (C) 2015 -2016 Simon Stürz * * * * This file is part of guh. * * * @@ -22,86 +22,65 @@ #define GPIO_H #include -#include -#include -#include +#include #include +#include +#include #include "libguh.h" -#include -#include -#include -#include -#include -#include -#include - -#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 { Q_OBJECT 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(); + static bool isAvailable(); + bool exportGpio(); bool unexportGpio(); - int openGpio(); - bool setDirection(int dir); - int getDirection(); + bool setDirection(Gpio::Direction direction); + Gpio::Direction direction(); - bool setValue(unsigned int value); - int getValue(); + bool setValue(Gpio::Value value); + Gpio::Value value(); - bool setEdgeInterrupt(int edge); bool setActiveLow(bool activeLow); + bool activeLow(); - int gpioNumber(); - bool isAvailable(); + bool setEdgeInterrupt(Gpio::Edge edge); + Gpio::Edge edgeInterrupt(); + + int gpioNumber() const; private: int m_gpio; - int m_dir; + Gpio::Direction m_direction; + QDir m_gpioDirectory; }; +QDebug operator<< (QDebug d, Gpio *gpio); + #endif // GPIO_H diff --git a/libguh/hardware/gpiomonitor.cpp b/libguh/hardware/gpiomonitor.cpp index 4204fe0b..d018e7a7 100644 --- a/libguh/hardware/gpiomonitor.cpp +++ b/libguh/hardware/gpiomonitor.cpp @@ -19,246 +19,144 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! - \class GpioMonitor - \brief The GpioMonitor class allows to monitor GPIOs. + \class GpioMonitor + \brief The GpioMonitor class allows to monitor GPIOs. - \ingroup hardware - \inmodule libguh + \ingroup hardware + \inmodule libguh - 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 - input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}). + 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 + input, with the edge interrupt EDGE_BOTH (\l{Gpio::setEdgeInterrupt()}{setEdgeInterrupt}). - \chapter Example - 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: + \chapter Example + 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: - \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 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 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). - 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} - \code - #include - #include - #include + bool Button::init() + { + return m_button->enable(); + } - #include "hardware/gpiomonitor.h" - - class GuhButton : public QObject - { - Q_OBJECT - public: - explicit GuhButton(QObject *parent = 0, int gpio = 4); - bool enable(); - void disable(); - - private: - GpioMonitor *m_monitor; - 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 + void Button::stateChanged(const bool &value) + { + if (m_pressed != value) { + m_pressed = value; + if (value) { + emit buttonPressed(); + } else { + emit buttonReleased(); + } + } + } + \endcode */ -/*! \fn void GpioMonitor::changed(const int &gpioPin, const int &value); - * This signal will be emited, if one of the monitored \l{Gpio}{Gpios} changed his \a value. The \a gpioPin - * paramter describes which \l{Gpio} changed his \a value. - * \sa Gpio::gpioNumber() - */ +/*! \fn void GpioMonitor::valueChanged(const bool &value); + * This signal will be emited, if the monitored \l{Gpio}{Gpios} changed his \a value. */ #include "gpiomonitor.h" #include "loggingcategories.h" -/*! Constructs a \l{GpioMonitor} object with the given \a parent. */ -GpioMonitor::GpioMonitor(QObject *parent) : - QThread(parent) +/*! Constructs a \l{GpioMonitor} object with the given \a gpio number and \a parent. */ +GpioMonitor::GpioMonitor(int gpio, QObject *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}.*/ -GpioMonitor::~GpioMonitor() +/*! Returns true if this \l{GpioMonitor} could be enabled successfully. With the \a activeLow parameter the values can be inverted. + With the \a edgeInterrupt parameter the interrupt type can be specified. */ +bool GpioMonitor::enable(bool activeLow, Gpio::Edge edgeInterrupt) { - foreach (Gpio* gpio, m_gpioList) { - gpio->unexportGpio(); - } - quit(); - wait(); - deleteLater(); -} + if (!Gpio::isAvailable()) + return false; -/*! Starts the \l{GpioMonitor}. While the \l{GpioMonitor} is running there can not be added new \l{Gpio}{Gpios}. - * \sa disable(), */ -void GpioMonitor::enable() -{ - m_enabledMutex.lock(); - m_enabled = true; - 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)) { + m_gpio = new Gpio(m_gpioNumber, this); + if (!m_gpio->exportGpio() || + !m_gpio->setDirection(Gpio::DirectionInput) || + !m_gpio->setActiveLow(activeLow) || + !m_gpio->setEdgeInterrupt(edgeInterrupt)) { + qDebug() << "ERROR: while initializing GPIO" << m_gpio->gpioNumber(); return false; } - m_gpioListMutex.lock(); - m_gpioList.append(gpio); - m_gpioListMutex.unlock(); + + if (!m_valueFile.open(QFile::ReadOnly)) { + 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; } -/*! Returns the list of \l{Gpio}{Gpios} which currently are monitored. - * \sa addGpio(), */ -QList GpioMonitor::gpioList() +/*! Disables this \l{GpioMonitor}. */ +void GpioMonitor::disable() { - m_gpioListMutex.lock(); - QList gpioList = m_gpioList; - m_gpioListMutex.unlock(); - return gpioList; + delete m_notifier; + delete m_gpio; + + 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 - * QThread by calling the method void QThread::start(). Never call this method directly. - * \sa enable(), */ -void GpioMonitor::run() +/*! Returns true if this \l{GpioMonitor} is running. */ +bool GpioMonitor::isRunning() const { - 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; + if (!m_notifier) { + return false; } - 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]->gpioNumber(), m_gpioList[i]->getValue()); - - if (retVal < 0) { - qCWarning(dcHardware) << "GpioMonitor poll failed"; - } - } - } - } else if (ret < 0) { - qCWarning(dcHardware) << "poll failed: " << errno; - } - m_gpioListMutex.unlock(); - - m_enabledMutex.lock(); - enabled = m_enabled; - m_enabledMutex.unlock(); - } - free(fds); + return m_notifier->isEnabled(); +} + +/*! Returns the current value of this \l{GpioMonitor}. */ +bool GpioMonitor::value() const +{ + return m_currentValue; +} + +/*! Returns the \l{Gpio} of this \l{GpioMonitor}. */ +Gpio *GpioMonitor::gpio() +{ + return m_gpio; +} + +void GpioMonitor::readyReady(const int &ready) +{ + Q_UNUSED(ready) + + m_valueFile.seek(0); + QByteArray data = m_valueFile.readAll(); + + bool value = false; + if (data[0] == '1') { + value = true; + } else if (data[0] == '0') { + value = false; + } else { + return; + } + + m_currentValue = value; + emit valueChanged(value); } diff --git a/libguh/hardware/gpiomonitor.h b/libguh/hardware/gpiomonitor.h index 5289d6c6..ea16f372 100644 --- a/libguh/hardware/gpiomonitor.h +++ b/libguh/hardware/gpiomonitor.h @@ -21,41 +21,41 @@ #ifndef GPIOMONITOR_H #define GPIOMONITOR_H -#include +#include #include -#include -#include -#include -#include +#include +#include #include "libguh.h" -#include "hardware/gpio.h" +#include "gpio.h" -class LIBGUH_EXPORT GpioMonitor : public QThread +class LIBGUH_EXPORT GpioMonitor : public QObject { Q_OBJECT + public: - explicit GpioMonitor(QObject *parent = 0); - ~GpioMonitor(); + explicit GpioMonitor(int gpio, QObject *parent = 0); - void enable(); + bool enable(bool activeLow = false, Gpio::Edge edgeInterrupt = Gpio::EdgeBoth); void disable(); - bool addGpio(Gpio *gpio, bool activeLow); - QList gpioList(); + bool isRunning() const; + bool value() const; + + Gpio* gpio(); private: - QMutex m_enabledMutex; - bool m_enabled; - - QMutex m_gpioListMutex; - QList m_gpioList; - -protected: - void run(); + int m_gpioNumber; + Gpio *m_gpio; + QSocketNotifier *m_notifier; + QFile m_valueFile; + bool m_currentValue; signals: - void changed(const int &gpioPin, const int &value); + void valueChanged(const bool &value); + +private slots: + void readyReady(const int &ready); }; diff --git a/libguh/hardware/pwm.cpp b/libguh/hardware/pwm.cpp new file mode 100644 index 00000000..41eebdc0 --- /dev/null +++ b/libguh/hardware/pwm.cpp @@ -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; +} diff --git a/libguh/hardware/pwm.h b/libguh/hardware/pwm.h new file mode 100644 index 00000000..94134fc9 --- /dev/null +++ b/libguh/hardware/pwm.h @@ -0,0 +1,88 @@ +#ifndef PWM_H +#define PWM_H + +#include +#include +#include +#include + +#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 diff --git a/libguh/hardware/radio433/radio433.cpp b/libguh/hardware/radio433/radio433.cpp index 6546a710..207f13a0 100644 --- a/libguh/hardware/radio433/radio433.cpp +++ b/libguh/hardware/radio433/radio433.cpp @@ -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} - */ -/*! \fn void Radio433::dataReceived(QList rawData) - This signal is emitted when the receiver recognized a signal. The \a rawData parameter describes the signal. -*/ #include "radio433.h" #include "loggingcategories.h" #include "guhsettings.h" +#include "hardware/gpio.h" #include @@ -63,14 +60,10 @@ Radio433::Radio433(QObject *parent) : GuhSettings settings(GuhSettings::SettingsRoleGlobal); qCDebug(dcHardware) << "Loading GPIO settings from:" << settings.fileName(); settings.beginGroup("GPIO"); - int receiverGpioNumber = settings.value("rf433rx",27).toInt(); int transmitterGpioNumber = settings.value("rf433tx",22).toInt(); settings.endGroup(); - m_receiver = new Radio433Receiver(this, receiverGpioNumber); m_transmitter = new Radio433Trasmitter(this, transmitterGpioNumber); - connect(m_receiver, &Radio433Receiver::readingChanged, this, &Radio433::readingChanged); - connect(m_receiver, &Radio433Receiver::dataReceived, this, &Radio433::dataReceived); #endif m_brennenstuhlTransmitter = new Radio433BrennenstuhlGateway(this); @@ -81,7 +74,6 @@ Radio433::Radio433(QObject *parent) : Radio433::~Radio433() { #ifdef GPIO433 - m_receiver->quit(); m_transmitter->quit(); #endif } @@ -94,24 +86,19 @@ bool Radio433::enable() #ifdef GPIO433 // check if GPIOs are available - QFileInfo gpioFile("/sys/class/gpio/export"); - if (gpioFile.exists()) { -// bool receiverAvailable = m_receiver->startReceiver(); -// if (!receiverAvailable) { -// //qWarning() << "ERROR: radio 433 MHz receiver not available on GPIO's"; -// } + if (Gpio::isAvailable()) { -// bool transmitterAvailable = m_transmitter->startTransmitter(); -// if (!transmitterAvailable) { -// //qWarning() << "ERROR: radio 433 MHz transmitter not available on GPIO's"; -// } + bool transmitterAvailable = m_transmitter->startTransmitter(); + if (!transmitterAvailable) { + //qCWarning(dcHardware) << "ERROR: radio 433 MHz transmitter not available on GPIO's"; + } -// if (!receiverAvailable && !transmitterAvailable) { -// qWarning() << "--> Radio 433 MHz GPIO's not available."; -// return false; -// } + if (!transmitterAvailable) { + qCWarning(dcHardware) << "--> Radio 433 MHz GPIO's not available."; + return false; + } } - qCDebug(dcDeviceManager) << "--> Radio 433 MHz GPIO's enabled."; + qCDebug(dcDeviceManager()) << "--> Radio 433 MHz GPIO's enabled."; #endif return true; @@ -121,22 +108,15 @@ bool Radio433::enable() bool Radio433::disabel() { m_brennenstuhlTransmitter->disable(); - - #ifdef GPIO433 - if (m_receiver->stopReceiver()) { - return true; - } - return false; - #endif return true; } void Radio433::brennenstuhlAvailableChanged(const bool &available) { if (available) { - qCDebug(dcDeviceManager) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available."; + qCDebug(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway available."; } else { - qCWarning(dcHardware) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available."; + qCWarning(dcHardware()) << "--> Radio 433 MHz Brennenstuhl LAN Gateway NOT available."; } } diff --git a/libguh/hardware/radio433/radio433.h b/libguh/hardware/radio433/radio433.h index 03c1246b..52a7e8bf 100644 --- a/libguh/hardware/radio433/radio433.h +++ b/libguh/hardware/radio433/radio433.h @@ -24,7 +24,6 @@ #include #ifdef GPIO433 -#include "radio433receiver.h" #include "radio433transmitter.h" #endif @@ -43,15 +42,11 @@ public: private: #ifdef GPIO433 - Radio433Receiver *m_receiver; Radio433Trasmitter *m_transmitter; #endif Radio433BrennenstuhlGateway *m_brennenstuhlTransmitter; -signals: - void dataReceived(QList rawData); - private slots: void brennenstuhlAvailableChanged(const bool &available); diff --git a/libguh/hardware/radio433/radio433transmitter.cpp b/libguh/hardware/radio433/radio433transmitter.cpp index 1cd06d76..8329f81b 100644 --- a/libguh/hardware/radio433/radio433transmitter.cpp +++ b/libguh/hardware/radio433/radio433transmitter.cpp @@ -52,17 +52,18 @@ void Radio433Trasmitter::run() rawData = m_rawDataQueue.dequeue(); m_queueMutex.unlock(); - m_gpio->setValue(LOW); + m_gpio->setValue(Gpio::ValueLow); int flag=1; foreach (int delay, rawData) { // 1 = High, 0 = Low - m_gpio->setValue(flag %2); + int value = flag %2; + m_gpio->setValue((Gpio::Value)value); flag++; usleep(delay); } - m_gpio->setValue(LOW); + m_gpio->setValue(Gpio::ValueLow); } m_queueMutex.unlock(); } @@ -76,9 +77,9 @@ void Radio433Trasmitter::allowSending(bool sending) 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; return false; } diff --git a/libguh/hardware/radio433/radio433transmitter.h b/libguh/hardware/radio433/radio433transmitter.h index fa8c3c3c..fc606452 100644 --- a/libguh/hardware/radio433/radio433transmitter.h +++ b/libguh/hardware/radio433/radio433transmitter.h @@ -28,7 +28,7 @@ #include #include "libguh.h" -#include "../gpio.h" +#include "hardware/gpio.h" class LIBGUH_EXPORT Radio433Trasmitter : public QThread diff --git a/libguh/libguh.pro b/libguh/libguh.pro index bd294922..9432ae37 100644 --- a/libguh/libguh.pro +++ b/libguh/libguh.pro @@ -34,7 +34,6 @@ HEADERS += devicemanager.h \ hardware/gpiomonitor.h \ hardware/radio433/radio433.h \ hardware/radio433/radio433transmitter.h \ - hardware/radio433/radio433receiver.h \ hardware/radio433/radio433brennenstuhlgateway.h \ network/upnpdiscovery/upnpdiscovery.h \ network/upnpdiscovery/upnpdevice.h \ @@ -65,6 +64,7 @@ HEADERS += devicemanager.h \ types/ruleaction.h \ types/ruleactionparam.h \ types/statedescriptor.h \ + hardware/pwm.h SOURCES += devicemanager.cpp \ @@ -79,7 +79,6 @@ SOURCES += devicemanager.cpp \ hardware/gpiomonitor.cpp \ hardware/radio433/radio433.cpp \ hardware/radio433/radio433transmitter.cpp \ - hardware/radio433/radio433receiver.cpp \ hardware/radio433/radio433brennenstuhlgateway.cpp \ network/upnpdiscovery/upnpdiscovery.cpp \ network/upnpdiscovery/upnpdevice.cpp \ @@ -110,6 +109,7 @@ SOURCES += devicemanager.cpp \ types/ruleaction.cpp \ types/ruleactionparam.cpp \ types/statedescriptor.cpp \ + hardware/pwm.cpp # install plugininfo python script for libguh-dev diff --git a/libguh/plugin/deviceplugin.cpp b/libguh/plugin/deviceplugin.cpp index ccab585f..cd326836 100644 --- a/libguh/plugin/deviceplugin.cpp +++ b/libguh/plugin/deviceplugin.cpp @@ -614,9 +614,6 @@ bool DevicePlugin::transmitData(int delay, QList rawData, int repetitions) switch (requiredHardware()) { case DeviceManager::HardwareResourceRadio433: return deviceManager()->m_radio433->sendData(delay, rawData, repetitions); - case DeviceManager::HardwareResourceRadio868: - qCDebug(dcDeviceManager) << "Radio868 not connected yet"; - return false; default: qCWarning(dcDeviceManager) << "Unknown harware type. Cannot send."; } diff --git a/server/main.cpp b/server/main.cpp index 80bcb134..68e53745 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -1,6 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright (C) 2015 Simon Stuerz * + * Copyright (C) 2015 Simon Stürz * * Copyright (C) 2014 Michael Zanetti * * * * This file is part of guh. *