-
Notifications
You must be signed in to change notification settings - Fork 1
/
eeprom_circular_buffer.c
134 lines (116 loc) · 4.45 KB
/
eeprom_circular_buffer.c
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
/*
* eeprom_circular_buffer.c
*
* Created: 7/14/2020 8:50:43 AM
* Author: Colin
*/
#include "eeprom_circular_buffer.h"
static uint8_t *ee_cb_get_data_base_address(struct ee_cb *self) {
return self->base_address;
}
static uint8_t *ee_cb_get_data_address(struct ee_cb *self, uint8_t index) {
return ee_cb_get_data_base_address(self) + index * self->data_size;
}
static uint8_t *ee_cb_get_status_base_address(struct ee_cb *self) {
return self->base_address + self->buffer_size * self->data_size;
}
static uint8_t *ee_cb_get_status_address(struct ee_cb *self, uint8_t index) {
return ee_cb_get_status_base_address(self) + index;
}
static uint8_t ee_cb_read_byte(struct ee_cb *self, uint8_t *addr) {
uint8_t ret = 0;
self->reader(addr, &ret, 1);
return ret;
}
static void ee_cb_write_byte(struct ee_cb* self, uint8_t* addr, uint8_t value) {
self->writer(addr, &value, 1);
}
static uint8_t ee_cb_get_previous_index(struct ee_cb *self, uint8_t index) {
int previous_index = index - 1;
if (previous_index < 0) {
previous_index = self->buffer_size - 1;
}
return (uint8_t)previous_index;
}
static uint8_t ee_cb_get_next_index(struct ee_cb *self, uint8_t index) {
int next_index = index + 1;
if (next_index >= self->buffer_size) {
next_index = 0;
}
return (uint8_t)next_index;
}
struct status_pair {
uint8_t previous;
uint8_t current;
};
static struct status_pair ee_cb_get_previous_and_current_status(
struct ee_cb *self, uint8_t current_index) {
uint8_t *current_address = ee_cb_get_status_address(self, current_index);
uint8_t previous_index = ee_cb_get_previous_index(self, current_index);
uint8_t *previous_address = ee_cb_get_status_address(self, previous_index);
uint8_t current_status = ee_cb_read_byte(self, current_address);
uint8_t previous_status = ee_cb_read_byte(self, previous_address);
return (struct status_pair) {
.previous = previous_status,
.current = current_status
};
}
static uint8_t ee_cb_get_write_index(struct ee_cb *self) {
uint8_t current_index = 0;
while (1) {
struct status_pair status =
ee_cb_get_previous_and_current_status(self, current_index);
if ((uint8_t)(status.previous + 1) != status.current) {
break;
}
current_index = ee_cb_get_next_index(self, current_index);
}
return current_index;
}
static uint8_t ee_cb_get_read_index(struct ee_cb *self) {
uint8_t write_index = ee_cb_get_write_index(self);
return ee_cb_get_previous_index(self, write_index);
}
static uint8_t ee_cb_get_status_to_write(struct ee_cb *self, uint8_t write_index) {
uint8_t previous_index = ee_cb_get_previous_index(self, write_index);
uint8_t *previous_status_address = ee_cb_get_status_address(self, previous_index);
uint8_t previous_status = ee_cb_read_byte(self, previous_status_address);
return previous_status + 1;
}
int ee_cb_init(struct ee_cb *self, uint8_t *base_address, size_t data_size,
size_t buffer_size, ee_cb_writer writer, ee_cb_reader reader) {
if (!writer || !reader || buffer_size > EE_CB_MAX_BUFFER_SIZE) return -1;
self->writer = writer;
self->reader = reader;
self->base_address = base_address;
self->data_size = data_size;
self->buffer_size = buffer_size;
return 0;
}
int ee_cb_write(struct ee_cb *self, const uint8_t *data) {
if (!self || !data) return -1;
uint8_t write_index = ee_cb_get_write_index(self);
/*write data*/
uint8_t *data_address = ee_cb_get_data_address(self, write_index);
self->writer(data_address, data, self->data_size);
/*write status*/
uint8_t next_status = ee_cb_get_status_to_write(self, write_index);
uint8_t *status_address = ee_cb_get_status_address(self, write_index);
ee_cb_write_byte(self, status_address, next_status);
return 0;
}
int ee_cb_read(struct ee_cb *self, uint8_t *data) {
if (!self || !data) return -1;
uint8_t read_index = ee_cb_get_read_index(self);
uint8_t *read_address = ee_cb_get_data_address(self, read_index);
self->reader(read_address, data, self->data_size);
return 0;
}
int ee_cb_read_previous(struct ee_cb *self, uint8_t *data) {
if (!self || !data) return -1;
uint8_t read_index = ee_cb_get_read_index(self);
uint8_t previous_index = ee_cb_get_previous_index(self, read_index);
uint8_t *read_address = ee_cb_get_data_address(self, previous_index);
self->reader(read_address, data, self->data_size);
return 0;
}