Line data Source code
1 : /**
2 : * @ingroup buffer
3 : *
4 : * @file buffer.c
5 : *
6 : * @{
7 : */
8 :
9 : #include "../firmware.h"
10 :
11 : static buffer_cache_t buffer_cache = { false, 0, 0, {0}, {0}, 0x0000 };
12 :
13 4866 : void Buffer_init(void)
14 : {
15 4866 : if(buffer_cache.initialised && !Buffer_verify_cache())
16 : {
17 : /* TODO: SEU Detected, REBOOT! */
18 4865 : Mission_SEU();
19 : }
20 1 : else if(!buffer_cache.initialised)
21 : {
22 1 : if(!Buffer_FRAM_cache_read(&buffer_cache))
23 : {
24 : /* Stored FRAM header fails CRC, so reset the buffer */
25 : /* TODO: Increment a Counter in health data */
26 1 : Buffer_reset();
27 : }
28 :
29 1 : buffer_cache.initialised = true;
30 : }
31 4866 : }
32 :
33 4865 : bool Buffer_verify_cache(void)
34 : {
35 4865 : return (buffer_cache.crc == Util_crc16((uint8_t *)&buffer_cache, sizeof(buffer_cache_t) - sizeof(uint16_t)));
36 : }
37 :
38 5 : void Buffer_reset(void)
39 : {
40 5 : buffer_cache.last_index_stored = 0;
41 5 : Buffer_FRAM_write_last_index_stored(&buffer_cache);
42 :
43 5 : buffer_cache.last_slot_transmitted = (BUFFER_SLOTS-1);
44 5 : Buffer_FRAM_write_last_slot_transmitted(&buffer_cache);
45 :
46 5 : memset(buffer_cache.occupancy, 0x00, BUFFER_FRAM_SIZE_OCCUPANCY);
47 5 : Buffer_FRAM_write_occupancy(&buffer_cache);
48 :
49 5 : memset(buffer_cache.indexes, 0x00, BUFFER_FRAM_SIZE_INDEXES);
50 5 : Buffer_FRAM_write_indexes(&buffer_cache);
51 :
52 : /* CRC is automatically updated on each FRAM write */
53 5 : }
54 :
55 2424 : void Buffer_store_new_data(uint8_t *data_payload)
56 : {
57 2424 : Buffer_init();
58 :
59 : uint16_t new_slot;
60 : uint16_t new_index;
61 :
62 2424 : new_index = (uint16_t)(buffer_cache.last_index_stored + 1);
63 :
64 2424 : Buffer_find_new_slot(&new_slot);
65 2424 : Buffer_FRAM_write_data(new_slot, data_payload);
66 2424 : Buffer_set_index(new_slot, new_index);
67 2424 : Buffer_set_occupancy(new_slot, true);
68 2424 : }
69 :
70 2424 : void Buffer_set_index(uint16_t slot, uint16_t index)
71 : {
72 2424 : buffer_cache.indexes[slot] = index;
73 2424 : Buffer_FRAM_write_indexes(&buffer_cache);
74 2424 : }
75 :
76 9 : bool Buffer_get_next_data(uint8_t *data_payload)
77 : {
78 9 : Buffer_init();
79 :
80 9 : if(Buffer_get_next_slot(&(buffer_cache.last_slot_transmitted)))
81 : {
82 7 : Buffer_FRAM_read_data(buffer_cache.last_slot_transmitted, data_payload);
83 7 : return true;
84 : }
85 2 : return false;
86 : }
87 :
88 9 : bool Buffer_get_next_slot(uint16_t *slot)
89 : {
90 9 : uint16_t new_slot = *slot;
91 :
92 9 : if(++new_slot >= BUFFER_SLOTS)
93 : {
94 : /* Wrap search */
95 4 : new_slot = 0;
96 : }
97 :
98 6062 : while(new_slot != *slot)
99 : {
100 : /* Check if slot is occupied */
101 6049 : if(0x00 != (buffer_cache.occupancy[new_slot>>3] & (0x80 >> (new_slot & 0x07))))
102 : {
103 5 : *slot = new_slot;
104 5 : return true;
105 : }
106 :
107 6044 : if(++new_slot >= BUFFER_SLOTS)
108 : {
109 : /* Wrap search */
110 3 : new_slot = 0;
111 : }
112 : }
113 :
114 4 : if(0x00 != (buffer_cache.occupancy[new_slot>>3] & (0x80 >> (new_slot & 0x07))))
115 : {
116 2 : *slot = new_slot;
117 2 : return true;
118 : }
119 :
120 2 : return false;
121 : }
122 :
123 3 : void Buffer_remove_index(uint16_t index)
124 : {
125 : uint16_t slot;
126 3 : if(Buffer_find_index(index, &slot))
127 : {
128 2 : Buffer_set_occupancy(slot, false);
129 : }
130 3 : }
131 :
132 3 : bool Buffer_find_index(uint16_t index, uint16_t *slot)
133 : {
134 3 : *slot = 0;
135 1215 : while(buffer_cache.indexes[*slot] != index)
136 : {
137 1210 : if(++*slot >= BUFFER_SLOTS)
138 : {
139 1 : return false;
140 : }
141 : }
142 2 : return true;
143 : }
144 :
145 2424 : void Buffer_find_new_slot(uint16_t *slot)
146 : {
147 2424 : *slot = 0;
148 2199184 : while (buffer_cache.occupancy[*slot>>3] & (0x80 >> (*slot & 0x07)))
149 : {
150 2195546 : if(++*slot >= BUFFER_SLOTS)
151 : {
152 : /* No unoccupied slots, so find slot with oldest index */
153 1210 : Buffer_find_oldest_slot(slot);
154 1210 : return;
155 : }
156 : }
157 : }
158 :
159 1210 : void Buffer_find_oldest_slot(uint16_t *slot)
160 : {
161 1210 : uint16_t oldest_slot, oldest_index = buffer_cache.last_index_stored;
162 :
163 1210 : *slot = 0;
164 1465310 : while(++*slot < BUFFER_SLOTS)
165 : {
166 1462890 : if(oldest_index <= buffer_cache.last_index_stored)
167 : {
168 1210 : if(buffer_cache.indexes[*slot] < oldest_index)
169 : {
170 0 : oldest_index = buffer_cache.indexes[*slot];
171 0 : oldest_slot = *slot;
172 : }
173 1210 : else if(buffer_cache.indexes[*slot] > buffer_cache.last_index_stored)
174 : {
175 1210 : oldest_index = buffer_cache.indexes[*slot];
176 1210 : oldest_slot = *slot;
177 : }
178 : }
179 1461680 : else if(buffer_cache.indexes[*slot] > buffer_cache.last_index_stored)
180 : {
181 1461680 : if(buffer_cache.indexes[*slot] < oldest_index)
182 : {
183 0 : oldest_index = buffer_cache.indexes[*slot];
184 0 : oldest_slot = *slot;
185 : }
186 : }
187 : }
188 :
189 1210 : *slot = oldest_slot;
190 1210 : return;
191 : }
192 :
193 2 : bool Buffer_get_occupancy(uint16_t slot)
194 : {
195 2 : return buffer_cache.occupancy[slot>>3] & (0x80 >> (slot & 0x07));
196 : }
197 :
198 2426 : void Buffer_set_occupancy(uint16_t slot, bool value)
199 : {
200 2426 : if(value)
201 : {
202 : /* Set the corresponding bit */
203 2424 : buffer_cache.occupancy[slot>>3] = (uint8_t)(buffer_cache.occupancy[slot>>3] | (0x80 >> (slot & 0x07)));
204 : }
205 : else
206 : {
207 : /* Reset the corresponding bit */
208 2 : buffer_cache.occupancy[slot>>3] = (uint8_t)(buffer_cache.occupancy[slot>>3] & ~(0x80 >> (slot & 0x07)));
209 : }
210 2426 : Buffer_FRAM_write_occupancy(&buffer_cache);
211 2426 : }
212 :
213 2429 : uint16_t Buffer_count_occupied(void)
214 : {
215 2429 : Buffer_init();
216 :
217 : uint16_t i;
218 2429 : uint16_t result = 0;
219 :
220 2941519 : for(i=0; i<BUFFER_SLOTS; i++)
221 : {
222 2939090 : if(buffer_cache.occupancy[i>>3] & (0x80 >> (i & 0x07)))
223 : {
224 2196762 : result++;
225 : }
226 : }
227 2429 : return result;
228 : }
229 :
230 : /**
231 : * @}
232 : */
|