-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuffer.cpp
More file actions
135 lines (114 loc) · 3.1 KB
/
buffer.cpp
File metadata and controls
135 lines (114 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* buffer.c
*
* This file implements a circular buffer
*
* Created: 24/2/2018 4:02:12 PM
* Author: dcstanc
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "buffer.h"
#ifndef NULL
#define NULL (void *) 0x0
#endif
// Disable interrupts
void enterAtomic(unsigned char *csreg)
{
*csreg = SREG;
cli();
}
// Re-enable interrupts
void exitAtomic(unsigned char csreg)
{
SREG = csreg;
}
// Initialize the buffer. We must call this before using writeBuffer or readBuffer.
// PRE:
// Buffer to use is specified in "buffer", size of buffer in characters is specified in "size"
// POST:
// Buffer is initialized to accept up to "size" characters.
void initBuffer(TBuffer *buffer, unsigned int size)
{
buffer->buffer = (unsigned char *) calloc(size, sizeof(unsigned char));
buffer->count=0;
buffer->front=0;
buffer->back=0;
buffer->size=size;
}
// Write to the buffer.
// PRE:
// Buffer specified in "buffer" argument must be initialized using initBuffer. "data" is character to
// write to buffer.
// POST:
// "data" is written to "buffer" and writeBuffer returns BUFFER_OK if space is available.
// "data" is discarded and writeBuffer returns BUFFER_FULL if space is not available.
// "data" is discarded and writeBuffer returns BUFFER_INVALID if "buffer" was not initialized using initBuffer.
TBufferResult writeBuffer(TBuffer *buffer, unsigned char data)
{
enterAtomic(&buffer->csreg);
if(buffer->buffer == NULL || buffer->size == 0)
{
exitAtomic(buffer->csreg);
return BUFFER_INVALID;
}
if(buffer->count >= buffer->size)
{
exitAtomic(buffer->csreg);
return BUFFER_FULL;
}
buffer->buffer[buffer->back] = data;
buffer->back = (buffer->back + 1) % buffer->size;
buffer->count++;
exitAtomic(buffer->csreg);
return BUFFER_OK;
}
// Read from the buffer.
// PRE:
// Buffer specified in "buffer" argument must be initialized using initBuffer. "data" is a pointer
// to a variable of type unsigned char.
// POST:
// Variable pointed to by "data" contains character read from head of the queue, and readBuffer returns
// BUFFER_OK if data is available for reading.
// Variable pointed to by "data" is unmodified, and readBuffer returns BUFFER_EMTPY if no data is available.
// Variable pointed to by "data" is unmodified, and readBuffer returns BUFFER_INVALID if "buffer" was
// not initialized using initBuffer.
TBufferResult readBuffer(TBuffer *buffer, unsigned char *data)
{
enterAtomic(&buffer->csreg);
if(buffer->buffer == NULL || buffer->size == 0)
{
exitAtomic(buffer->csreg);
return BUFFER_INVALID;
}
if(buffer->count == 0)
{
exitAtomic(buffer->csreg);
return BUFFER_EMPTY;
}
*data = buffer->buffer[buffer->front];
buffer->front = (buffer->front + 1) % buffer->size;
buffer->count--;
exitAtomic(buffer->csreg);
return BUFFER_OK;
}
// Frees buffer
// PRE:
// "buffer" points to buffer to free
// POST:
// "buffer" is deallocated.
void freeBuffer(TBuffer *buffer)
{
if(buffer->buffer != NULL)
{
free(buffer->buffer);
buffer->buffer = NULL;
}
buffer->size=0;
buffer->count=0;
}
int dataAvailable(TBuffer *buffer)
{
return (buffer->count > 0);
}