version 1.15.0_alpha

add PIGPIO class
gcc warnings fix
This commit is contained in:
2020-05-22 21:34:21 +03:00
parent 51a76be487
commit 299d1e1708
9 changed files with 415 additions and 11 deletions

View File

@@ -215,9 +215,9 @@
#define PRIVATE_DEFINITION_END(c) \
}; \
c::__PrivateInitializer__::__PrivateInitializer__() {p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & o) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::__PrivateInitializer__(const c::__PrivateInitializer__ & ) {/*if (p) delete p;*/ p = new c::__Private__();} \
c::__PrivateInitializer__::~__PrivateInitializer__() {delete p; p = 0;} \
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & o) {if (p) delete p; p = new c::__Private__(); return *this;}
c::__PrivateInitializer__ & c::__PrivateInitializer__::operator =(const c::__PrivateInitializer__ & ) {if (p) delete p; p = new c::__Private__(); return *this;}
#define PRIVATE (__privateinitializer__.p)
#define PRIVATEWB __privateinitializer__.p

View File

@@ -201,9 +201,9 @@
typedef name __PIObject__; \
public: \
static const PIString __classNameS() {return PIStringAscii(#name);} \
static const uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual const char * className() const {return #name;} \
virtual const uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
private: \
virtual int ptrOffset() const {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
class __BaseInitializer__ { \
@@ -515,10 +515,10 @@ public:
//! Returns object class name
virtual const char * className() const {return "PIObject";}
virtual const uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static const PIString __classNameS() {return PIStringAscii("PIObject");}
static const uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
//! Returns parent object class name
virtual const char * parentClassName() const {return "";}

View File

@@ -36,7 +36,8 @@ PIIntrospectionThreads::PIIntrospectionThreads() {
void PIIntrospectionThreads::threadNew(PIThread * t) {
PIMutexLocker _ml(mutex);
ThreadInfo & ti(threads[t]);
//ThreadInfo & ti(threads[t]);
threads.insert(t, ThreadInfo());
//piCout << "register thread" << id << name;
}

View File

@@ -0,0 +1,256 @@
/*
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pigpio.h"
#ifdef LINUX
# define GPIO_SYS_CLASS
#endif
#ifdef GPIO_SYS_CLASS
# include <fcntl.h>
# include <unistd.h>
# include <cstdlib>
#endif
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
/*! \class PIGPIO
* \brief GPIO support
*
* \section PIGPIO_sec0 Synopsis
* This class provide initialize, get/set and watch functions for GPIO.
*
* Currently supported only \"/sys/class/gpio\" mechanism on Linux.
*
* This class should be used with \a PIGPIO::instance() singleton.
*
*
*
* \section PIGPIO_sec1 API
* There are several function to directly read or write pin states.
*
* Also you can start %PIGPIO as thread to watch pin states and receive
* \a pinChanged() event.
*
*/
PIGPIO::PIGPIO(): PIThread() {
}
PIGPIO::~PIGPIO() {
stop();
waitForFinish(100);
PIMutexLocker ml(mutex);
#ifdef GPIO_SYS_CLASS
PIVector<int> ids = gpio_.keys();
for(int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.fd != -1) {
::close(g.fd);
g.fd = -1;
}
}
gpio_.clear();
#endif
}
PIGPIO * PIGPIO::instance() {
static PIGPIO ret;
return &ret;
}
PIString PIGPIO::GPIOName(int gpio_num) {
return PIStringAscii("gpio") + PIString::fromNumber(gpio_num);
}
void PIGPIO::exportGPIO(int gpio_num) {
#ifdef GPIO_SYS_CLASS
int fd = ::open(("/sys/class/gpio/" + GPIOName(gpio_num) + "/value").dataAscii(), O_RDONLY);
if (fd != -1) {
::close(fd);
return;
}
int ret = 0;
ret = system(PIString("echo " + PIString::fromNumber(gpio_num) + " >> /sys/class/gpio/export").dataAscii());
#endif
}
void PIGPIO::openGPIO(GPIOData & g) {
#ifdef GPIO_SYS_CLASS
if (g.fd != -1) {
::close(g.fd);
g.fd = -1;
}
PIString fp = "/sys/class/gpio/" + g.name + "/value";
g.fd = ::open(fp.dataAscii(), O_RDWR);
//piCoutObj << "initGPIO" << g.num << ":" << fp << g.fd << errorString();
#endif
}
bool PIGPIO::getPinState(int gpio_num) {
#ifdef GPIO_SYS_CLASS
GPIOData & g(gpio_[gpio_num]);
char r = 0;
int ret = 0;
if (g.fd != -1) {
::lseek(g.fd, 0, SEEK_SET);
ret = ::read(g.fd, &r, sizeof(r));
if (ret > 0) {
if (r == '1') return true;
if (r == '0') return false;
}
}
//piCoutObj << "pinState" << gpio_num << ":" << ret << (int)r << errorString();
//initGPIO(gpio_num, PIGPIO::In); TODO: discuss - why?
#endif
return false;
}
void PIGPIO::begin() {
PIMutexLocker ml(mutex);
if (watch_state.isEmpty()) return;
PIVector<int> ids = watch_state.keys();
for(int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.num != -1 && !g.name.isEmpty()) {
openGPIO(g);
watch_state[ids[i]] = getPinState(ids[i]);
}
}
}
void PIGPIO::run() {
PIMutexLocker ml(mutex);
if (watch_state.isEmpty()) return;
PIVector<int> ids = watch_state.keys();
for(int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.num != -1 && !g.name.isEmpty()) {
bool v = getPinState(g.num);
//piCoutObj << "*** pin state ***" << ids[i] << "=" << v;
if (watch_state[g.num] != v) {
watch_state[g.num] = v;
pinChanged(g.num, v);
}
}
}
}
void PIGPIO::end() {
PIMutexLocker ml(mutex);
if (watch_state.isEmpty()) return;
PIVector<int> ids = watch_state.keys();
for(int i = 0; i < ids.size_s(); i++) {
GPIOData & g(gpio_[ids[i]]);
if (g.fd != -1) {
#ifdef GPIO_SYS_CLASS
::close(g.fd);
#endif
g.fd = -1;
}
}
}
void PIGPIO::initPin(int gpio_num, Direction dir) { //, PullUpDownControl pull) {
#ifdef GPIO_SYS_CLASS
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
if (g.num == -1) {
g.num = gpio_num;
g.name = GPIOName(gpio_num);
exportGPIO(gpio_num);
}
g.dir = dir;
int ret = 0;
switch(dir) {
case In:
ret = system(("echo in >> /sys/class/gpio/" + g.name + "/direction").dataAscii());
break;
case Out:
ret = system(("echo out >> /sys/class/gpio/" + g.name + "/direction").dataAscii());
break;
default: break;
}
openGPIO(g);
#endif
}
void PIGPIO::pinSet(int gpio_num, bool value) {
#ifdef GPIO_SYS_CLASS
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
int ret = 0;
if (g.fd != -1) {
if (value) ret = ::write(g.fd, "1", 1);
else ret = ::write(g.fd, "0", 1);
}
//piCoutObj << "pinSet" << gpio_num << ":" << ret << errorString();
#endif
}
bool PIGPIO::pinState(int gpio_num) {
PIMutexLocker ml(mutex);
return getPinState(gpio_num);
}
void PIGPIO::pinBeginWatch(int gpio_num) {
PIMutexLocker ml(mutex);
GPIOData & g(gpio_[gpio_num]);
if (g.fd != -1) {
#ifdef GPIO_SYS_CLASS
::close(g.fd);
#endif
g.fd = -1;
}
watch_state.insert(gpio_num, false);
}
void PIGPIO::pinEndWatch(int gpio_num) {
PIMutexLocker ml(mutex);
watch_state.remove(gpio_num);
}
void PIGPIO::clearWatch() {
PIMutexLocker ml(mutex);
watch_state.clear();
}
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,117 @@
/*! \file pigpio.h
* \brief GPIO
*/
/*
PIP - Platform Independent Primitives
GPIO
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIGPIO_H
#define PIGPIO_H
#include "pithread.h"
class PIGPIO: public PIThread
{
PIOBJECT_SUBCLASS(PIGPIO, PIThread)
public:
PIGPIO();
virtual ~PIGPIO();
//! \brief Work mode for pin
enum Direction {
In /** Input direction (read) */,
Out /** Output direction (write) */
};
//enum PullUpDownControl {NoPull, PullUp, PullDown};
//! \brief Returns singleton object of %PIGPIO
static PIGPIO * instance();
//! \brief Initialize pin \"gpio_num\" for \"dir\" mode
void initPin(int gpio_num, Direction dir = PIGPIO::In);//, PullUpDownControl pull);
//! \brief Set pin \"gpio_num\" value to \"value\"
void pinSet (int gpio_num, bool value);
//! \brief Set pin \"gpio_num\" value to \b true
void pinHigh (int gpio_num) {pinSet(gpio_num, true );}
//! \brief Set pin \"gpio_num\" value to \b false
void pinLow (int gpio_num) {pinSet(gpio_num, false);}
//! \brief Returns pin \"gpio_num\" state
bool pinState(int gpio_num);
//! \brief Starts watch for pin \"gpio_num\".
//! \details Pins watching starts only with \a PIThread::start() function!
//! This function doesn`t affect thread state
void pinBeginWatch(int gpio_num);
//! \brief End watch for pin \"gpio_num\".
//! \details Pins watching starts only with \a PIThread::start() function!
//! This function doesn`t affect thread state
void pinEndWatch (int gpio_num);
//! \brief End watch for all pins.
//! \details Pins watching starts only with \a PIThread::start() function!
//! This function doesn`t affect thread state
void clearWatch();
EVENT2(pinChanged, int, gpio_num, bool, new_value)
//! \events
//! \{
//! \fn void pinChanged(int gpio_num, bool new_value)
//! \brief Raise on pin \"gpio_num\" state changes to \"new_value\"
//! \details Important! This event will be raised only with started
//! thread.
//! \}
private:
struct GPIOData {
GPIOData() {dir = PIGPIO::In; num = fd = -1;}
PIString name;
int dir;
int num;
int fd;
};
void exportGPIO(int gpio_num);
void openGPIO(GPIOData & g);
bool getPinState(int gpio_num);
void begin();
void run();
void end();
static PIString GPIOName(int gpio_num);
PIMap<int, GPIOData> gpio_;
PIMap<int, bool> watch_state;
PIMutex mutex;
};
#endif // PIDIR_H

View File

@@ -375,7 +375,6 @@ void PISystemMonitor::gatherThread(llong id) {
ts.name = tbid.value(id, "<PIThread>");
#else
ts.name = tbid.value(id, "<non-PIThread>");
PISystemTime ct = PISystemTime::current();
# ifndef WINDOWS
PIFile f(PRIVATE->proc_dir + "task/" + PIString::fromNumber(id) + "/stat");
//piCout << f.path();
@@ -399,6 +398,7 @@ void PISystemMonitor::gatherThread(llong id) {
ts.user_time = PISystemTime::fromMilliseconds(sl[12].toInt() * 10.);
ts.kernel_time = PISystemTime::fromMilliseconds(sl[13].toInt() * 10.);
# else
PISystemTime ct = PISystemTime::current();
FILETIME times[4];
HANDLE thdl = OpenThread(THREAD_QUERY_INFORMATION, FALSE, DWORD(id));
if (thdl == NULL) {