1/* Copyright (c) 2014, Nordic Semiconductor ASA
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in all
11 * copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 * SOFTWARE.
20 */
21
22 /** @file
23@brief Implementation of a circular queue for ACI data
24*/
25
26#include "hal_aci_tl.h"
27#include "aci_queue.h"
28
29void aci_queue_init(aci_queue_t *aci_q)
30{
31  uint8_t loop;
32
33  // ble_assert(NULL != aci_q);
34
35  aci_q->head = 0;
36  aci_q->tail = 0;
37  for(loop=0; loop<ACI_QUEUE_SIZE; loop++)
38  {
39    aci_q->aci_data[loop].buffer[0] = 0x00;
40    aci_q->aci_data[loop].buffer[1] = 0x00;
41  }
42}
43
44bool aci_queue_dequeue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
45{
46  // ble_assert(NULL != aci_q);
47  // ble_assert(NULL != p_data);
48
49  if (aci_queue_is_empty(aci_q))
50  {
51    return false;
52  }
53
54  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
55  aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE;
56
57  return true;
58}
59
60bool aci_queue_dequeue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data)
61{
62  // ble_assert(NULL != aci_q);
63  // ble_assert(NULL != p_data);
64
65  if (aci_queue_is_empty_from_isr(aci_q))
66  {
67    return false;
68  }
69
70  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
71  aci_q->head = (aci_q->head + 1) % ACI_QUEUE_SIZE;
72
73  return true;
74}
75
76bool aci_queue_enqueue(aci_queue_t *aci_q, hal_aci_data_t *p_data)
77{
78  const uint8_t length = p_data->buffer[0];
79
80  // ble_assert(NULL != aci_q);
81  // ble_assert(NULL != p_data);
82
83  if (aci_queue_is_full(aci_q))
84  {
85    return false;
86  }
87
88  aci_q->aci_data[aci_q->tail].status_byte = 0;
89  memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1);
90  aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
91
92  return true;
93}
94
95bool aci_queue_enqueue_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data)
96{
97  const uint8_t length = p_data->buffer[0];
98
99  // ble_assert(NULL != aci_q);
100  // ble_assert(NULL != p_data);
101
102  if (aci_queue_is_full_from_isr(aci_q))
103  {
104    return false;
105  }
106
107  aci_q->aci_data[aci_q->tail].status_byte = 0;
108  memcpy((uint8_t *)&(aci_q->aci_data[aci_q->tail].buffer[0]), (uint8_t *)&p_data->buffer[0], length + 1);
109  aci_q->tail = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
110
111  return true;
112}
113
114bool aci_queue_is_empty(aci_queue_t *aci_q)
115{
116  bool state = false;
117
118  // ble_assert(NULL != aci_q);
119
120  //Critical section
121  // noInterrupts();
122  if (aci_q->head == aci_q->tail)
123  {
124    state = true;
125  }
126  // interrupts();
127
128  return state;
129}
130
131bool aci_queue_is_empty_from_isr(aci_queue_t *aci_q)
132{
133  // ble_assert(NULL != aci_q);
134
135  return aci_q->head == aci_q->tail;
136}
137
138bool aci_queue_is_full(aci_queue_t *aci_q)
139{
140  uint8_t next;
141  bool state;
142
143  // ble_assert(NULL != aci_q);
144
145  //This should be done in a critical section
146  // noInterrupts();
147  next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
148
149  if (next == aci_q->head)
150  {
151    state = true;
152  }
153  else
154  {
155    state = false;
156  }
157
158  // interrupts();
159  //end
160
161  return state;
162}
163
164bool aci_queue_is_full_from_isr(aci_queue_t *aci_q)
165{
166  const uint8_t next = (aci_q->tail + 1) % ACI_QUEUE_SIZE;
167
168  // ble_assert(NULL != aci_q);
169
170  return next == aci_q->head;
171}
172
173bool aci_queue_peek(aci_queue_t *aci_q, hal_aci_data_t *p_data)
174{
175  // ble_assert(NULL != aci_q);
176  // ble_assert(NULL != p_data);
177
178  if (aci_queue_is_empty(aci_q))
179  {
180    return false;
181  }
182
183  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
184
185  return true;
186}
187
188bool aci_queue_peek_from_isr(aci_queue_t *aci_q, hal_aci_data_t *p_data)
189{
190  // ble_assert(NULL != aci_q);
191  // ble_assert(NULL != p_data);
192
193  if (aci_queue_is_empty_from_isr(aci_q))
194  {
195    return false;
196  }
197
198  memcpy((uint8_t *)p_data, (uint8_t *)&(aci_q->aci_data[aci_q->head]), sizeof(hal_aci_data_t));
199
200  return true;
201}
202