yfifo.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * $Id: yfifo.c 23630 2016-03-29 21:05:54Z mvuilleu $
4  *
5  * Implementation of a generic fifo queue
6  *
7  * - - - - - - - - - License information: - - - - - - - - -
8  *
9  * Copyright (C) 2011 and beyond by Yoctopuce Sarl, Switzerland.
10  *
11  * Yoctopuce Sarl (hereafter Licensor) grants to you a perpetual
12  * non-exclusive license to use, modify, copy and integrate this
13  * file into your software for the sole purpose of interfacing
14  * with Yoctopuce products.
15  *
16  * You may reproduce and distribute copies of this file in
17  * source or object form, as long as the sole purpose of this
18  * code is to interface with Yoctopuce products. You must retain
19  * this notice in the distributed source file.
20  *
21  * You should refer to Yoctopuce General Terms and Conditions
22  * for additional information regarding your rights and
23  * obligations.
24  *
25  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
26  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
27  * WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS
28  * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO
29  * EVENT SHALL LICENSOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
30  * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA,
31  * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR
32  * SERVICES, ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT
33  * LIMITED TO ANY DEFENSE THEREOF), ANY CLAIMS FOR INDEMNITY OR
34  * CONTRIBUTION, OR OTHER SIMILAR COSTS, WHETHER ASSERTED ON THE
35  * BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE), BREACH OF
36  * WARRANTY, OR OTHERWISE.
37  *
38  *********************************************************************/
39 #define __FILE_ID__ "yfifo"
40 
41 #include "ydef.h"
42 
43 #if defined(MICROCHIP_API)
44 #include "api.h"
45 #else
46 #include "yfifo.h"
47 #include "yproto.h"
48 #endif
49 
51 #ifdef DEBUG_FIFO
52  const char* fileid, int line,
53 #endif
54  yFifoBuf *buf, u8 *buffer, u16 bufflen)
55 {
56  memset(buf,0,sizeof(yFifoBuf));
57  buf->buff = buffer;
58  buf->buffsize = bufflen;
59  buf->head = buf->tail = buffer;
60 #ifdef DEBUG_FIFO
61  buf->line = line;
62  buf->fileid = fileid;
63 #endif
64 #ifdef YFIFO_USE_MUTEX
65  yInitializeCriticalSection(&(buf->cs));
66 #endif
67 }
68 
69 #ifndef MICROCHIP_API
71 {
72 #ifdef YFIFO_USE_MUTEX
73  yDeleteCriticalSection(&(buf->cs));
74 #endif
75  memset(buf,0,sizeof(yFifoBuf));
76 }
77 #endif
78 
79 #ifdef YFIFO_USE_MUTEX
80 
82 {
83  yEnterCriticalSection(&(buf->cs));
84 }
85 
87 {
88  yLeaveCriticalSection(&(buf->cs));
89 }
90 #endif
91 
93 {
94  buf->datasize = 0;
95  buf->head = buf->tail = buf->buff;
96 }
97 
98 #ifdef YFIFO_USE_MUTEX
99 
101 {
102  yFifoEnterCS(buf);
103  yFifoEmptyEx(buf);
104  yFifoLeaveCS(buf);
105 }
106 #endif
107 
108 u16 yPushFifoEx(yFifoBuf *buf, const u8 *data, u16 datalen)
109 {
110  u16 freespace = buf->buffsize - buf->datasize;
111 
112  if (datalen > freespace) {
113  // not enough space available in
114  // buffer to handle correctly this packet
115  // (we do not handle partial packet since usb packet are
116  // max 64byte long)
117  return 0;
118  }
119  //append data to our fifo buffer
120  if (buf->tail + datalen <= YFIFOEND(buf)) {
121  memcpy(buf->tail, data, datalen);
122  buf->tail += datalen;
123  if (buf->tail == YFIFOEND(buf))
124  buf->tail = buf->buff;
125  } else {
126  u16 cplen = (u16)(YFIFOEND(buf) - buf->tail);
127  memcpy(buf->tail, data, cplen);
128  memcpy(buf->buff, data + cplen, datalen - cplen);
129  buf->tail = buf->buff + (datalen - cplen);
130  }
131  // This must remain very last, so that datasize always remain
132  // the number of bytes really available in buffer (may be polled
133  // from within interrupt handlers)
134  buf->datasize += datalen;
135 #ifdef DEBUG_FIFO
136  buf->totalPushed += datalen;
137 #endif
138  return datalen;
139 }
140 
141 #ifdef YFIFO_USE_MUTEX
142 
143 u16 yPushFifo(yFifoBuf *buf, const u8 *data, u16 datalen)
144 {
145  u16 res;
146  yFifoEnterCS(buf);
147  res = yPushFifoEx(buf,data,datalen);
148  yFifoLeaveCS(buf);
149  return res;
150 }
151 #endif
152 
153 u16 yPopFifoEx(yFifoBuf *buf, u8 *data, u16 datalen)
154 {
155  if (datalen > buf->datasize)
156  datalen = buf->datasize;
157  if (buf->head + datalen > YFIFOEND(buf)) {
158  //need to handle wrap
159  u16 firstpart = (u16)(YFIFOEND(buf) - buf->head);
160  if (data) {
161  memcpy(data, buf->head, firstpart);
162  memcpy(data + firstpart, buf->buff, datalen - firstpart);
163  }
164 
165  buf->head = buf->buff + (datalen - firstpart);
166  } else {
167  if (data) {
168  memcpy(data, buf->head, datalen);
169  }
170  buf->head += datalen;
171  if (buf->head == YFIFOEND(buf))
172  buf->head -= buf->buffsize;
173  }
174  // This must remain very last, so that buffsize-datasize always
175  // remain the number of bytes really free in buffer (may be polled
176  // from within interrupt handlers)
177  buf->datasize -= datalen;
178 #ifdef DEBUG_FIFO
179  buf->totalPopded += datalen;
180 #endif
181  return datalen;
182 }
183 
184 
185 #ifdef YFIFO_USE_MUTEX
186 
187 u16 yPopFifo(yFifoBuf *buf, u8 *data, u16 datalen)
188 {
189  u16 res;
190  yFifoEnterCS(buf);
191  res = yPopFifoEx(buf,data,datalen);
192  yFifoLeaveCS(buf);
193  return res;
194 }
195 #endif
196 
197 
198 static u16 yForceFifoEx(yFifoBuf *buf, const u8 *data, u16 datalen)
199 {
200  u16 freespace;
201  freespace = buf->buffsize - buf->datasize;
202 
203  if(datalen > buf->buffsize) {
204  return 0;
205  }
206 
207  if (datalen > freespace) {
208  // not enough space, drop oldest data
209  yPopFifoEx(buf, NULL, datalen - freespace);
210  }
211  return yPushFifoEx(buf, data, datalen);
212 }
213 
214 u16 yForceFifo(yFifoBuf *buf, const u8 *data, u16 datalen, u32 *absCounter)
215 {
216  u16 res;
217 
218 #ifndef MICROCHIP_API
219  yFifoEnterCS(buf);
220 #endif
221 
222  res = yForceFifoEx(buf,data,datalen);
223  *absCounter += res;
224 
225 #ifndef MICROCHIP_API
226  yFifoLeaveCS(buf);
227 #endif
228 
229  return res;
230 }
231 
232 u16 yPeekFifoEx(yFifoBuf *buf, u8 *data, u16 datalen, u16 startofs)
233 {
234  u8 *ptr ;
235  if(startofs > buf->datasize){
236  return 0;
237  }
238 
239  if (datalen + startofs > buf->datasize)
240  datalen = buf->datasize - startofs;
241 
242  ptr=buf->head+startofs;
243  if(ptr >= YFIFOEND(buf)){
244  ptr -= buf->buffsize;
245  }
246  if (ptr + datalen > YFIFOEND(buf)) {
247  //need to handle wrap
248  u16 firstpart = (u16)(YFIFOEND(buf) - ptr);
249  if (data) {
250  memcpy(data, ptr, firstpart);
251  memcpy(data + firstpart, buf->buff, datalen - firstpart);
252  }
253  } else {
254  if (data) {
255  memcpy(data, ptr, datalen);
256  }
257  }
258  return datalen;
259 }
260 
261 #ifdef YFIFO_USE_MUTEX
262 
263 u16 yPeekFifo(yFifoBuf *buf, u8 *data, u16 datalen, u16 startofs)
264 {
265  u16 res;
266  yFifoEnterCS(buf);
267  res = yPeekFifoEx(buf,data,datalen,startofs);
268  yFifoLeaveCS(buf);
269  return res;
270 }
271 #endif
272 
273 
274 u16 yPeekContinuousFifoEx(yFifoBuf *buf, u8 **ptr, u16 startofs)
275 {
276  u8 *lptr;
277 
278  if(startofs >= buf->datasize) {
279  return 0;
280  }
281 
282  lptr = buf->head + startofs;
283  if(lptr >= YFIFOEND(buf)) {
284  // wrap
285  if(ptr) {
286  *ptr = lptr - buf->buffsize;
287  }
288  return buf->datasize - startofs;
289  } else {
290  // no wrap
291  u16 toend = (u16)(YFIFOEND(buf) - lptr);
292  if(ptr) {
293  *ptr = lptr;
294  }
295  return (toend < buf->datasize ? toend : buf->datasize);
296  }
297 
298 }
299 
300 
301 #ifdef YFIFO_USE_MUTEX
302 
303 u16 yPeekContinuousFifo(yFifoBuf *buf, u8 **ptr, u16 startofs)
304 {
305  u16 res;
306  yFifoEnterCS(buf);
307  res = yPeekContinuousFifoEx(buf,ptr,startofs);
308  yFifoLeaveCS(buf);
309  return res;
310 }
311 #endif
312 
313 
314 u16 ySeekFifoEx(yFifoBuf *buf, const u8* pattern, u16 patlen, u16 startofs, u16 searchlen, u8 bTextCompare)
315 {
316  u8 *ptr;
317  u16 patidx;
318  u16 firstmatch = 0xffff;
319 
320  // pattern bigger than our buffer size -> not found
321  if (startofs + patlen > buf->datasize) {
322  return 0xffff;
323  }
324  // ajust searchlen and ptr to our buffer
325  // size and position
326  if (searchlen == 0 || searchlen > buf->datasize - startofs)
327  searchlen = buf->datasize - startofs;
328  ptr = buf->head + startofs;
329  if (ptr >= YFIFOEND(buf))
330  ptr -= buf->buffsize;
331 
332  patidx = 0;
333  while (searchlen > 0 && patidx < patlen) {
334  u16 bletter = *ptr;
335  u16 pletter = pattern[patidx];
336 
337  if (bTextCompare && pletter >= 'A' && bletter >= 'A' && pletter <= 'z' && bletter <= 'z') {
338  pletter &= ~32;
339  bletter &= ~32;
340  }
341  if (pletter == bletter) {
342  if(patidx == 0) {
343  firstmatch = startofs;
344  }
345  patidx++;
346  } else if(patidx > 0) {
347  // rescan this character as first pattern character
348  patidx = 0;
349  continue;
350  }
351  startofs++;
352  searchlen--;
353  ptr++;
354  if (ptr >= YFIFOEND(buf))
355  ptr -= buf->buffsize;
356 
357  }
358  if (patidx == patlen) {
359  return firstmatch;
360  }
361  return 0xffff;
362 }
363 
364 
365 #ifdef YFIFO_USE_MUTEX
366 
367 u16 ySeekFifo(yFifoBuf *buf, const u8* pattern, u16 patlen, u16 startofs, u16 searchlen, u8 bTextCompare)
368 {
369  u16 res;
370 
371  yFifoEnterCS(buf);
372  res = ySeekFifoEx(buf,pattern,patlen,startofs,searchlen,bTextCompare);
373  yFifoLeaveCS(buf);
374  return res;
375 }
376 #endif
377 
379 {
380  return buf->datasize;
381 }
382 
383 #ifdef YFIFO_USE_MUTEX
384 
386 {
387  u16 res;
388  yFifoEnterCS(buf);
389  res = yFifoGetUsedEx(buf);
390  yFifoLeaveCS(buf);
391  return res;
392 }
393 #endif
394 
396 {
397  return buf->buffsize-buf->datasize;
398 }
399 
400 #ifdef YFIFO_USE_MUTEX
402 {
403  u16 res;
404  yFifoEnterCS(buf);
405  res = yFifoGetFreeEx(buf);
406  yFifoLeaveCS(buf);
407  return res;
408 }
409 
410 #endif
411 
412 #ifndef REDUCE_COMMON_CODE
413 void yxtoa(u32 x, char *buf, u16 len)
414 {
415  buf[len] = 0;
416  while(len > 0) {
417  unsigned b = x & 0xf;
418  buf[--len] = (b>9u) ? b+'a'-10 : b+'0';
419  x >>= 4;
420  }
421 }
422 #endif
423 
424 #if defined(USE_TYPED_NOTIFICATIONS) || !defined(MICROCHIP_API)
425 
426 // Decode a standard (V1) or typed notification (V2), possibly not null terminated,
427 // to its text representation (always null terminated)
428 //
429 void decodePubVal(Notification_funydx funInfo, const char *funcval, char *buffer)
430 {
431  const unsigned char *p = (const unsigned char *)funcval;
432  u16 funcValType;
433  s32 numVal;
434  float floatVal;
435  int i;
436 
437  if(funInfo.v2.typeV2 == NOTIFY_V2_6RAWBYTES || funInfo.v2.typeV2 == NOTIFY_V2_TYPEDDATA) {
438  if(funInfo.v2.typeV2 == NOTIFY_V2_6RAWBYTES) {
439  funcValType = PUBVAL_6RAWBYTES;
440  } else {
441  funcValType = *p++;
442  }
443  switch(funcValType) {
444  case PUBVAL_LEGACY:
445  // fallback to legacy handling, just in case
446  break;
447  case PUBVAL_1RAWBYTE:
448  case PUBVAL_2RAWBYTES:
449  case PUBVAL_3RAWBYTES:
450  case PUBVAL_4RAWBYTES:
451  case PUBVAL_5RAWBYTES:
452  case PUBVAL_6RAWBYTES:
453  // 1..6 hex bytes
454  for(i = 0; i < funcValType; i++) {
455  unsigned c = *p++;
456  unsigned b = c >> 4;
457  buffer[2*i] = (b>9u) ? b+'a'-10 : b+'0';
458  b = c & 0xf;
459  buffer[2*i+1] = (b>9u) ? b+'a'-10 : b+'0';
460  }
461  buffer[2*i] = 0;
462  return;
463  case PUBVAL_C_LONG:
465  // 32bit integer in little endian format or Yoctopuce 10-3 format
466  numVal = *p++;
467  numVal += (s32)*p++ << 8;
468  numVal += (s32)*p++ << 16;
469  numVal += (s32)*p++ << 24;
470 #ifdef MICROCHIP_API
471  if(funcValType == PUBVAL_C_LONG) {
472  s32toa(numVal, buffer);
473  } else {
474  dectoa(numVal, buffer, YOCTO_PUBVAL_LEN-1, 1);
475  }
476 #else
477  if(funcValType == PUBVAL_C_LONG) {
478  YSPRINTF(buffer, YOCTO_PUBVAL_LEN, "%d", numVal);
479  } else {
480  char *endp;
481  YSPRINTF(buffer, YOCTO_PUBVAL_LEN, "%.3f", numVal/1000.0);
482  endp = buffer + strlen(buffer);
483  while(endp > buffer && endp[-1] == '0') {
484  *--endp = 0;
485  }
486  if(endp > buffer && endp[-1] == '.') {
487  *--endp = 0;
488  }
489  }
490 #endif
491  return;
492  case PUBVAL_C_FLOAT:
493  // 32bit (short) float
494  memcpy(&floatVal, p, sizeof(floatVal));
495 #ifdef MICROCHIP_API
496  dectoa(floatVal*1000.0, buffer, YOCTO_PUBVAL_LEN-1, 1);
497 #else
498  {
499  char largeBuffer[64];
500  char *endp;
501  YSPRINTF(largeBuffer, 64, "%.6f", floatVal);
502  endp = largeBuffer + strlen(largeBuffer);
503  while(endp > largeBuffer && endp[-1] == '0') {
504  *--endp = 0;
505  }
506  if(endp > largeBuffer && endp[-1] == '.') {
507  *--endp = 0;
508  }
509  YSTRCPY(buffer, YOCTO_PUBVAL_LEN, largeBuffer);
510  }
511 #endif
512  return;
513  default:
514  buffer[0] = '?';
515  buffer[1] = 0;
516  return;
517  }
518  }
519 
520  // Legacy handling: just pad with NUL up to 7 chars
521  for(i = 0; i < 6; i++,p++) {
522  u8 c = *p;
523  if(!c) break;
524  buffer[i] = c;
525  }
526  buffer[i] = 0;
527 }
528 
529 #endif
#define PUBVAL_6RAWBYTES
Definition: ydef.h:563
void yFifoEnterCS(yFifoBuf *buf)
Definition: yfifo.c:81
u16 yFifoGetUsedEx(yFifoBuf *buf)
Definition: yfifo.c:378
u16 yPeekContinuousFifo(yFifoBuf *buf, u8 **ptr, u16 startofs)
Definition: yfifo.c:303
#define PUBVAL_LEGACY
Definition: ydef.h:557
u16 yPushFifoEx(yFifoBuf *buf, const u8 *data, u16 datalen)
Definition: yfifo.c:108
void yInitializeCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:629
void yFifoCleanup(yFifoBuf *buf)
Definition: yfifo.c:70
#define NOTIFY_V2_TYPEDDATA
Definition: ydef.h:552
#define PUBVAL_1RAWBYTE
Definition: ydef.h:558
#define PUBVAL_C_FLOAT
Definition: ydef.h:565
u16 yPushFifo(yFifoBuf *buf, const u8 *data, u16 datalen)
Definition: yfifo.c:143
u16 yPeekFifo(yFifoBuf *buf, u8 *data, u16 datalen, u16 startofs)
Definition: yfifo.c:263
void yFifoEmptyEx(yFifoBuf *buf)
Definition: yfifo.c:92
u16 buffsize
Definition: yfifo.h:60
u8 * head
Definition: yfifo.h:63
u16 yFifoGetUsed(yFifoBuf *buf)
Definition: yfifo.c:385
yCRITICAL_SECTION cs
Definition: yfifo.h:66
void yLeaveCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:672
u16 yPeekContinuousFifoEx(yFifoBuf *buf, u8 **ptr, u16 startofs)
Definition: yfifo.c:274
void yFifoInitEx(yFifoBuf *buf, u8 *buffer, u16 bufflen)
Definition: yfifo.c:50
void yFifoLeaveCS(yFifoBuf *buf)
Definition: yfifo.c:86
u16 yFifoGetFreeEx(yFifoBuf *buf)
Definition: yfifo.c:395
#define PUBVAL_YOCTO_FLOAT_E3
Definition: ydef.h:566
#define YOCTO_PUBVAL_LEN
Definition: ydef.h:428
Definition: yfifo.h:59
#define YFIFOEND(fifobuf)
Definition: yfifo.h:76
#define PUBVAL_2RAWBYTES
Definition: ydef.h:559
void decodePubVal(Notification_funydx funInfo, const char *funcval, char *buffer)
Definition: yfifo.c:429
struct Notification_funydx::@10 v2
#define YSTRCPY(dst, dstsize, src)
Definition: yproto.h:234
static u16 yForceFifoEx(yFifoBuf *buf, const u8 *data, u16 datalen)
Definition: yfifo.c:198
u16 yPopFifoEx(yFifoBuf *buf, u8 *data, u16 datalen)
Definition: yfifo.c:153
u16 yPeekFifoEx(yFifoBuf *buf, u8 *data, u16 datalen, u16 startofs)
Definition: yfifo.c:232
#define NOTIFY_V2_6RAWBYTES
Definition: ydef.h:551
u16 yForceFifo(yFifoBuf *buf, const u8 *data, u16 datalen, u32 *absCounter)
Definition: yfifo.c:214
#define YSPRINTF
Definition: yproto.h:238
#define PUBVAL_4RAWBYTES
Definition: ydef.h:561
#define PUBVAL_5RAWBYTES
Definition: ydef.h:562
void yFifoEmpty(yFifoBuf *buf)
Definition: yfifo.c:100
u16 yFifoGetFree(yFifoBuf *buf)
Definition: yfifo.c:401
void yEnterCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:647
u8 * buff
Definition: yfifo.h:62
u16 ySeekFifoEx(yFifoBuf *buf, const u8 *pattern, u16 patlen, u16 startofs, u16 searchlen, u8 bTextCompare)
Definition: yfifo.c:314
void yDeleteCriticalSection(yCRITICAL_SECTION *cs)
Definition: ythread.c:682
void yxtoa(u32 x, char *buf, u16 len)
Definition: yfifo.c:413
#define PUBVAL_C_LONG
Definition: ydef.h:564
u8 * tail
Definition: yfifo.h:64
#define PUBVAL_3RAWBYTES
Definition: ydef.h:560
u16 ySeekFifo(yFifoBuf *buf, const u8 *pattern, u16 patlen, u16 startofs, u16 searchlen, u8 bTextCompare)
Definition: yfifo.c:367
u16 yPopFifo(yFifoBuf *buf, u8 *data, u16 datalen)
Definition: yfifo.c:187
u16 datasize
Definition: yfifo.h:61


yoctopuce_altimeter
Author(s): Anja Sheppard
autogenerated on Mon Jun 10 2019 15:49:10