xref: /btstack/port/stm32-wb55xx-nucleo-freertos/Middlewares/STM32_WPAN/utilities/stm_queue.c (revision 0561b2d8d5dba972c7daa57d5e677f7a1327edfd)
1*0561b2d8STREFOU Felix /**
2*0561b2d8STREFOU Felix   ******************************************************************************
3*0561b2d8STREFOU Felix   * @file    stm_queue.c
4*0561b2d8STREFOU Felix   * @author  MCD Application Team
5*0561b2d8STREFOU Felix   * @brief   Queue management
6*0561b2d8STREFOU Felix   ******************************************************************************
7*0561b2d8STREFOU Felix    * @attention
8*0561b2d8STREFOU Felix   *
9*0561b2d8STREFOU Felix   * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
10*0561b2d8STREFOU Felix   * All rights reserved.</center></h2>
11*0561b2d8STREFOU Felix   *
12*0561b2d8STREFOU Felix   * This software component is licensed by ST under BSD 3-Clause license,
13*0561b2d8STREFOU Felix   * the "License"; You may not use this file except in compliance with the
14*0561b2d8STREFOU Felix   * License. You may obtain a copy of the License at:
15*0561b2d8STREFOU Felix   *                        opensource.org/licenses/BSD-3-Clause
16*0561b2d8STREFOU Felix   *
17*0561b2d8STREFOU Felix   ******************************************************************************
18*0561b2d8STREFOU Felix  */
19*0561b2d8STREFOU Felix 
20*0561b2d8STREFOU Felix /* Includes ------------------------------------------------------------------*/
21*0561b2d8STREFOU Felix 
22*0561b2d8STREFOU Felix /* Includes ------------------------------------------------------------------*/
23*0561b2d8STREFOU Felix #include "utilities_common.h"
24*0561b2d8STREFOU Felix 
25*0561b2d8STREFOU Felix #include "stm_queue.h"
26*0561b2d8STREFOU Felix 
27*0561b2d8STREFOU Felix /* Private define ------------------------------------------------------------*/
28*0561b2d8STREFOU Felix /* Private typedef -------------------------------------------------------------*/
29*0561b2d8STREFOU Felix /* Private macro -------------------------------------------------------------*/
30*0561b2d8STREFOU Felix #define MOD(X,Y) (((X) >= (Y)) ? ((X)-(Y)) : (X))
31*0561b2d8STREFOU Felix 
32*0561b2d8STREFOU Felix /* Private variables ---------------------------------------------------------*/
33*0561b2d8STREFOU Felix /* Global variables ----------------------------------------------------------*/
34*0561b2d8STREFOU Felix /* Extern variables ----------------------------------------------------------*/
35*0561b2d8STREFOU Felix /* Private function prototypes -----------------------------------------------*/
36*0561b2d8STREFOU Felix /* Private functions ---------------------------------------------------------*/
37*0561b2d8STREFOU Felix /* Public functions ----------------------------------------------------------*/
38*0561b2d8STREFOU Felix 
39*0561b2d8STREFOU Felix /**
40*0561b2d8STREFOU Felix   * @brief   Initilaiilze queue strcuture .
41*0561b2d8STREFOU Felix   * @note   This function is used to initialize the global queue strcuture.
42*0561b2d8STREFOU Felix   * @param  q: pointer on queue strcture to be initialised
43*0561b2d8STREFOU Felix   * @param  queueBuffer: pointer on Queue Buffer
44*0561b2d8STREFOU Felix   * @param  queueSize:  Size of Queue Buffer
45*0561b2d8STREFOU Felix   * @param  elementSize: Size of an element in the queue. if =0, the queue will manage variable sizze elements
46*0561b2d8STREFOU Felix   * @retval   always 0
47*0561b2d8STREFOU Felix   */
CircularQueue_Init(queue_t * q,uint8_t * queueBuffer,uint32_t queueSize,uint16_t elementSize,uint8_t optionFlags)48*0561b2d8STREFOU Felix int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionFlags)
49*0561b2d8STREFOU Felix {
50*0561b2d8STREFOU Felix   q->qBuff = queueBuffer;
51*0561b2d8STREFOU Felix   q->first = 0;
52*0561b2d8STREFOU Felix   q->last = 0; /* queueSize-1; */
53*0561b2d8STREFOU Felix   q->byteCount = 0;
54*0561b2d8STREFOU Felix   q->elementCount = 0;
55*0561b2d8STREFOU Felix   q->queueMaxSize = queueSize;
56*0561b2d8STREFOU Felix   q->elementSize = elementSize;
57*0561b2d8STREFOU Felix   q->optionFlags = optionFlags;
58*0561b2d8STREFOU Felix 
59*0561b2d8STREFOU Felix    if ((optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG) && q-> elementSize)
60*0561b2d8STREFOU Felix    {
61*0561b2d8STREFOU Felix     /* can not deal with splitting at the end of buffer with fixed size element */
62*0561b2d8STREFOU Felix     return -1;
63*0561b2d8STREFOU Felix   }
64*0561b2d8STREFOU Felix   return 0;
65*0561b2d8STREFOU Felix }
66*0561b2d8STREFOU Felix 
67*0561b2d8STREFOU Felix /**
68*0561b2d8STREFOU Felix   * @brief   Add  element to the queue .
69*0561b2d8STREFOU Felix   * @note   This function is used to add one or more  element(s) to the Circular Queue .
70*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure   to be handled
71*0561b2d8STREFOU Felix   * @param  X; pointer on element(s) to be added
72*0561b2d8STREFOU Felix   * @param  elementSize:  Size of element to be added to the queue. Only used if the queue manage variable size elements
73*0561b2d8STREFOU Felix   * @param  nbElements:  number of elements in the in buffer pointed by x
74*0561b2d8STREFOU Felix   * @retval  pointer on last element just added to the queue, NULL if the element to be added do not fit in the queue (too big)
75*0561b2d8STREFOU Felix   */
CircularQueue_Add(queue_t * q,uint8_t * x,uint16_t elementSize,uint32_t nbElements)76*0561b2d8STREFOU Felix uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements)
77*0561b2d8STREFOU Felix {
78*0561b2d8STREFOU Felix 
79*0561b2d8STREFOU Felix   uint8_t* ptr = NULL;                      /* fct return ptr to the element freshly added, if no room fct return NULL */
80*0561b2d8STREFOU Felix   uint16_t curElementSize = 0;              /* the size of the element currently  stored at q->last position */
81*0561b2d8STREFOU Felix   uint8_t  elemSizeStorageRoom  = 0 ;       /* Indicate the header (which contain only size) of element in case of varaibale size elemenet (q->elementsize == 0) */
82*0561b2d8STREFOU Felix   uint32_t curBuffPosition;                  /* the current position in the queue buffer */
83*0561b2d8STREFOU Felix   uint32_t i;                               /* loop counter */
84*0561b2d8STREFOU Felix   uint32_t NbBytesToCopy = 0, NbCopiedBytes = 0 ; /* Indicators for copying bytes in queue */
85*0561b2d8STREFOU Felix   uint32_t eob_free_size;                         /* Eof End of Quque Buffer Free Size */
86*0561b2d8STREFOU Felix   uint8_t  wrap_will_occur = 0;                   /* indicate if a wrap around will occurs */
87*0561b2d8STREFOU Felix   uint8_t  wrapped_element_eob_size;              /* In case of Wrap around, indicat size of parta of elemenet that fit at thened of the queuue  buffer */
88*0561b2d8STREFOU Felix   uint16_t overhead = 0;                          /* In case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG or CIRCULAR_QUEUE_NO_WRAP_FLAG options,
89*0561b2d8STREFOU Felix                                                      indcate the size overhead that will be generated by adding the element with wrap management (split or no wrap ) */
90*0561b2d8STREFOU Felix 
91*0561b2d8STREFOU Felix 
92*0561b2d8STREFOU Felix   elemSizeStorageRoom  = (q->elementSize == 0) ? 2 : 0;
93*0561b2d8STREFOU Felix   /* retrieve the size of last element sored: the value stored at the beginning of the queue element if element size is variable otherwise take it from fixed element Size member */
94*0561b2d8STREFOU Felix   if (q->byteCount)
95*0561b2d8STREFOU Felix   {
96*0561b2d8STREFOU Felix     curElementSize = (q->elementSize == 0) ? q->qBuff[q->last] + ((q->qBuff[MOD((q->last+1), q->queueMaxSize)])<<8) + 2 : q->elementSize;
97*0561b2d8STREFOU Felix   }
98*0561b2d8STREFOU Felix   /* if queue element have fixed size , reset the elementSize arg with fixed element size value */
99*0561b2d8STREFOU Felix   if (q->elementSize > 0)
100*0561b2d8STREFOU Felix   {
101*0561b2d8STREFOU Felix     elementSize = q->elementSize;
102*0561b2d8STREFOU Felix   }
103*0561b2d8STREFOU Felix 
104*0561b2d8STREFOU Felix    eob_free_size = (q->last >= q->first) ? q->queueMaxSize - (q->last + curElementSize) : 0;
105*0561b2d8STREFOU Felix 
106*0561b2d8STREFOU Felix    /* check how many bytes of wrapped element (if anay) are at end of buffer */
107*0561b2d8STREFOU Felix    wrapped_element_eob_size = (((elementSize + elemSizeStorageRoom )*nbElements) < eob_free_size) ? 0 : (eob_free_size % (elementSize + elemSizeStorageRoom));
108*0561b2d8STREFOU Felix    wrap_will_occur  = wrapped_element_eob_size > elemSizeStorageRoom;
109*0561b2d8STREFOU Felix 
110*0561b2d8STREFOU Felix    overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)) ? wrapped_element_eob_size : overhead;
111*0561b2d8STREFOU Felix    overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)) ? elemSizeStorageRoom  : overhead;
112*0561b2d8STREFOU Felix 
113*0561b2d8STREFOU Felix 
114*0561b2d8STREFOU Felix   /* Store now the elements if ennough room for all elements */
115*0561b2d8STREFOU Felix   if (elementSize && ((q->byteCount + ((elementSize + elemSizeStorageRoom )*nbElements) + overhead) <= q->queueMaxSize))
116*0561b2d8STREFOU Felix   {
117*0561b2d8STREFOU Felix     /* loop to add all elements  */
118*0561b2d8STREFOU Felix     for (i=0; i < nbElements; i++)
119*0561b2d8STREFOU Felix     {
120*0561b2d8STREFOU Felix       q->last = MOD ((q->last + curElementSize),q->queueMaxSize);
121*0561b2d8STREFOU Felix       curBuffPosition = q->last;
122*0561b2d8STREFOU Felix 
123*0561b2d8STREFOU Felix       /* store the element  */
124*0561b2d8STREFOU Felix       /* store fisrt the element size if element size is varaible */
125*0561b2d8STREFOU Felix       if (q->elementSize == 0)
126*0561b2d8STREFOU Felix       {
127*0561b2d8STREFOU Felix         q->qBuff[curBuffPosition++]= elementSize & 0xFF;
128*0561b2d8STREFOU Felix         curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
129*0561b2d8STREFOU Felix         q->qBuff[curBuffPosition++]= (elementSize & 0xFF00) >> 8 ;
130*0561b2d8STREFOU Felix         curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
131*0561b2d8STREFOU Felix         q->byteCount += 2;
132*0561b2d8STREFOU Felix       }
133*0561b2d8STREFOU Felix 
134*0561b2d8STREFOU Felix       /* Identify number of bytes of copy takeing account possible wrap, in this case NbBytesToCopy will contains size that fit at end of the queue buffer */
135*0561b2d8STREFOU Felix       NbBytesToCopy = MIN((q->queueMaxSize-curBuffPosition),elementSize);
136*0561b2d8STREFOU Felix       /* check if no wrap (NbBytesToCopy == elementSize) or if Wrap and no spsicf option;
137*0561b2d8STREFOU Felix          In thi case part of data will copied at the end of the buffer and the rest a the beggining */
138*0561b2d8STREFOU Felix       if ((NbBytesToCopy == elementSize) || ((NbBytesToCopy < elementSize) && (q->optionFlags == CIRCULAR_QUEUE_NO_FLAG)))
139*0561b2d8STREFOU Felix       {
140*0561b2d8STREFOU Felix         /* Copy First part (or emtire buffer ) from current position up to the end of the buffer queue (or before if enough room)  */
141*0561b2d8STREFOU Felix         memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
142*0561b2d8STREFOU Felix         /* Adjust bytes count */
143*0561b2d8STREFOU Felix         q->byteCount += NbBytesToCopy;
144*0561b2d8STREFOU Felix         /* Wrap */
145*0561b2d8STREFOU Felix         curBuffPosition = 0;
146*0561b2d8STREFOU Felix         /* set NbCopiedBytes bytes with  ampount copied */
147*0561b2d8STREFOU Felix         NbCopiedBytes = NbBytesToCopy;
148*0561b2d8STREFOU Felix         /* set the rest to copy if wrao , if no wrap will be 0 */
149*0561b2d8STREFOU Felix         NbBytesToCopy = elementSize - NbBytesToCopy;
150*0561b2d8STREFOU Felix         /* set the current element Size, will be used to calaculate next last position at beggining of loop */
151*0561b2d8STREFOU Felix         curElementSize = (elementSize) + elemSizeStorageRoom ;
152*0561b2d8STREFOU Felix       }
153*0561b2d8STREFOU Felix       else if (NbBytesToCopy)  /* We have a wrap  to manage */
154*0561b2d8STREFOU Felix       {
155*0561b2d8STREFOU Felix        /* case of CIRCULAR_QUEUE_NO_WRAP_FLAG option */
156*0561b2d8STREFOU Felix          if (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)
157*0561b2d8STREFOU Felix         {
158*0561b2d8STREFOU Felix           /* if element size are variable and NO_WRAP option, Invalidate end of buffer setting 0xFFFF size*/
159*0561b2d8STREFOU Felix           if (q->elementSize == 0)
160*0561b2d8STREFOU Felix           {
161*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition-2] = 0xFF;
162*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition-1] = 0xFF;
163*0561b2d8STREFOU Felix           }
164*0561b2d8STREFOU Felix           q->byteCount += NbBytesToCopy;  /* invalid data at the end of buffer are take into account in byteCount */
165*0561b2d8STREFOU Felix           /* No bytes coped a the end of buffer */
166*0561b2d8STREFOU Felix           NbCopiedBytes = 0;
167*0561b2d8STREFOU Felix           /* all element to be copied at the begnning of buffer */
168*0561b2d8STREFOU Felix           NbBytesToCopy = elementSize;
169*0561b2d8STREFOU Felix           /* Wrap */
170*0561b2d8STREFOU Felix           curBuffPosition = 0;
171*0561b2d8STREFOU Felix           /* if variable size element, invalidate end of buffer setting OxFFFF in element header (size) */
172*0561b2d8STREFOU Felix           if (q->elementSize == 0)
173*0561b2d8STREFOU Felix           {
174*0561b2d8STREFOU Felix             q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
175*0561b2d8STREFOU Felix             q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
176*0561b2d8STREFOU Felix             q->byteCount += 2;
177*0561b2d8STREFOU Felix           }
178*0561b2d8STREFOU Felix 
179*0561b2d8STREFOU Felix         }
180*0561b2d8STREFOU Felix         /* case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG option */
181*0561b2d8STREFOU Felix         else if (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)
182*0561b2d8STREFOU Felix         {
183*0561b2d8STREFOU Felix           if (q->elementSize == 0)
184*0561b2d8STREFOU Felix           {
185*0561b2d8STREFOU Felix             /* reset the size of current element to the nb bytes fitting at the end of buffer */
186*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition-2] = NbBytesToCopy & 0xFF;
187*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition-1] = (NbBytesToCopy & 0xFF00) >> 8 ;
188*0561b2d8STREFOU Felix              /* copy the bytes */
189*0561b2d8STREFOU Felix              memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
190*0561b2d8STREFOU Felix              q->byteCount += NbBytesToCopy;
191*0561b2d8STREFOU Felix              /* set the number of copied bytes */
192*0561b2d8STREFOU Felix              NbCopiedBytes = NbBytesToCopy;
193*0561b2d8STREFOU Felix              /* set rest of data to be copied to begnning of buffer */
194*0561b2d8STREFOU Felix              NbBytesToCopy = elementSize - NbBytesToCopy;
195*0561b2d8STREFOU Felix              /* one element more dur to split in 2 elements */
196*0561b2d8STREFOU Felix              q->elementCount++;
197*0561b2d8STREFOU Felix              /* Wrap */
198*0561b2d8STREFOU Felix              curBuffPosition = 0;
199*0561b2d8STREFOU Felix              /* Set new size for rest of data */
200*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
201*0561b2d8STREFOU Felix              q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
202*0561b2d8STREFOU Felix              q->byteCount += 2;
203*0561b2d8STREFOU Felix           }
204*0561b2d8STREFOU Felix           else
205*0561b2d8STREFOU Felix           {
206*0561b2d8STREFOU Felix             /* Should not occur */
207*0561b2d8STREFOU Felix             /* can not manage split Flag on Fixed size element */
208*0561b2d8STREFOU Felix             /* Buffer is corrupted */
209*0561b2d8STREFOU Felix             return NULL;
210*0561b2d8STREFOU Felix           }
211*0561b2d8STREFOU Felix         }
212*0561b2d8STREFOU Felix         curElementSize = (NbBytesToCopy) + elemSizeStorageRoom ;
213*0561b2d8STREFOU Felix         q->last = 0;
214*0561b2d8STREFOU Felix       }
215*0561b2d8STREFOU Felix 
216*0561b2d8STREFOU Felix       /* some remaning byte to copy */
217*0561b2d8STREFOU Felix       if (NbBytesToCopy)
218*0561b2d8STREFOU Felix       {
219*0561b2d8STREFOU Felix         memcpy(&q->qBuff[curBuffPosition],&x[(i*elementSize)+NbCopiedBytes],NbBytesToCopy);
220*0561b2d8STREFOU Felix         q->byteCount += NbBytesToCopy;
221*0561b2d8STREFOU Felix       }
222*0561b2d8STREFOU Felix 
223*0561b2d8STREFOU Felix       /* One more element */
224*0561b2d8STREFOU Felix       q->elementCount++;
225*0561b2d8STREFOU Felix     }
226*0561b2d8STREFOU Felix 
227*0561b2d8STREFOU Felix     ptr = q->qBuff + (MOD((q->last+elemSizeStorageRoom ),q->queueMaxSize));
228*0561b2d8STREFOU Felix   }
229*0561b2d8STREFOU Felix   /* for Breakpoint only...to remove */
230*0561b2d8STREFOU Felix   else
231*0561b2d8STREFOU Felix   {
232*0561b2d8STREFOU Felix     return NULL;
233*0561b2d8STREFOU Felix   }
234*0561b2d8STREFOU Felix   return ptr;
235*0561b2d8STREFOU Felix }
236*0561b2d8STREFOU Felix 
237*0561b2d8STREFOU Felix 
238*0561b2d8STREFOU Felix /**
239*0561b2d8STREFOU Felix   * @brief  Remove element from  the queue and copy it in provided buffer
240*0561b2d8STREFOU Felix   * @note   This function is used to remove and element from  the Circular Queue .
241*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure  to be handled
242*0561b2d8STREFOU Felix   * @param  elementSize: Pointer to return Size of element to be removed
243*0561b2d8STREFOU Felix   * @param  buffer: destination buffer where to copy element
244*0561b2d8STREFOU Felix   * @retval Pointer on removed element. NULL if queue was empty
245*0561b2d8STREFOU Felix   */
CircularQueue_Remove_Copy(queue_t * q,uint16_t * elementSize,uint8_t * buffer)246*0561b2d8STREFOU Felix uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
247*0561b2d8STREFOU Felix {
248*0561b2d8STREFOU Felix    return NULL;
249*0561b2d8STREFOU Felix }
250*0561b2d8STREFOU Felix 
251*0561b2d8STREFOU Felix 
252*0561b2d8STREFOU Felix 
253*0561b2d8STREFOU Felix /**
254*0561b2d8STREFOU Felix   * @brief  Remove element from  the queue.
255*0561b2d8STREFOU Felix   * @note   This function is used to remove and element from  the Circular Queue .
256*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure  to be handled
257*0561b2d8STREFOU Felix   * @param  elementSize: Pointer to return Size of element to be removed
258*0561b2d8STREFOU Felix   * @retval Pointer on removed element. NULL if queue was empty
259*0561b2d8STREFOU Felix   */
CircularQueue_Remove(queue_t * q,uint16_t * elementSize)260*0561b2d8STREFOU Felix uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize)
261*0561b2d8STREFOU Felix {
262*0561b2d8STREFOU Felix   uint8_t  elemSizeStorageRoom = 0;
263*0561b2d8STREFOU Felix   uint8_t* ptr= NULL;
264*0561b2d8STREFOU Felix   elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
265*0561b2d8STREFOU Felix   *elementSize = 0;
266*0561b2d8STREFOU Felix   if (q->byteCount > 0)
267*0561b2d8STREFOU Felix   {
268*0561b2d8STREFOU Felix     /* retreive element Size */
269*0561b2d8STREFOU Felix     *elementSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
270*0561b2d8STREFOU Felix 
271*0561b2d8STREFOU Felix      if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
272*0561b2d8STREFOU Felix      {
273*0561b2d8STREFOU Felix        if (((*elementSize == 0xFFFF) && q->elementSize == 0 ) ||
274*0561b2d8STREFOU Felix            ((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
275*0561b2d8STREFOU Felix        {
276*0561b2d8STREFOU Felix           /* all data from current position up to the end of buffer are invalid */
277*0561b2d8STREFOU Felix           q->byteCount -= (q->queueMaxSize - q->first);
278*0561b2d8STREFOU Felix           /* Adjust first element pos */
279*0561b2d8STREFOU Felix           q->first = 0;
280*0561b2d8STREFOU Felix           /* retrieve the rigth size after the wrap [if varaible size element] */
281*0561b2d8STREFOU Felix           *elementSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
282*0561b2d8STREFOU Felix        }
283*0561b2d8STREFOU Felix      }
284*0561b2d8STREFOU Felix 
285*0561b2d8STREFOU Felix     /* retreive element */
286*0561b2d8STREFOU Felix     ptr = q->qBuff + (MOD((q->first + elemSizeStorageRoom), q->queueMaxSize));
287*0561b2d8STREFOU Felix 
288*0561b2d8STREFOU Felix     /* adjust byte count */
289*0561b2d8STREFOU Felix     q->byteCount -= (*elementSize + elemSizeStorageRoom) ;
290*0561b2d8STREFOU Felix 
291*0561b2d8STREFOU Felix     /* Adjust q->first */
292*0561b2d8STREFOU Felix     if (q->byteCount > 0)
293*0561b2d8STREFOU Felix     {
294*0561b2d8STREFOU Felix       q->first = MOD((q->first+ *elementSize + elemSizeStorageRoom ), q->queueMaxSize);
295*0561b2d8STREFOU Felix     }
296*0561b2d8STREFOU Felix     /* adjust element count */
297*0561b2d8STREFOU Felix     --q->elementCount;
298*0561b2d8STREFOU Felix   }
299*0561b2d8STREFOU Felix   return ptr;
300*0561b2d8STREFOU Felix }
301*0561b2d8STREFOU Felix 
302*0561b2d8STREFOU Felix 
303*0561b2d8STREFOU Felix /**
304*0561b2d8STREFOU Felix   * @brief  "Sense" first element of the queue, without removing it and copy it in provided buffer
305*0561b2d8STREFOU Felix   * @note   This function is used to return a pointer on the first element of the queue without removing it.
306*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure  to be handled
307*0561b2d8STREFOU Felix   * @param  elementSize:  Pointer to return Size of element to be removed
308*0561b2d8STREFOU Felix   * @param  buffer: destination buffer where to copy element
309*0561b2d8STREFOU Felix   * @retval Pointer on sensed element. NULL if queue was empty
310*0561b2d8STREFOU Felix   */
311*0561b2d8STREFOU Felix 
CircularQueue_Sense_Copy(queue_t * q,uint16_t * elementSize,uint8_t * buffer)312*0561b2d8STREFOU Felix uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
313*0561b2d8STREFOU Felix {
314*0561b2d8STREFOU Felix     return NULL;
315*0561b2d8STREFOU Felix }
316*0561b2d8STREFOU Felix 
317*0561b2d8STREFOU Felix 
318*0561b2d8STREFOU Felix /**
319*0561b2d8STREFOU Felix   * @brief  "Sense" first element of the queue, without removing it.
320*0561b2d8STREFOU Felix   * @note   This function is used to return a pointer on the first element of the queue without removing it.
321*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure  to be handled
322*0561b2d8STREFOU Felix   * @param  elementSize:  Pointer to return Size of element to be removed
323*0561b2d8STREFOU Felix   * @retval Pointer on sensed element. NULL if queue was empty
324*0561b2d8STREFOU Felix   */
CircularQueue_Sense(queue_t * q,uint16_t * elementSize)325*0561b2d8STREFOU Felix uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize)
326*0561b2d8STREFOU Felix {
327*0561b2d8STREFOU Felix   uint8_t  elemSizeStorageRoom = 0;
328*0561b2d8STREFOU Felix   uint8_t* x= NULL;
329*0561b2d8STREFOU Felix   elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
330*0561b2d8STREFOU Felix   *elementSize = 0;
331*0561b2d8STREFOU Felix   uint32_t FirstElemetPos = 0;
332*0561b2d8STREFOU Felix 
333*0561b2d8STREFOU Felix   if (q->byteCount > 0)
334*0561b2d8STREFOU Felix   {
335*0561b2d8STREFOU Felix     FirstElemetPos = q->first;
336*0561b2d8STREFOU Felix     *elementSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
337*0561b2d8STREFOU Felix 
338*0561b2d8STREFOU Felix     if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
339*0561b2d8STREFOU Felix     {
340*0561b2d8STREFOU Felix       if (((*elementSize == 0xFFFF) && q->elementSize == 0 ) ||
341*0561b2d8STREFOU Felix           ((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
342*0561b2d8STREFOU Felix 
343*0561b2d8STREFOU Felix       {
344*0561b2d8STREFOU Felix         /* all data from current position up to the end of buffer are invalid */
345*0561b2d8STREFOU Felix         FirstElemetPos = 0; /* wrap to the begiining of buffer */
346*0561b2d8STREFOU Felix 
347*0561b2d8STREFOU Felix         /* retrieve the rigth size after the wrap [if varaible size element] */
348*0561b2d8STREFOU Felix         *elementSize = (q->elementSize == 0) ? q->qBuff[FirstElemetPos]+ ((q->qBuff[MOD((FirstElemetPos+1), q->queueMaxSize)])<<8) : q->elementSize;
349*0561b2d8STREFOU Felix       }
350*0561b2d8STREFOU Felix    }
351*0561b2d8STREFOU Felix    /* retrieve element */
352*0561b2d8STREFOU Felix     x = q->qBuff + (MOD((FirstElemetPos + elemSizeStorageRoom), q->queueMaxSize));
353*0561b2d8STREFOU Felix   }
354*0561b2d8STREFOU Felix   return x;
355*0561b2d8STREFOU Felix }
356*0561b2d8STREFOU Felix 
357*0561b2d8STREFOU Felix /**
358*0561b2d8STREFOU Felix   * @brief   Check if queue is empty.
359*0561b2d8STREFOU Felix   * @note    This function is used to to check if the queue is empty.
360*0561b2d8STREFOU Felix   * @param  q: pointer on queue structure  to be handled
361*0561b2d8STREFOU Felix   * @retval   TRUE (!0) if the queue is empyu otherwise FALSE (0)
362*0561b2d8STREFOU Felix   */
CircularQueue_Empty(queue_t * q)363*0561b2d8STREFOU Felix int CircularQueue_Empty(queue_t *q)
364*0561b2d8STREFOU Felix {
365*0561b2d8STREFOU Felix   int ret=FALSE;
366*0561b2d8STREFOU Felix   if (q->byteCount <= 0)
367*0561b2d8STREFOU Felix   {
368*0561b2d8STREFOU Felix     ret=TRUE;
369*0561b2d8STREFOU Felix   }
370*0561b2d8STREFOU Felix   return ret;
371*0561b2d8STREFOU Felix }
372*0561b2d8STREFOU Felix 
CircularQueue_NbElement(queue_t * q)373*0561b2d8STREFOU Felix int CircularQueue_NbElement(queue_t *q)
374*0561b2d8STREFOU Felix {
375*0561b2d8STREFOU Felix   return q->elementCount;
376*0561b2d8STREFOU Felix }
377