nmpp
ringbuffer_.h
1#ifndef RING_INCLUDED
2#define RING_INCLUDED
3#include <string.h>
4#include <time.h>
5
6#ifdef __NM__
7#undef CLOCKS_PER_SEC
8#define CLOCKS_PER_SEC 320000000
9#endif
10
11
12#define MIN(a,b) ((a) > (b) ? (b) : (a))
13
14#define RING_BUFFER_DECLARED 0xDEC1A8ED
15#define RING_BUFFER_ALLOCATED 0xA10CA7ED
16#define RING_BUFFER_MEM_ERROR 0xDEADF00D
17#define RING_BUFFER_ERROR 0xBEDABEDA
18#define RING_BUFFER_OK 0x0
19
20#define EXIT_ON_TIMEOUT 1
21#define EXIT_ON_COMPLETED 0
22#define EXIT_ON_FULL_BUFFER 2
23#define EXIT_ON_EMPTY_BUFFER 2
24
25#ifdef __NM__
26#define bytesizeof(T) (sizeof(T)<<2)
27#else
28#define bytesizeof(T) sizeof(T)
29#endif
30
31typedef void *(*memcpy_ptr)(void *, void const *, size_t) ;
32typedef void *(*t_bytecpy)(void *to, int toIndex, void const *from, int fromIndex, size_t size) ;
33template <class T> class C_RingBuffer{
34public:
35 T* data;
36 size_t size;
37 size_t head;
38 size_t tail;
39 size_t* head_addr;
40 size_t* tail_addr;
41 size_t id;
42
43 t_bytecpy push_memcpy;
44 t_bytecpy pop_memcpy;
45
46 // ------------- dma --------------
47 memcpy_ptr dma_init;
48 size_t(*dma_check)();
49 T* dma_ptr;
50 size_t dma_left;
51 size_t dma_size;
52 //----------------------------------
53 unsigned timeout; // msec
54 unsigned time2sleep; // msec
55 int pad[16-3-5*sizeof(memcpy_ptr)/sizeof(int)];
56
57
58 void Sleep(clock_t msec ){
59 #ifdef __NM__
60 clock_t dt=msec*(CLOCKS_PER_SEC/1000);
61 clock_t t0=clock();
62 while(clock()-t0<dt){
63 __asm{
64 rep 32 with vfalse;
65 rep 32 with afifo and afifo;
66 rep 32 with afifo and afifo;
67 rep 32 with afifo and afifo;
68 rep 32 with afifo and afifo;
69 rep 32 with afifo and afifo;
70 rep 32 with afifo and afifo;
71 rep 32 with afifo and afifo;
72 rep 32 with afifo and afifo;
73 rep 32 [ar7] = afifo;
74 }
75 }
76
77 #else
78 ::Sleep(msec);
79 #endif
80 }
82
83 //sizeof_size_t=sizeof(size_t);
84 //sizeof_T=sizeof(T);
85 //Init(0,0,(memcpy_ptr)memcpy,(memcpy_ptr)memcpy);
86 Init(0,0,0,0);
87 }
88 C_RingBuffer(T* buffer,size_t count, t_bytecpy pushmemcpy, t_bytecpy popmemcpy ){
89 Init(buffer,count,pushmemcpy,popmemcpy);
90 }
91 //void Init(T* buffer,size_t count, memcpy_ptr pushmemcpy, memcpy_ptr popmemcpy ){
92 bool Init(T* buffer,size_t count, t_bytecpy pushmemcpy, t_bytecpy popmemcpy ){
93 if (buffer==0) return false;
94 if (count&(count-1)!=0) return false ;
95 data=buffer;
96 size=count;
97 head=0;
98 tail=0;
99 head_addr=&head;
100 tail_addr=&tail;
101 id=0x600DB00F;
102 push_memcpy=(t_bytecpy)pushmemcpy;
103 pop_memcpy =(t_bytecpy)popmemcpy;
104 dma_init=0;
105 dma_check=0;
106 dma_ptr =0;
107 dma_left=0;
108 dma_size=0;
109 time2sleep=1; // msec
110 timeout=100; //
111 return true;
112
113 }
114
115 __INLINE__ bool IsFull(){
116 return (head-tail==size);
117 }
118 __INLINE__ bool IsEmpty(){
119 return (head==tail);
120 }
121 __INLINE__ size_t PushAvail(){
122 return (size-(head-tail));
123 }
124 __INLINE__ size_t PopAvail(){
125 return (head-tail);
126 }
127
128
129 T* Head(){
130 if (PushAvail()==0)
131 return 0;
132 size_t headPointer=head&(size-1);
133 T* pElement=data+headPointer;
134 return pElement;
135 }
136 T* Tail(){
137 if (PopAvail()==0)
138 return 0;
139 size_t tailPointer=tail&(size-1);
140 T* pElement=data+tailPointer;
141 return pElement;
142 }
143
144 bool MoveHead(int numElements){
145 size_t h=head+numElements;
146 if (h>tail+size)
147 return RING_BUFFER_ERROR;
148 head=h;
149 return RING_BUFFER_OK;
150 }
151
152 bool MoveTail(int numElements){
153 size_t t=tail+numElements;
154 if (t>head)
155 return RING_BUFFER_ERROR;
156 tail=t;
157 return RING_BUFFER_OK;
158 }
159
160
161 size_t Push(T* pSrcElements, size_t numElements, int ExitMode= EXIT_ON_COMPLETED)
162 {
163 size_t initHead=head;
164 size_t count;
165 size_t diff;
166 clock_t t0=clock();
167 size_t posSrc=0;
168 while (numElements){
169 size_t Tail=tail;
170 size_t posHead=head&(size-1);
171 size_t posTail=Tail&(size-1);
172 if (posTail<posHead || head==Tail)
173 diff=size-posHead;
174 else if (posHead<posTail)
175 diff=posTail-posHead;
176 else if (ExitMode&EXIT_ON_FULL_BUFFER) // buffer is full
177 return (head-initHead);
178 else if (ExitMode&EXIT_ON_TIMEOUT){
179 if ((clock()-t0)>timeout*(CLOCKS_PER_SEC/1000))
180 return (head-initHead);
181 Sleep(time2sleep);
182 continue;
183 } else { // EXIT_ON_COMPLETED
184 Sleep(time2sleep);
185 continue;
186 }
187
188 count=MIN(numElements,diff);
189 if (push_memcpy(data,posHead*bytesizeof(T),pSrcElements,posSrc*bytesizeof(T),count*bytesizeof(T))){
190 head+=count;
191 posSrc+=count;
192 numElements -=count;
193 }
194 }
195 return (head-initHead);
196 }
197
198 size_t Push(T pSrcElement)
199 {
200 return Push(&pSrcElement,1,EXIT_ON_COMPLETED);
201 }
202
203 void PushRequest(T* pSrcElements, size_t numElements)
204 {
205 size_t posHead;
206 size_t posTail;
207 size_t diff=0;
208 while(diff==0){
210 posHead=head&(size-1);
211 posTail=tail&(size-1);
212 if (posTail<posHead || head==tail)
213 diff=size-posHead;
214 else if (posHead<posTail)
215 diff=posTail-posHead;
216 else { // buffer is full
217 Sleep(time2sleep);
218 continue;
219 }
220 }
221 dma_ptr =pSrcElements;
222 dma_left =numElements;
223 dma_size =MIN(dma_left,diff);
224 //dma_init(data,posHead,pSrcElements,0,dma_size*sizeof(T));
225 }
226
227 bool isPushCompleted()
228 {
229 if (dma_left==0)
230 return true;
231 if (dma_check())
232 return false;
233
234 head +=dma_size;
235 dma_ptr +=dma_size;
236 dma_left -=dma_size;
237 if (dma_left){
238 PushRequest(dma_ptr,dma_left);//?
239 return false;
240 }
241 return true;
242
243 }
244
245
246
247
248
249
250 size_t Pop(T* pDstElements, size_t numElements, int ExitMode= EXIT_ON_COMPLETED)
251 {
252 size_t initTail=tail;
253 size_t count;
254 size_t diff;
255 clock_t t0=clock();
256 size_t posDst=0;
257 while (numElements){
258 size_t Head=head;
259 size_t posHead=Head&(size-1);
260 size_t posTail=tail&(size-1);
261 if (posTail<posHead )
262 diff=posHead-posTail;
263 else if (posHead<=posTail && Head!=tail)
264 diff=size-posTail;
265 else if (ExitMode&EXIT_ON_EMPTY_BUFFER) // buffer is empty
266 return (tail-initTail);
267 else if (ExitMode&EXIT_ON_TIMEOUT){
268 if ((clock()-t0)>timeout)
269 return (tail-initTail);
270 Sleep(time2sleep);
271 continue;
272 } else {
273 //Sleep(time2sleep);
274 continue;
275 }
276
277 count=MIN(numElements,diff);
278 pop_memcpy(pDstElements,posDst*bytesizeof(T),data,posTail*bytesizeof(T),count*bytesizeof(T));
279 tail+=count;
280 posDst+=count;
281 numElements -=count;
282 }
283 return (tail-initTail);
284 }
285
286
287
288
289
290
291
292};
293
294
295#endif
Definition: ringbuffer_.h:33
int pad[16-3-5 *sizeof(memcpy_ptr)/sizeof(int)]
резервные поля
Definition: ringbuffer_.h:55
void PushRequest(T *pSrcElements, size_t numElements)
Definition: ringbuffer_.h:203
size_t size
размер кольцевого буфера входных данных (в элементах; гарантируется что это степень двойки)
Definition: ringbuffer_.h:36
size_t tail
сколько элементов ОТ НАЧАЛА ПОТОКА код SLAVE уже прочитал (обработал) [заполняется SLAVE]
Definition: ringbuffer_.h:38
size_t head
сколько элементов ОТ НАЧАЛА ПОТОКА код MASTER уже записал в буфер входных данных [заполняется MASTER]
Definition: ringbuffer_.h:37
T * data
физический адрес кольцевого буфера входных данных
Definition: ringbuffer_.h:35