diff --git a/CMakeLists.txt b/CMakeLists.txt
index fdba57ad..bccf8a1c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip)
set(_PIP_MAJOR 1)
-set(_PIP_MINOR 14)
+set(_PIP_MINOR 15)
set(_PIP_REVISION 0)
-set(_PIP_SUFFIX beta)
+set(_PIP_SUFFIX alpha)
set(_PIP_COMPANY SHS)
set(_PIP_DOMAIN org.SHS)
@@ -84,6 +84,8 @@ set(PIP_SRC_DIRS "src_main" "src_crypt" "src_compress" "src_usb" "src_fftw" "src
set(PIP_LIBS_TARGETS pip)
set(LIBS_MAIN)
set(LIBS_STATUS)
+set(HDRS)
+set(PHDRS)
if (TESTS)
set(PIP_SRC_CONCURRENT_TEST "src_concurrent/test")
@@ -110,12 +112,16 @@ set_version(PIP
REVISION "${_PIP_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_PIP_SUFFIX}"
- OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
set_deploy_property(pip ${PIP_LIB_TYPE}
LABEL "PIP main library"
FULLNAME "${_PIP_DOMAIN}.pip"
COMPANY "${_PIP_COMPANY}"
INFO "Platform-Independent Primitives")
+if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
+ file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/${PIP_SRC_MAIN}/piversion.h")
+endif()
+list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/piversion.h")
message(STATUS "Building PIP version ${PIP_VERSION} (${PIP_LIB_TYPE})")
diff --git a/main.cpp b/main.cpp
index 38f8dd69..029fe068 100644
--- a/main.cpp
+++ b/main.cpp
@@ -111,10 +111,27 @@ private:
};
*/
+
PIKbdListener kbd;
+#include "pigpio.h"
int main(int argc, char * argv[]) {
+ PIGPIO::instance()->initPin(4, PIGPIO::Out);
+ /*PIGPIO::instance()->pinBeginWatch(4);
+ PIGPIO::instance()->start(10);
+ CONNECTL(PIGPIO::instance(), pinChanged, [](int pin, bool value){
+ piCout << "pin" << pin << "->" << value;}
+ );*/
+ kbd.enableExitCapture();
+ kbd.start();
+ bool val = false;
+ while (!PIKbdListener::exiting) {
+ piMSleep(500);
+ PIGPIO::instance()->pinSet(4, val);
+ piCout << PIGPIO::instance()->pinState(4);
+ val = !val;
+ }
/*PIStringList dl = PISerial::availableDevices();
piCout << dl;
PISerial ser(dl[0]);
diff --git a/src_io_utils/pistreampacker.cpp b/src_io_utils/pistreampacker.cpp
index ec5d9be4..73a3f249 100644
--- a/src_io_utils/pistreampacker.cpp
+++ b/src_io_utils/pistreampacker.cpp
@@ -17,8 +17,15 @@
along with this program. If not, see .
*/
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wnonnull"
+#endif
#include "pistreampacker.h"
#include "piiodevice.h"
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
/** \class PIStreamPacker
* \brief Simple packet wrap aroud any PIIODevice
diff --git a/src_main/core/pibase.h b/src_main/core/pibase.h
index 8a3ea2b2..230668bd 100644
--- a/src_main/core/pibase.h
+++ b/src_main/core/pibase.h
@@ -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
diff --git a/src_main/core/piobject.h b/src_main/core/piobject.h
index a33e6922..9269b043 100755
--- a/src_main/core/piobject.h
+++ b/src_main/core/piobject.h
@@ -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 "";}
diff --git a/src_main/introspection/piintrospection_threads_p.cpp b/src_main/introspection/piintrospection_threads_p.cpp
index b7430e86..94cf1326 100644
--- a/src_main/introspection/piintrospection_threads_p.cpp
+++ b/src_main/introspection/piintrospection_threads_p.cpp
@@ -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;
}
diff --git a/src_main/io_devices/pigpio.cpp b/src_main/io_devices/pigpio.cpp
new file mode 100644
index 00000000..93dfdc53
--- /dev/null
+++ b/src_main/io_devices/pigpio.cpp
@@ -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 .
+*/
+
+#include "pigpio.h"
+#ifdef LINUX
+# define GPIO_SYS_CLASS
+#endif
+#ifdef GPIO_SYS_CLASS
+# include
+# include
+# include
+#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 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 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 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 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
diff --git a/src_main/io_devices/pigpio.h b/src_main/io_devices/pigpio.h
new file mode 100644
index 00000000..ea8dc4b6
--- /dev/null
+++ b/src_main/io_devices/pigpio.h
@@ -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 .
+*/
+
+#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 gpio_;
+ PIMap watch_state;
+ PIMutex mutex;
+
+};
+
+
+#endif // PIDIR_H
diff --git a/src_main/system/pisystemmonitor.cpp b/src_main/system/pisystemmonitor.cpp
index 5d29308b..686c3942 100755
--- a/src_main/system/pisystemmonitor.cpp
+++ b/src_main/system/pisystemmonitor.cpp
@@ -375,7 +375,6 @@ void PISystemMonitor::gatherThread(llong id) {
ts.name = tbid.value(id, "");
#else
ts.name = tbid.value(id, "");
- 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) {