-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcircbuf.h
131 lines (116 loc) · 3.33 KB
/
circbuf.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
123
124
125
126
127
128
129
130
131
// Circular buffer for incoming reports. We write reports in the IRQ
// handler, and we read reports in the main loop in normal application
// (non-IRQ) context.
//
// The design is organically safe for IRQ threading; there are no critical
// sections. The IRQ context has exclusive access to the write pointer,
// and the application context has exclusive access to the read pointer,
// so there are no test-and-set or read-and-modify race conditions.
#ifndef _CIRCBUF_H_
#define _CIRCBUF_H_
// Circular buffer with a fixed buffer size
template<class T, int cnt> class CircBuf
{
public:
CircBuf()
{
iRead = iWrite = 0;
}
// Read an item from the buffer. Returns true if an item was available,
// false if the buffer was empty. (Called in the main loop, in application
// context.)
bool read(T &result)
{
if (iRead != iWrite)
{
//{uint8_t *d = buf[iRead].data; printf("circ read [%02x %02x %02x %02x %02x %02x %02x %02x]\r\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);}
memcpy(&result, &buf[iRead], sizeof(T));
iRead = advance(iRead);
return true;
}
else
return false;
}
// is an item ready to read?
bool readReady() const { return iRead != iWrite; }
// Write an item to the buffer. (Called in the IRQ handler, in interrupt
// context.)
bool write(const T &item)
{
int nxt = advance(iWrite);
if (nxt != iRead)
{
memcpy(&buf[iWrite], &item, sizeof(T));
iWrite = nxt;
return true;
}
else
return false;
}
private:
int advance(int i)
{
++i;
return i < cnt ? i : 0;
}
int iRead;
int iWrite;
T buf[cnt];
};
// Circular buffer with a variable buffer size
template<class T> class CircBufV
{
public:
CircBufV(int cnt)
{
buf = new T[cnt];
this->cnt = cnt;
iRead = iWrite = 0;
}
~CircBufV()
{
delete[] buf;
}
// Read an item from the buffer. Returns true if an item was available,
// false if the buffer was empty. (Called in the main loop, in application
// context.)
bool read(T &result)
{
if (iRead != iWrite)
{
//{uint8_t *d = buf[iRead].data; printf("circ read [%02x %02x %02x %02x %02x %02x %02x %02x]\r\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);}
memcpy(&result, &buf[iRead], sizeof(T));
iRead = advance(iRead);
return true;
}
else
return false;
}
// is an item ready to read?
bool readReady() const { return iRead != iWrite; }
// Write an item to the buffer. (Called in the IRQ handler, in interrupt
// context.)
bool write(const T &item)
{
int nxt = advance(iWrite);
if (nxt != iRead)
{
memcpy(&buf[iWrite], &item, sizeof(T));
iWrite = nxt;
return true;
}
else
return false;
}
private:
int advance(int i)
{
++i;
return i < cnt ? i : 0;
}
int iRead;
int iWrite;
int cnt;
T *buf;
};
#endif