LPCOpen Platform for LPC112X microcontrollers  112X
LPCOpen Platform for the NXP LPC112X family of Microcontrollers
ring_buffer.c
Go to the documentation of this file.
1 /*
2  * @brief Common ring buffer support functions
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include <string.h>
33 #include "ring_buffer.h"
34 
35 /*****************************************************************************
36  * Private types/enumerations/variables
37  ****************************************************************************/
38 
39 #define RB_INDH(rb) ((rb)->head & ((rb)->count - 1))
40 #define RB_INDT(rb) ((rb)->tail & ((rb)->count - 1))
41 
42 /*****************************************************************************
43  * Public types/enumerations/variables
44  ****************************************************************************/
45 
46 /*****************************************************************************
47  * Private functions
48  ****************************************************************************/
49 
50 /*****************************************************************************
51  * Public functions
52  ****************************************************************************/
53 
54 /* Initialize ring buffer */
55 int RingBuffer_Init(RINGBUFF_T *RingBuff, void *buffer, int itemSize, int count)
56 {
57  RingBuff->data = buffer;
58  RingBuff->count = count;
59  RingBuff->itemSz = itemSize;
60  RingBuff->head = RingBuff->tail = 0;
61 
62  return 1;
63 }
64 
65 /* Insert a single item into Ring Buffer */
66 int RingBuffer_Insert(RINGBUFF_T *RingBuff, const void *data)
67 {
68  uint8_t *ptr = RingBuff->data;
69 
70  /* We cannot insert when queue is full */
71  if (RingBuffer_IsFull(RingBuff))
72  return 0;
73 
74  ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
75  memcpy(ptr, data, RingBuff->itemSz);
76  RingBuff->head++;
77 
78  return 1;
79 }
80 
81 /* Insert multiple items into Ring Buffer */
82 int RingBuffer_InsertMult(RINGBUFF_T *RingBuff, const void *data, int num)
83 {
84  uint8_t *ptr = RingBuff->data;
85  int cnt1, cnt2;
86 
87  /* We cannot insert when queue is full */
88  if (RingBuffer_IsFull(RingBuff))
89  return 0;
90 
91  /* Calculate the segment lengths */
92  cnt1 = cnt2 = RingBuffer_GetFree(RingBuff);
93  if (RB_INDH(RingBuff) + cnt1 >= RingBuff->count)
94  cnt1 = RingBuff->count - RB_INDH(RingBuff);
95  cnt2 -= cnt1;
96 
97  cnt1 = MIN(cnt1, num);
98  num -= cnt1;
99 
100  cnt2 = MIN(cnt2, num);
101  num -= cnt2;
102 
103  /* Write segment 1 */
104  ptr += RB_INDH(RingBuff) * RingBuff->itemSz;
105  memcpy(ptr, data, cnt1 * RingBuff->itemSz);
106  RingBuff->head += cnt1;
107 
108  /* Write segment 2 */
109  ptr = (uint8_t *) RingBuff->data + RB_INDH(RingBuff) * RingBuff->itemSz;
110  data = (const uint8_t *) data + cnt1 * RingBuff->itemSz;
111  memcpy(ptr, data, cnt2 * RingBuff->itemSz);
112  RingBuff->head += cnt2;
113 
114  return cnt1 + cnt2;
115 }
116 
117 /* Pop single item from Ring Buffer */
118 int RingBuffer_Pop(RINGBUFF_T *RingBuff, void *data)
119 {
120  uint8_t *ptr = RingBuff->data;
121 
122  /* We cannot pop when queue is empty */
123  if (RingBuffer_IsEmpty(RingBuff))
124  return 0;
125 
126  ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
127  memcpy(data, ptr, RingBuff->itemSz);
128  RingBuff->tail++;
129 
130  return 1;
131 }
132 
133 /* Pop multiple items from Ring buffer */
134 int RingBuffer_PopMult(RINGBUFF_T *RingBuff, void *data, int num)
135 {
136  uint8_t *ptr = RingBuff->data;
137  int cnt1, cnt2;
138 
139  /* We cannot insert when queue is empty */
140  if (RingBuffer_IsEmpty(RingBuff))
141  return 0;
142 
143  /* Calculate the segment lengths */
144  cnt1 = cnt2 = RingBuffer_GetCount(RingBuff);
145  if (RB_INDT(RingBuff) + cnt1 >= RingBuff->count)
146  cnt1 = RingBuff->count - RB_INDT(RingBuff);
147  cnt2 -= cnt1;
148 
149  cnt1 = MIN(cnt1, num);
150  num -= cnt1;
151 
152  cnt2 = MIN(cnt2, num);
153  num -= cnt2;
154 
155  /* Write segment 1 */
156  ptr += RB_INDT(RingBuff) * RingBuff->itemSz;
157  memcpy(data, ptr, cnt1 * RingBuff->itemSz);
158  RingBuff->tail += cnt1;
159 
160  /* Write segment 2 */
161  ptr = (uint8_t *) RingBuff->data + RB_INDT(RingBuff) * RingBuff->itemSz;
162  data = (uint8_t *) data + cnt1 * RingBuff->itemSz;
163  memcpy(data, ptr, cnt2 * RingBuff->itemSz);
164  RingBuff->tail += cnt2;
165 
166  return cnt1 + cnt2;
167 }