Skip to content

Commit 0c228ab

Browse files
committed
Bring back FunctionalInterrupt, and ScheduledFunctions, as example code.
It should be decided whether to reinstate these in the core, or make them an optional library.
1 parent 7218bcc commit 0c228ab

File tree

5 files changed

+383
-0
lines changed

5 files changed

+383
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <Arduino.h>
2+
#include "FunctionalInterrupts.h"
3+
4+
#if defined(ESP8266) || defined(ARDUINO_D1_MINI32)
5+
#define BUTTON1 D3
6+
#define BUTTON2 D4
7+
#else
8+
#define BUTTON1 16
9+
#define BUTTON2 17
10+
#endif
11+
12+
class Button
13+
{
14+
public:
15+
Button(uint8_t reqPin) : PIN(reqPin) {
16+
pinMode(PIN, INPUT_PULLUP);
17+
attachInterrupt(PIN, std::bind(&Button::isr,this), FALLING);
18+
};
19+
~Button() {
20+
detachFunctionalInterrupt(PIN);
21+
}
22+
23+
#if defined(ESP8266)
24+
void ICACHE_RAM_ATTR isr()
25+
#elif defined(ESP32)
26+
void IRAM_ATTR isr()
27+
#endif
28+
{
29+
numberKeyPresses += 1;
30+
pressed = true;
31+
}
32+
33+
void checkPressed() {
34+
if (pressed) {
35+
Serial.printf("Button on pin %u has been pressed %u times\n", PIN, numberKeyPresses);
36+
pressed = false;
37+
}
38+
}
39+
40+
private:
41+
const uint8_t PIN;
42+
volatile uint32_t numberKeyPresses;
43+
volatile bool pressed;
44+
};
45+
46+
Button button1(BUTTON1);
47+
Button button2(BUTTON2);
48+
49+
50+
void setup() {
51+
Serial.begin(115200);
52+
}
53+
54+
void loop() {
55+
button1.checkPressed();
56+
button2.checkPressed();
57+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#include "FunctionalInterrupts.h"
2+
#include <Schedule.h>
3+
#include "Arduino.h"
4+
5+
#if defined(ESP8266)
6+
7+
// Duplicate typedefs from core_esp8266_wiring_digital.cpp
8+
// Keep in sync
9+
typedef void (*voidFuncPtr)(void);
10+
typedef void (*voidFuncPtrArg)(void*);
11+
12+
typedef struct {
13+
uint8_t mode;
14+
voidFuncPtr fn;
15+
void* arg;
16+
} interrupt_handler_t;
17+
18+
// Helper functions for Functional interrupt routines
19+
extern "C" interrupt_handler_t* __getInterruptHandler(uint8_t pin);
20+
21+
#elif defined(ESP32)
22+
23+
// Duplicate typedefs from esp32-hal-gpio.c
24+
// Keep in sync
25+
typedef void (*voidFuncPtr)(void);
26+
typedef void (*voidFuncPtrArg)(void*);
27+
typedef struct {
28+
voidFuncPtr fn;
29+
void* arg;
30+
} InterruptHandle_t;
31+
32+
// Helper functions for Functional interrupt routines
33+
extern "C" InterruptHandle_t* __getInterruptHandler(uint8_t pin);
34+
35+
#endif
36+
37+
void ICACHE_RAM_ATTR interruptFunctional(void* arg)
38+
{
39+
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
40+
if (localArg->interruptInfo)
41+
{
42+
localArg->interruptInfo->value = digitalRead(localArg->interruptInfo->pin);
43+
localArg->interruptInfo->micro = micros();
44+
}
45+
if (localArg->functionInfo->reqScheduledFunction)
46+
{
47+
schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))));
48+
}
49+
if (localArg->functionInfo->reqFunction)
50+
{
51+
localArg->functionInfo->reqFunction();
52+
}
53+
}
54+
55+
void cleanupFunctional(void* arg)
56+
{
57+
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
58+
delete localArg;
59+
}
60+
61+
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
62+
{
63+
// use the local interrupt routine which takes the ArgStructure as argument
64+
65+
#if defined(ESP8266)
66+
interrupt_handler_t* handler = __getInterruptHandler(pin);
67+
#elif defined(ESP32)
68+
InterruptHandle_t* handler = __getInterruptHandler(pin);
69+
#endif
70+
if (handler->arg)
71+
{
72+
cleanupFunctional(handler->arg);
73+
}
74+
75+
FunctionInfo* fi = new FunctionInfo;
76+
fi->reqFunction = intRoutine;
77+
78+
ArgStructure* as = new ArgStructure;
79+
as->functionInfo = fi;
80+
81+
::attachInterruptArg (pin, static_cast<voidFuncPtrArg>(interruptFunctional), as, mode);
82+
}
83+
84+
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
85+
{
86+
#if defined(ESP8266)
87+
interrupt_handler_t* handler = __getInterruptHandler(pin);
88+
#elif defined(ESP32)
89+
InterruptHandle_t* handler = __getInterruptHandler(pin);
90+
#endif
91+
if (handler->arg)
92+
{
93+
cleanupFunctional(handler->arg);
94+
}
95+
96+
InterruptInfo* ii = new InterruptInfo(pin);
97+
98+
FunctionInfo* fi = new FunctionInfo;
99+
fi->reqScheduledFunction = scheduledIntRoutine;
100+
101+
ArgStructure* as = new ArgStructure;
102+
as->interruptInfo = ii;
103+
as->functionInfo = fi;
104+
105+
::attachInterruptArg (pin, static_cast<voidFuncPtrArg>(interruptFunctional), as, mode);
106+
}
107+
108+
void detachFunctionalInterrupt(uint8_t pin)
109+
{
110+
#if defined(ESP8266)
111+
interrupt_handler_t* handler = __getInterruptHandler(pin);
112+
#elif defined(ESP32)
113+
InterruptHandle_t* handler = __getInterruptHandler(pin);
114+
#endif
115+
if (handler->arg)
116+
{
117+
cleanupFunctional(handler->arg);
118+
}
119+
::detachInterrupt (pin);
120+
}
121+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef FUNCTIONALINTERRUPTS_H
2+
#define FUNCTIONALINTERRUPTS_H
3+
4+
#include <stddef.h>
5+
#include <stdint.h>
6+
#include <functional>
7+
#include "ScheduledFunctions.h"
8+
9+
// Structures for communication
10+
11+
struct InterruptInfo {
12+
InterruptInfo(uint8_t _pin) : pin(_pin) {}
13+
const uint8_t pin;
14+
uint8_t value = 0;
15+
uint32_t micro = 0;
16+
};
17+
18+
struct FunctionInfo {
19+
std::function<void(void)> reqFunction = nullptr;
20+
std::function<void(InterruptInfo)> reqScheduledFunction = nullptr;
21+
};
22+
23+
struct ArgStructure {
24+
~ArgStructure()
25+
{
26+
delete functionInfo;
27+
delete interruptInfo;
28+
}
29+
InterruptInfo* interruptInfo = nullptr;
30+
FunctionInfo* functionInfo = nullptr;
31+
};
32+
33+
void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode);
34+
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode);
35+
void detachFunctionalInterrupt(uint8_t pin);
36+
37+
#endif //INTERRUPTS_H
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* ScheduledFunctions.cpp
3+
*
4+
* Created on: 27 apr. 2018
5+
* Author: Herman
6+
*/
7+
#include "ScheduledFunctions.h"
8+
9+
std::list<ScheduledFunctions::ScheduledElement> ScheduledFunctions::scheduledFunctions;
10+
11+
ScheduledFunctions::ScheduledFunctions()
12+
:ScheduledFunctions(UINT_MAX)
13+
{
14+
}
15+
16+
ScheduledFunctions::ScheduledFunctions(unsigned int reqMax)
17+
{
18+
maxElements = reqMax;
19+
}
20+
21+
ScheduledFunctions::~ScheduledFunctions() {
22+
}
23+
24+
ScheduledRegistration ScheduledFunctions::insertElement(ScheduledElement se, bool front)
25+
{
26+
if (countElements >= maxElements)
27+
{
28+
return nullptr;
29+
}
30+
else
31+
{
32+
countElements++;
33+
if (front)
34+
{
35+
scheduledFunctions.push_front(se);
36+
return scheduledFunctions.begin()->registration;
37+
}
38+
else
39+
{
40+
scheduledFunctions.push_back(se);
41+
return scheduledFunctions.rbegin()->registration;
42+
}
43+
}
44+
}
45+
46+
std::list<ScheduledFunctions::ScheduledElement>::iterator ScheduledFunctions::eraseElement(std::list<ScheduledFunctions::ScheduledElement>::iterator it)
47+
{
48+
countElements--;
49+
return scheduledFunctions.erase(it);
50+
}
51+
52+
bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf, bool continuous, bool front)
53+
{
54+
return (insertElement({this,continuous,nullptr,sf}, front) == nullptr);
55+
}
56+
57+
bool ScheduledFunctions::scheduleFunction(ScheduledFunction sf)
58+
{
59+
return scheduleFunction(sf, false, false);
60+
}
61+
62+
ScheduledRegistration ScheduledFunctions::scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front)
63+
{
64+
return insertElement({this,continuous,std::make_shared<int>(1),sf},front);
65+
}
66+
67+
void ScheduledFunctions::runScheduledFunctions()
68+
{
69+
auto lastElement = scheduledFunctions.end(); // do not execute elements added during runScheduledFunctions
70+
auto it = scheduledFunctions.begin();
71+
while (it != lastElement)
72+
{
73+
bool erase = false;
74+
if (it->registration == nullptr)
75+
{
76+
it->function();
77+
}
78+
else
79+
{
80+
if (it->registration.use_count() > 1)
81+
{
82+
it->function();
83+
}
84+
else
85+
{
86+
erase = true;
87+
}
88+
}
89+
if ((!it->continuous) || (erase))
90+
{
91+
it = it->_this->eraseElement(it);
92+
}
93+
else
94+
{
95+
it++;
96+
}
97+
}
98+
}
99+
100+
void ScheduledFunctions::removeFunction(ScheduledRegistration sr)
101+
{
102+
auto it = scheduledFunctions.begin();
103+
bool removed = false;
104+
while ((!removed) && (it != scheduledFunctions.end()))
105+
{
106+
if (it->registration == sr)
107+
{
108+
it = eraseElement(it);
109+
removed = true;
110+
}
111+
else
112+
{
113+
it++;
114+
}
115+
}
116+
}
117+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* ScheduledFunctions.h
3+
*
4+
* Created on: 27 apr. 2018
5+
* Author: Herman
6+
*/
7+
#include "Arduino.h"
8+
#include "Schedule.h"
9+
10+
#include <functional>
11+
#include <memory>
12+
#include <list>
13+
#include <climits>
14+
15+
#ifndef SCHEDULEDFUNCTIONS_H_
16+
#define SCHEDULEDFUNCTIONS_H_
17+
18+
typedef std::function<void(void)> ScheduledFunction;
19+
typedef std::shared_ptr<void> ScheduledRegistration;
20+
21+
class ScheduledFunctions {
22+
23+
public:
24+
ScheduledFunctions();
25+
ScheduledFunctions(unsigned int reqMax);
26+
virtual ~ScheduledFunctions();
27+
28+
struct ScheduledElement
29+
{
30+
ScheduledFunctions* _this;
31+
bool continuous;
32+
ScheduledRegistration registration;
33+
ScheduledFunction function;
34+
};
35+
36+
ScheduledRegistration insertElement(ScheduledElement se, bool front);
37+
std::list<ScheduledElement>::iterator eraseElement(std::list<ScheduledElement>::iterator);
38+
bool scheduleFunction(ScheduledFunction sf, bool continuous, bool front);
39+
bool scheduleFunction(ScheduledFunction sf);
40+
ScheduledRegistration scheduleFunctionReg (ScheduledFunction sf, bool continuous, bool front);
41+
static void runScheduledFunctions();
42+
void removeFunction(ScheduledRegistration sr);
43+
44+
45+
static std::list<ScheduledElement> scheduledFunctions;
46+
unsigned int maxElements;
47+
unsigned int countElements = 0;
48+
49+
};
50+
51+
#endif /* SCHEDULEDFUNCTIONS_H_ */

0 commit comments

Comments
 (0)