Skip to content

Commit

Permalink
wrap MRAA lib's Gpio::isr() for IRQ support
Browse files Browse the repository at this point in the history
I also removed MRAA exclusion from examples build. Previously, interruptConfigure.cpp was not built for MRAA driver.
  • Loading branch information
2bndy5 committed Mar 26, 2024
1 parent 7441eef commit 105dc0b
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 11 deletions.
8 changes: 1 addition & 7 deletions examples_linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(EXAMPLES_LIST
streamingData
multiceiverDemo
scanner
interruptConfigure
)

project(RF24Examples CXX)
Expand All @@ -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}
Expand Down
5 changes: 1 addition & 4 deletions examples_linux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
60 changes: 60 additions & 0 deletions utility/MRAA/interrupt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <map>
#include <mraa.h> // mraa_strresult()
#include <mraa.hpp> // mraa::Gpio
#include "interrupt.h"
#include "gpio.h" // rf24_gpio_pin_t

#ifdef __cplusplus
extern "C" {
#endif

std::map<rf24_gpio_pin_t, mraa::Gpio*> 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<std::map<rf24_gpio_pin_t, mraa::Gpio*>::iterator, bool> indexPair = irqCache.insert(std::pair<rf24_gpio_pin_t, mraa::Gpio*>(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<rf24_gpio_pin_t, mraa::Gpio*>::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)
45 changes: 45 additions & 0 deletions utility/MRAA/interrupt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef RF24_UTILITY_MRAA_INTERRUPT_H_
#define RF24_UTILITY_MRAA_INTERRUPT_H_

#include <stdexcept> // 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_

0 comments on commit 105dc0b

Please sign in to comment.