From 299d1e1708a536df82d853191a7cc38fe720600b Mon Sep 17 00:00:00 2001 From: Ivan Pelipenko Date: Fri, 22 May 2020 21:34:21 +0300 Subject: [PATCH] version 1.15.0_alpha add PIGPIO class gcc warnings fix --- CMakeLists.txt | 12 +- main.cpp | 17 ++ src_io_utils/pistreampacker.cpp | 7 + src_main/core/pibase.h | 4 +- src_main/core/piobject.h | 8 +- .../piintrospection_threads_p.cpp | 3 +- src_main/io_devices/pigpio.cpp | 256 ++++++++++++++++++ src_main/io_devices/pigpio.h | 117 ++++++++ src_main/system/pisystemmonitor.cpp | 2 +- 9 files changed, 415 insertions(+), 11 deletions(-) create mode 100644 src_main/io_devices/pigpio.cpp create mode 100644 src_main/io_devices/pigpio.h 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) {