Skip to content

Commit

Permalink
Refactor FunctionalInterrupt, undo removal of attachInterrupt() for f…
Browse files Browse the repository at this point in the history
…unctional arguments.
  • Loading branch information
dok-net committed Jun 25, 2019
1 parent d0279f2 commit 3cd9bd9
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 80 deletions.
18 changes: 6 additions & 12 deletions libraries/FunctionalInterrupt/examples/Functional/Functional.ino
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include <FunctionalInterrupt.h>
#include <Arduino.h>

#ifndef IRAM_ATTR
#define IRAM_ATTR ICACHE_RAM_ATTR
#endif

#if defined(ESP32)
#define BUTTON1 16
#define BUTTON2 17
Expand Down Expand Up @@ -35,22 +39,12 @@ class Button {
detachFunctionalInterrupt(PIN);
}

#if defined(ESP8266)
void ICACHE_RAM_ATTR isr()
#elif defined(ESP32)
void IRAM_ATTR isr()
#endif
{
void IRAM_ATTR isr() {
numberKeyPresses += 1;
pressed = true;
}

#if defined(ESP8266)
static void ICACHE_RAM_ATTR isr_static(Button* const self)
#elif defined(ESP32)
static void IRAM_ATTR isr_static(Button* const self)
#endif
{
static void IRAM_ATTR isr_static(Button* const self) {
self->isr();
}

Expand Down
98 changes: 53 additions & 45 deletions libraries/FunctionalInterrupt/src/FunctionalInterrupt.cpp
Original file line number Diff line number Diff line change
@@ -1,65 +1,73 @@
#include <FunctionalInterrupt.h>
#include "FunctionalInterrupt.h"
#include <Schedule.h>
#include "Arduino.h"
#include <Arduino.h>

// Duplicate typedefs from core_esp8266_wiring_digital_c
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);
namespace {

// Helper functions for Functional interrupt routines
extern "C" void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtr userFunc, void*fp, int mode, bool functional);
struct ArgStructure
{
std::function<void()> function = nullptr;
};

void ICACHE_RAM_ATTR interruptFunctional(void* arg)
{
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
localArg->function();
}

void ICACHE_RAM_ATTR interruptFunctional(void* arg)
{
ArgStructure* localArg = (ArgStructure*)arg;
if (localArg->functionInfo->reqScheduledFunction)
{
schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))));
}
if (localArg->functionInfo->reqFunction)
{
localArg->functionInfo->reqFunction();
}
}
void cleanupFunctional(void* arg)
{
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
delete localArg;
}

extern "C"
{
void cleanupFunctional(void* arg)
{
ArgStructure* localArg = (ArgStructure*)arg;
delete (FunctionInfo*)localArg->functionInfo;
delete (InterruptInfo*)localArg->interruptInfo;
delete localArg;
}
}

void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument

InterruptInfo* ii = nullptr;
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(localArg);
}

FunctionInfo* fi = new FunctionInfo;
fi->reqFunction = intRoutine;
if (intRoutine)
{
ArgStructure* arg = new ArgStructure;
arg->function = std::move(intRoutine);

ArgStructure* as = new ArgStructure;
as->interruptInfo = ii;
as->functionInfo = fi;

__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
attachInterruptArg(pin, interruptFunctional, arg, mode);
}
}

void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
{
InterruptInfo* ii = new InterruptInfo;
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(localArg);
}

FunctionInfo* fi = new FunctionInfo;
fi->reqScheduledFunction = scheduledIntRoutine;
if (scheduledIntRoutine)
{
ArgStructure* arg = new ArgStructure;
arg->function = [scheduledIntRoutine = std::move(scheduledIntRoutine), pin]()
{
InterruptInfo interruptInfo(pin);
interruptInfo.value = digitalRead(pin);
interruptInfo.micro = micros();
schedule_function([scheduledIntRoutine, interruptInfo]() { scheduledIntRoutine(std::move(interruptInfo)); });
};

ArgStructure* as = new ArgStructure;
as->interruptInfo = ii;
as->functionInfo = fi;
attachInterruptArg(pin, interruptFunctional, arg, mode);
}
}

__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
void detachFunctionalInterrupt(uint8_t pin)
{
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(localArg);
}
}
31 changes: 8 additions & 23 deletions libraries/FunctionalInterrupt/src/FunctionalInterrupt.h
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
#ifndef FUNCTIONALINTERRUPT_H
#define FUNCTIONALINTERRUPT_H

#include <stddef.h>
#include <stdint.h>
#include <functional>

extern "C" {
#include "c_types.h"
#include "ets_sys.h"
}

// Structures for communication

struct InterruptInfo {
uint8_t pin = 0;
uint8_t value = 0;
uint32_t micro = 0;
};

struct FunctionInfo {
std::function<void(void)> reqFunction = nullptr;
std::function<void(InterruptInfo)> reqScheduledFunction = nullptr;
};

struct ArgStructure {
InterruptInfo* interruptInfo = nullptr;
FunctionInfo* functionInfo = nullptr;
struct InterruptInfo
{
InterruptInfo(uint8_t _pin) : pin(_pin) {}
const uint8_t pin;
uint8_t value = 0;
uint32_t micro = 0;
};

void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
void detachFunctionalInterrupt(uint8_t pin);


#endif //INTERRUPTS_H
#endif //FUNCTIONALINTERRUPT_H

0 comments on commit 3cd9bd9

Please sign in to comment.