This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
2019-04-01 20:48:17 +02:00

366 lines
9.3 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This file is part of guh. *
* *
* Guh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* Guh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class Gpio
\brief The Gpio class helps to interact with the gpio pins of the Raspberry Pi.
\inmodule libguh
The Raspberry Pi offers lower-level interfaces (GPIO's) intended to connect more directly
with chips and subsystem modules. 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 on the board.
In following table is a list of all GPIO's of the Raspberry Pi Rev. 2.0:
\image gpio.png "Gpio settings"
Valid GPIO's for this class are those with a GPIO number (for example GPIO 22, which is on pin Nr. 15)
*/
#include "gpio.h"
#include <QDebug>
/*! 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)
{
}
/*! Destroys the Gpio object and unexports the GPIO. */
Gpio::~Gpio()
{
unexportGpio();
}
/*! Returns true if this GPIO could be exported in the system file "/sys/class/gpio/export". */
bool Gpio::exportGpio()
{
unexportGpio();
char buf[64];
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
//qDebug() << "ERROR: could not open /sys/class/gpio/export";
return false;
}
ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio);
if(write(fd, buf, len) != len){
qDebug() << "ERROR: could not write to gpio (export)";
close(fd);
return false;
}
close(fd);
return true;
}
/*! Returns true if this GPIO could be unexported in the system file "/sys/class/gpio/unexport". */
bool Gpio::unexportGpio()
{
char buf[64];
int fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
//qDebug() << "ERROR: could not open /sys/class/gpio/unexport";
return false;
}
ssize_t len = snprintf(buf, sizeof(buf), "%d", m_gpio);
if(write(fd, buf, len) != len){
//qDebug() << "ERROR: could not write to gpio (unexport)";
close(fd);
return false;
}
close(fd);
return true;
}
/*! Returns true, if the file of this GPIO could be opend.*/
int Gpio::openGpio()
{
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) {
qDebug() << "ERROR: 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) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/direction";
return false;
}
if(dir == INPUT){
if(write(fd, "in", 3) != 3){
qDebug() << "ERROR: could not write to gpio (set INPUT)";
close(fd);
return false;
}
m_dir = INPUT;
close(fd);
return true;
}
if(dir == OUTPUT){
if(write(fd, "out", 4) != 4){
qDebug() << "ERROR: could not write to gpio (set OUTPUT)";
close(fd);
return false;
}
m_dir = OUTPUT;
close(fd);
return true;
}
close(fd);
return false;
}
/*! 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) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/value";
return false;
}
if(value == LOW){
if(write(fd, "0", 2) != 2){
qDebug() << "ERROR: could not write to gpio (set LOW)";
close(fd);
return false;
}
close(fd);
return true;
}
if(value == HIGH){
if(write(fd, "1", 2) != 2){
qDebug() << "ERROR: could not write to gpio (set HIGH)";
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
}else{
qDebug() << "ERROR: 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) {
qDebug() << "ERROR: 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)
{
char buf[64];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/edge", m_gpio);
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/edge";
return false;
}
if(edge == EDGE_FALLING){
if(write(fd, "falling", 8) != 8){
qDebug() << "ERROR: could not write to gpio (set EDGE_FALLING)";
close(fd);
return false;
}
close(fd);
return true;
}
if(edge == EDGE_RISING){
if(write(fd, "rising", 7) != 7){
qDebug() << "ERROR: 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){
qDebug() << "ERROR: could not write to gpio (set EDGE_BOTH)";
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
}
bool Gpio::setActiveLow(bool activeLow)
{
char buf[64];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/active_low", m_gpio);
int fd = open(buf, O_WRONLY);
if (fd < 0) {
qDebug() << "ERROR: could not open /sys/class/gpio" << m_gpio << "/active_low";
return false;
}
if(activeLow){
if(write(fd, "0", 2) != 2){
qDebug() << "ERROR: could not write to gpio (set Active LOW)";
close(fd);
return false;
}
close(fd);
return true;
}
if(!activeLow){
if(write(fd, "1", 2) != 2){
qDebug() << "ERROR: could not write to gpio (set Active HIGH)";
close(fd);
return false;
}
close(fd);
return true;
}
close(fd);
return false;
}
int Gpio::gpioPin()
{
return m_gpio;
}
int Gpio::gpioDirection()
{
return m_dir;
}
bool Gpio::isAvailable()
{
QDir gpioDirectory("/sys/class/gpio");
return gpioDirectory.exists();
}