firmware  v0.1.2
Chromation Spectrometer Dev-Kit
Queue.h
1 #ifndef _QUEUE_H
2 #define _QUEUE_H
3 #include <stdint.h> // uint8_t
4 #include <stdbool.h> // bool, true, false
5 typedef struct Queue_s Queue_s;
6 // Define a Queue struct for accessing the SPI FIFO Rx Buffer.
8 
27 struct Queue_s {
33  volatile uint8_t * buffer;
37  volatile uint8_t head; // index buffer at head for Push
41  volatile uint8_t tail;
43  volatile uint8_t length;
47  volatile uint8_t max_length;
48 };
49 extern volatile Queue_s Queue;
50 // ---API---
51 inline volatile Queue_s * QueueInit(
52  volatile uint8_t * buffer,
53  uint16_t const buffer_size_in_bytes
54  )
55 {
63  // Create a pointer to the global Queue.
64  volatile Queue_s * pq = &Queue;
65  // Assign Queue to access the array
66  pq->buffer = buffer;
67  // Store array size (this is the maximum length of the Queue)
68  pq->max_length = buffer_size_in_bytes;
69  // Empty the Rx Buffer: by setting head/tail index to first byte
70  pq->head = 0;
71  pq->tail = 0;
72  // queue length is 0
73  pq->length = 0;
74  return pq;
75 }
76 inline uint16_t QueueLength(volatile Queue_s * pq)
77 {
84  return pq->length;
85 }
86 inline bool QueueIsFull(volatile Queue_s * pq)
87 {
92  if (pq->length >= pq->max_length) return true;
93  return false;
94 }
95 inline bool QueueIsEmpty(volatile Queue_s * pq)
96 {
101  if (pq->length == 0) return true;
102  return false;
103  // ---Expected Assembly---
104  // 1b0: ldd r24, Z+4 ; 0x04
105  // 1b2: and r24, r24
106  // 1b4: breq .-6 ; 0x1b0 <main+0x10a>
107  // Total number of cycles: 5
108  // Total number of instructions: 3
109  //
110  // ---24 cycles without inline---
111  // 10 cycles to call
112  // 14 cycles to execute
113  // movw r30, r24
114  // ldd r18, Z+4 ; 0x04
115  // ldd r19, Z+5 ; 0x05
116  // ldi r24, 0x01 ; 1
117  // or r18, r19
118  // breq .+2 ; 0xfa <QueueIsEmpty+0xe>
119  // ldi r24, 0x00 ; 0
120  // ret
121 }
122 inline void QueuePush(
123  volatile Queue_s * pq,
124  uint8_t data
125  )
126 {
133  if (QueueIsFull(pq)) return;
134  // wrap head to beginning of buffer when it reaches the end of the buffer
135  if (pq->head >= pq->max_length) pq->head = 0;
136  pq->buffer[pq->head++] = data;
137  pq->length++;
138 }
139 inline uint8_t QueuePop(volatile Queue_s *pq)
140 {
148  if (QueueIsEmpty(pq)) return 0;
149  // wrap tail to beginning of buffer when it reaches the end of the buffer
150  if (pq->tail >= pq->max_length) pq->tail = 0;
151  // ---Expected Assembly---
152  // 1bc: ldd r25, Z+3 ; 0x03
153  // 1be: ldd r24, Z+5 ; 0x05
154  // 1c0: cp r25, r24
155  // 1c2: brcs .+2 ; 0x1c6 <main+0x120>
156  // 1c4: std Z+3, r1 ; 0x03
157  // Total number of cycles: 9
158  // Total number of instructions: 5
159  pq->length--;
160  // ---Expected Assembly---
161  // 1c6: ldd r24, Z+4 ; 0x04
162  // 1c8: subi r24, 0x01 ; 1
163  // 1ca: std Z+4, r24 ; 0x04
164  // Total number of cycles: 5
165  // Total number of instructions: 3
166  // Return the byte. Remove byte from Queue by advancing "tail".
167  return pq->buffer[pq->tail++];
168  // ---Expected Assembly---
169  // 1cc: ld r26, Z
170  // 1ce: ldd r27, Z+1 ; 0x01
171  // 1d0: ldd r24, Z+3 ; 0x03
172  // 1d2: ldi r25, 0x01 ; 1
173  // 1d4: add r25, r24
174  // 1d6: std Z+3, r25 ; 0x03
175  // 1d8: add r26, r24
176  // 1da: adc r27, r1
177  // 1dc: ld r24, X
178  // Total number of cycles: 14
179  // Total number of instructions: 9
180 }
181 
182 #endif // _QUEUE_H
uint8_t QueuePop(volatile Queue_s *SpiFifo)
Definition: Queue.h:139
uint16_t QueueLength(volatile Queue_s *pq)
Definition: Queue.h:76
bool QueueIsFull(volatile Queue_s *SpiFifo)
Definition: Queue.h:86
void QueuePush(volatile Queue_s *SpiFifo, uint8_t data_to_push)
Definition: Queue.h:122
volatile Queue_s * QueueInit(volatile uint8_t *buffer, uint16_t const buffer_size_in_bytes)
Definition: Queue.h:51
bool QueueIsEmpty(volatile Queue_s *SpiFifo)
Definition: Queue.h:95
Queue uses a byte array as a circular buffer.
Definition: Queue.h:27
volatile uint8_t max_length
max_length is the maximum number of bytes the queue can hold
Definition: Queue.h:47
volatile uint8_t tail
tail advances after a byte is popped from the queue
Definition: Queue.h:41
volatile uint8_t length
length is the number of unread bytes in the queue
Definition: Queue.h:43
volatile uint8_t * buffer
buffer is the address of the queue's FIFO buffer
Definition: Queue.h:33
volatile uint8_t head
head advances after a byte is pushed onto the queue
Definition: Queue.h:37