-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathArduino_Threads.h
122 lines (110 loc) · 3.17 KB
/
Arduino_Threads.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
template<class T>
class Shared // template definition
{
public:
Shared() {
queue = new rtos::Queue<Shared<T>, 16>;
}
operator T() const {
osEvent evt = queue->get();
if (evt.status == osEventMessage) {
Shared<T> *x = (Shared<T>*)evt.value.p;
return x->val;
}
}
T& operator= (const T& other) {
val = other;
queue->put(this);
}
T& peek() {
return val;
}
T& latest() {
return peek();
}
private:
T val;
rtos::Queue<Shared<T>, 16> *queue;
};
#define CONCAT2(x,y) x##y
#define CONCAT(x,y) CONCAT2(x,y)
#define INCF(F) INCF_(F)
#define INCF_(F) #F
#define _macroToString(sequence) #sequence
class ArduinoThreads {
private:
static rtos::EventFlags globalEvents;
uint32_t startFlags;
uint32_t stopFlags;
uint32_t loopDelay;
virtual void setup(void) {};
virtual void loop(void) {};
void execute() {
setup();
// if startFlags have been passed then wait until all the flags are set
// before starting the loop. this is used to synchronize loops from multiple
// sketches.
if (startFlags != 0) {
globalEvents.wait_all(startFlags);
}
// if stopFlags have been passed stop when all the flags are set
// otherwise loop forever
while ( 1 ) {
loop();
// on exit clear the flags that have forced us to stop.
// note that if two groups of sketches stop on common flags
// the first group will clear them so the second group may never
// exit
if (stopFlags!=0) {
if ((globalEvents.get()&stopFlags)!=stopFlags) {
globalEvents.clear(stopFlags);
return;
}
if ((rtos::ThisThread::flags_get()&stopFlags)!=stopFlags) {
rtos::ThisThread::flags_clear(stopFlags);
return;
}
}
// sleep for the time we've been asked to insert between loops
rtos::ThisThread::sleep_for(loopDelay);
}
}
rtos::Thread *t;
protected:
char* _tabname;
public:
// start this sketch
void start(int stacksize = 4096, uint32_t startFlags=0, uint32_t stopFlags=0) {
this->startFlags = startFlags;
this->stopFlags = stopFlags;
loopDelay=0;
t = new rtos::Thread(osPriorityNormal, stacksize, nullptr, _tabname);
t->start(mbed::callback(this, &ArduinoThreads::execute));
}
// kill this sketch
void terminate() {
t->terminate();
}
// send an event to all sketches at the same time
static void broadcastEvent(uint32_t event) {
globalEvents.set(event);
}
// send an event only to this sketch
void sendEvent(uint32_t event) {
t->flags_set(event);
}
// set the rate at which loop function will be called
void setLoopDelay(uint32_t delay) {
loopDelay = delay;
}
};
rtos::EventFlags ArduinoThreads::globalEvents;
#define THD_ENTER(tabname) class CONCAT(tabname, Class) : public ArduinoThreads { \
public: \
CONCAT(tabname, Class)() { _tabname = _macroToString(tabname); } \
private: \
#define THD_DONE(tabname) \
}; \
CONCAT(tabname,Class) tabname;
#include "Wire.h"
#include "SerialDispatcher.h"