-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathPipe.ino
163 lines (143 loc) · 3.47 KB
/
Pipe.ino
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* A sketch that illustrates using two coroutines and a channel to create a
* pipe between them. Work in progress... Haven't had time to finish this
* line of research.
*/
#include <Arduino.h>
#include <AceRoutine.h>
#define CHANNEL_TYPE_SYNC 0
#define CHANNEL_TYPE_NO_SYNC 1
#define CHANNEL_TYPE CHANNEL_TYPE_SYNC
#define TEST_TYPE_LOOP 0
#define TEST_TYPE_SEQ 1
#define TEST_TYPE TEST_TYPE_LOOP
using namespace ace_routine;
/**
* An unbuffered channel that provides no synchronization. Perhaps better
* described as a buffered channel of size 1.
*
* Because of the buffering of size one, sending 10 integers from the writer to
* the reader has the following order:
*
* @code
* Writer: sending 0
* Writer: sending 1
* Reader: received 0
* Writer: sending 2
* Reader: received 1
* Writer: sending 3
* Reader: received 2
* ...
* @endcode
*
* In other words, the receiver is one iteration behind the writer.
*
* TODO: Figure out if it's useful to move into the src/ace_time/ directory,
* perhaps as a BufferedChannel?
*/
template<typename T>
class NoSyncChannel {
public:
void setValue(const T& value) {
mValueToWrite = value;
}
bool write() {
if (mDataReady) {
return false;
} else {
mValue = mValueToWrite;
mDataReady = true;
return true;
}
}
bool write(const T& value) {
if (mDataReady) {
return false;
} else {
mValue = value;
mDataReady = true;
return true;
}
}
bool read(T& value) {
if (mDataReady) {
value = mValue;
mDataReady = false;
return true;
} else {
return false;
}
}
private:
T mValue;
T mValueToWrite;
bool mDataReady = false;
};
struct Message {
static uint8_t const kStatusOk = 0;
static uint8_t const kStatusError = 1;
uint8_t status;
int value;
};
#if CHANNEL_TYPE == CHANNEL_TYPE_NO_SYNC
NoSyncChannel<Message> channel;
#elif CHANNEL_TYPE == CHANNEL_TYPE_SYNC
// This is a synchronized unbuffered Channel.
Channel<Message> channel;
#endif
#if TEST_TYPE == TEST_TYPE_LOOP
// Test the ordering of sending 10 integers and receiving 10 integers.
COROUTINE(writer) {
static int i;
static Message message;
COROUTINE_BEGIN();
for (i = 0; i < 10; i++) {
Serial.print("Writer: sending ");
Serial.println(i);
message = {Message::kStatusOk, i};
COROUTINE_CHANNEL_WRITE(channel, message);
}
Serial.println("Writer: done");
COROUTINE_END();
}
COROUTINE(reader) {
static Message message;
COROUTINE_LOOP() {
COROUTINE_CHANNEL_READ(channel, message);
Serial.print("Reader: received ");
Serial.println(message.value);
}
}
#else
// Test the sequencing of the writer and reader.
COROUTINE(writer) {
COROUTINE_BEGIN();
Serial.println("Writer: sending data");
COROUTINE_CHANNEL_WRITE(channel, 42);
Serial.println("Writer: sent data");
COROUTINE_END();
}
COROUTINE(reader) {
COROUTINE_BEGIN();
Serial.println("Reader: sleeping for 1 second");
COROUTINE_DELAY(1000);
Serial.println("Reader: receiving data");
int data;
COROUTINE_CHANNEL_READ(channel, data);
Serial.println("Reader: received data");
COROUTINE_END();
}
#endif
void setup() {
#if ! defined(EPOXY_DUINO)
delay(1000);
#endif
Serial.begin(115200);
while (!Serial); // Leonardo/Micro
}
void loop() {
// The order of these 2 shouldn't matter, but we should flip them
// occasionally to verify that.
reader.runCoroutine();
writer.runCoroutine();
}