diff --git a/examples_linux/CMakeLists.txt b/examples_linux/CMakeLists.txt index 40101a60..cc2ef089 100644 --- a/examples_linux/CMakeLists.txt +++ b/examples_linux/CMakeLists.txt @@ -8,6 +8,7 @@ set(EXAMPLES_LIST streamingData multiceiverDemo scanner + interruptConfigure ) project(RF24Examples CXX) @@ -23,13 +24,6 @@ include(../cmake/AutoConfig_RF24_DRIVER.cmake) find_library(RF24 rf24 REQUIRED) message(STATUS "using RF24 library: ${RF24}") -# conditionally append "interruptConfigure" to the EXAMPLES_LIST -if("${RF24_DRIVER}" STREQUAL "MRAA") - message(STATUS "Skipping interruptConfigure.cpp example as it is incompatible with selected driver library") -else() # not using MRAA or wiringPi drivers (or pigpio lib was found) - list(APPEND EXAMPLES_LIST interruptConfigure) -endif() - set(linked_libs ${RF24} diff --git a/examples_linux/Makefile b/examples_linux/Makefile index 901a7402..e3a3c499 100644 --- a/examples_linux/Makefile +++ b/examples_linux/Makefile @@ -18,9 +18,6 @@ endif include ../Makefile.inc # define all programs -PROGRAMS = gettingstarted acknowledgementPayloads manualAcknowledgements streamingData multiceiverDemo scanner -ifneq ($(DRIVER), MRAA) -PROGRAMS+=interruptConfigure -endif +PROGRAMS = gettingstarted acknowledgementPayloads manualAcknowledgements streamingData multiceiverDemo scanner interruptConfigure include Makefile.examples diff --git a/utility/MRAA/interrupt.cpp b/utility/MRAA/interrupt.cpp new file mode 100644 index 00000000..cf5dda5d --- /dev/null +++ b/utility/MRAA/interrupt.cpp @@ -0,0 +1,60 @@ +#include +#include // mraa_strresult() +#include // mraa::Gpio +#include "interrupt.h" +#include "gpio.h" // rf24_gpio_pin_t + +#ifdef __cplusplus +extern "C" { +#endif + +std::map irqCache; + +int attachInterrupt(rf24_gpio_pin_t pin, uint8_t mode, void (*function)(void)) +{ + // ensure pin is not already being used in a separate thread + detachInterrupt(pin); + GPIO::close(pin); + + mraa::Gpio* gpio = new mraa::Gpio(pin); + mraa::Result status = gpio->dir(mraa::DIR_IN); + if (status != mraa::SUCCESS) { + std::string msg = "[attachInterrupt] Could not set the pin as an input; "; + msg += mraa_strresult((mraa_result_t)status); + throw IRQException(msg); + return 0; + } + status = gpio->isr((mraa::Edge)mode, (void (*)(void*))function, NULL); + if (status != mraa::SUCCESS) { + std::string msg = "[attachInterrupt] Could not setup the ISR; "; + msg += mraa_strresult((mraa_result_t)status); + throw IRQException(msg); + return 0; + } + + std::pair::iterator, bool> indexPair = irqCache.insert(std::pair(pin, gpio)); + if (!indexPair.second) { + // this should not be reached, but indexPair.first needs to be the inserted map element + gpio->close(); + throw IRQException("[attachInterrupt] Could not cache the mraa::Gpio object"); + return 0; + } + return 1; +} + +int detachInterrupt(rf24_gpio_pin_t pin) +{ + std::map::iterator cachedPin = irqCache.find(pin); + if (cachedPin == irqCache.end()) { + return 0; // pin not in cache; just exit + } + cachedPin->second->close(); + irqCache.erase(cachedPin); + return 1; +} + +#ifdef __cplusplus +} +#endif + +#endif // !defined(ARDUINO) diff --git a/utility/MRAA/interrupt.h b/utility/MRAA/interrupt.h new file mode 100644 index 00000000..3b722ecf --- /dev/null +++ b/utility/MRAA/interrupt.h @@ -0,0 +1,45 @@ +#ifndef RF24_UTILITY_MRAA_INTERRUPT_H_ +#define RF24_UTILITY_MRAA_INTERRUPT_H_ + + #include // std::exception, std::string + #include "mraa.hpp" // mraa:: + #include "gpio.h" // rf24_gpio_pin_t + + #ifdef __cplusplus +extern "C" { + #endif + + + enum Edge + { + INT_EDGE_FALLING = mraa::Edge::EDGE_FALLING, + INT_EDGE_RISING = mraa::Edge::EDGE_RISING, + INT_EDGE_BOTH = mraa::Edge::EDGE_BOTH, + }; + + /** Specific exception for IRQ errors */ + class IRQException : public std::runtime_error + { + public: + explicit IRQException(const std::string& msg) + : std::runtime_error(msg) + { + } + }; + + /** + * Take the details and create an interrupt handler that will + * callback to the user-supplied function. + */ + int attachInterrupt(rf24_gpio_pin_t pin, uint8_t mode, void (*function)(void)); + + /** + * Will cancel the interrupt thread, close the filehandle and release the pin. + */ + int detachInterrupt(rf24_gpio_pin_t pin); + + #ifdef __cplusplus +} + #endif + +#endif // RF24_UTILITY_MRAA_INTERRUPT_H_