-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlibstorm.h
More file actions
361 lines (348 loc) · 10.7 KB
/
Copy pathlibstorm.h
File metadata and controls
361 lines (348 loc) · 10.7 KB
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
#ifndef __LIBSTORM_H__
#define __LIBSTORM_H__
#include <memory>
#include <functional>
#include <queue>
#include <stdio.h>
using std::move;
namespace storm
{
using buf_t = std::shared_ptr<std::vector<uint8_t>>;
std::shared_ptr<std::vector<uint8_t>> mkbuf(size_t size);
std::shared_ptr<std::vector<uint8_t>> mkbuf(std::initializer_list<uint8_t> contents);
namespace _priv
{
uint32_t __attribute__((naked)) syscall_ex(...);
}
namespace tq
{
class Task
{
public:
Task(std::shared_ptr<std::function<void(void)>> target) : target(target){}
void fire();
private:
const std::shared_ptr<std::function<void(void)>> target;
};
extern std::queue<Task> dyn_tq;
template <typename T> bool add(T target)
{
dyn_tq.push(Task(std::make_shared<std::function<void(void)>>(target)));
return true;
}
void __attribute__((noreturn)) scheduler();
}
namespace util
{
class Resource
{
public:
Resource();
void acquire(std::function<void()>);
void release();
private:
bool active;
std::queue<std::function<void()>> queue;
};
}
namespace gpio
{
struct Pin {
const uint16_t idx;
const uint16_t spec;
};
struct Dir {
const uint8_t dir;
};
struct Edge {
const uint8_t edge;
};
struct Pull {
const uint8_t dir;
};
//Pin directions
extern const Dir OUT;
extern const Dir IN;
//Pins
constexpr Pin D0 = {0,0x0109};
constexpr Pin D1 = {1,0x010A};
constexpr Pin D2 = {2,0x0010};
constexpr Pin D3 = {3,0x000C};
constexpr Pin D4 = {4,0x0209};
constexpr Pin D5 = {5,0x000A};
constexpr Pin D6 = {6,0x000B};
constexpr Pin D7 = {7,0x0013};
constexpr Pin D8 = {8,0x000D};
constexpr Pin D9 = {9,0x010B};
constexpr Pin D10 = {10,0x010C};
constexpr Pin D11 = {11,0x010F};
constexpr Pin D12 = {12,0x010E};
constexpr Pin D13 = {13,0x010D};
constexpr Pin A0 = {14,0x0105};
constexpr Pin A1 = {15,0x0104};
constexpr Pin A2 = {16,0x0103};
constexpr Pin A3 = {17,0x0102};
constexpr Pin A4 = {18,0x0007};
constexpr Pin A5 = {19,0x0005};
constexpr Pin GP0 = {20,0x020A};
//Pin values
extern const uint8_t HIGH;
extern const uint8_t LOW;
extern const uint8_t TOGGLE;
//Edges
extern const Edge RISING;
extern const Edge FALLING;
extern const Edge CHANGE;
//Pull
extern const Pull UP;
extern const Pull DOWN;
extern const Pull KEEP;
extern const Pull NONE;
//GPIO functions
uint32_t set_mode(Pin pin, Dir dir);
uint32_t set(Pin pin, uint8_t value);
uint8_t get(Pin pin);
uint8_t get_shadow(Pin pin);
void set_pull(Pin pin, Pull pull);
void enable_irq(Pin pin, Edge edge, std::shared_ptr<std::function<void()>> callback);
void disable_irq(Pin pin);
}
class Timer
{
public:
Timer() = delete;
Timer(const Timer& that) = delete;
template<typename T> static std::shared_ptr<Timer> once(uint32_t ticks, T callback)
{
auto rv = std::shared_ptr<Timer>(new Timer(false, ticks, std::make_shared<std::function<void(std::shared_ptr<Timer>)>>(callback)));
rv->self = rv; //Circle reference, we cannot be deconstructed
return rv;
}
template<typename T> static std::shared_ptr<Timer> periodic(uint32_t ticks, T callback)
{
auto rv = std::shared_ptr<Timer>(new Timer(true, ticks, std::make_shared<std::function<void(std::shared_ptr<Timer>)>>(callback)));
rv->self = rv; //Circle reference, we cannot be deconstructed
return rv;
}
void cancel();
void fire();
static constexpr uint32_t MILLISECOND = 375;
static constexpr uint32_t SECOND = MILLISECOND*1000;
static constexpr uint32_t MINUTE = SECOND*60;
static constexpr uint32_t HOUR = MINUTE*60;
private:
Timer(bool periodic, uint32_t ticks, std::shared_ptr<std::function<void(std::shared_ptr<Timer>)>> callback);
uint16_t id;
bool is_periodic;
const std::shared_ptr<std::function<void(std::shared_ptr<Timer>)>> callback;
std::shared_ptr<Timer> self;
};
namespace sys
{
struct Shift {
const uint16_t code;
};
uint32_t now();
uint32_t now(Shift shift);
void reset();
void kick_wdt();
extern const Shift SHIFT_0;
extern const Shift SHIFT_16;
extern const Shift SHIFT_48;
}
class UDPSocket;
namespace _priv
{
struct udp_recv_params_t;
void udp_callback(UDPSocket *sock, udp_recv_params_t *recv, char *addrstr);
}
class UDPSocket
{
public:
class Packet
{
public:
std::string payload;
std::string strsrc;
uint8_t src[16];
uint16_t port;
uint8_t lqi;
uint8_t rssi;
};
template<typename T> static std::shared_ptr<UDPSocket> open(uint16_t port, T callback)
{
auto rv = std::shared_ptr<UDPSocket>(new UDPSocket(port, std::make_shared<std::function<void(std::shared_ptr<Packet>)>>(callback)));
if (!rv->okay)
{
return std::shared_ptr<UDPSocket>();
}
rv->self = rv; //Circle reference, we cannot be deconstructed
return rv;
}
void close();
void _handle(_priv::udp_recv_params_t *recv, char *addrstr);
bool sendto(const std::string &addr, uint16_t port, const std::string &payload);
bool sendto(const std::string &addr, uint16_t port, const uint8_t *payload, size_t length);
bool sendto(const std::string &addr, uint16_t port, buf_t payload, size_t length);
private:
UDPSocket(uint16_t port, std::shared_ptr<std::function<void(std::shared_ptr<Packet>)>> callback);
int32_t id;
bool okay;
const std::shared_ptr<std::function<void(std::shared_ptr<Packet>)>> callback;
std::shared_ptr<UDPSocket> self;
};
namespace flash
{
class FlashWOperation;
class FlashROperation;
extern util::Resource lock;
}
namespace _priv
{
void flash_wcallback(flash::FlashWOperation *op, int status);
void flash_rcallback(flash::FlashROperation *op, int status);
}
namespace flash
{
class FlashWOperation
{
public:
FlashWOperation(buf_t payload, std::function<void(int, buf_t)> callback)
:payload(move(payload)), callback(callback)
{
}
void invoke(int status)
{
callback(status, move(payload));
self.reset();
}
buf_t payload;
std::function<void(int, buf_t)> callback;
std::shared_ptr<FlashWOperation> self;
};
class FlashROperation
{
public:
FlashROperation(buf_t payload, size_t length, std::function<void(int, buf_t)> callback)
: length(length), payload(move(payload)), callback(callback)
{
}
void invoke(int status)
{
callback(status, move(payload));
self.reset();
}
size_t length;
buf_t payload;
std::function<void(int, buf_t)> callback;
std::shared_ptr<FlashROperation> self;
};
template <typename T> std::shared_ptr<FlashWOperation> write(uint32_t address, buf_t payload, uint8_t length, T callback)
{
auto rv = std::make_shared<FlashWOperation>(move(payload), std::function<void(int, buf_t)>(callback));
rv->self = rv; //circular reference to prevent dealloc.
int sysrv = _priv::syscall_ex(0xA02, address, &((*rv->payload)[0]), length, _priv::flash_wcallback, rv.get());
return sysrv ? nullptr : rv;
}
template <typename T> std::shared_ptr<FlashROperation> read(uint32_t address, buf_t target, uint8_t length, T callback)
{
auto rv = std::make_shared<FlashROperation>(move(target), length, std::function<void(int, buf_t)>(callback));
rv->self = rv; //circular reference to prevent dealloc.
int sysrv = _priv::syscall_ex(0xA01, address, &((*rv->payload)[0]), length, _priv::flash_rcallback, rv.get());
return sysrv ? nullptr : rv;
}
void erase_chip();
}
namespace i2c
{
class I2CWOperation;
class I2CROperation;
}
namespace _priv
{
void i2c_wcallback(i2c::I2CWOperation *op, int status);
void i2c_rcallback(i2c::I2CROperation *op, int status);
}
namespace i2c
{
extern util::Resource lock;
class I2CFlag
{
public:
constexpr I2CFlag operator| (I2CFlag const& rhs)
{
return I2CFlag{val+rhs.val};
}
uint32_t val;
};
class I2CWOperation
{
public:
I2CWOperation(buf_t payload, std::function<void(int, buf_t)> callback)
:payload(move(payload)), callback(callback)
{
}
void invoke(int status)
{
callback(status, move(payload));
self.reset();
}
buf_t payload;
std::function<void(int, buf_t)> callback;
std::shared_ptr<I2CWOperation> self;
};
class I2CROperation
{
public:
I2CROperation(buf_t payload, size_t length, std::function<void(int, buf_t)> callback)
: length(length), payload(move(payload)), callback(callback)
{
}
void invoke(int status)
{
callback(status, move(payload));
self.reset();
}
size_t length;
buf_t payload;
std::function<void(int, buf_t)> callback;
std::shared_ptr<I2CROperation> self;
};
template <typename T> std::shared_ptr<I2CWOperation> write(uint16_t address, I2CFlag const &flags, buf_t payload, uint16_t length, T callback)
{
auto rv = std::make_shared<I2CWOperation>(move(payload), std::function<void(int, buf_t)>(callback));
rv->self = rv; //circular reference to prevent dealloc.
int sysrv = _priv::syscall_ex(0x502, address, flags.val, &((*rv->payload)[0]), length, _priv::i2c_wcallback, rv.get());
return sysrv ? nullptr : rv;
}
template <typename T> std::shared_ptr<I2CROperation> read(uint16_t address, I2CFlag const &flags, buf_t target, uint16_t length, T callback)
{
auto rv = std::make_shared<I2CROperation>(move(target), length, std::function<void(int, buf_t)>(callback));
rv->self = rv; //circular reference to prevent dealloc.
int sysrv = _priv::syscall_ex(0x501, address, flags.val, &((*rv->payload)[0]), length, _priv::i2c_rcallback, rv.get());
return sysrv ? nullptr : rv;
}
constexpr uint16_t internal(uint8_t address)
{
return 0x200 + address;
}
constexpr uint16_t external(uint8_t address)
{
return 0x100 + address;
}
constexpr uint16_t TMP006 = internal(0x80);
constexpr I2CFlag NONE = I2CFlag{0};
constexpr I2CFlag START = I2CFlag{1};
constexpr I2CFlag RSTART = I2CFlag{1};
constexpr I2CFlag ACKLAST = I2CFlag{2};
constexpr I2CFlag STOP = I2CFlag{4};
constexpr int OK = 0;
constexpr int DNAK = 1;
constexpr int ANAK = 2;
constexpr int ERR = 3;
constexpr int ARBLST = 4;
constexpr int SYSCALL_ERR = 5;
const char* decode(int code);
}
}
#endif