blob: b23abdbf92536742d613064858a5383aaf84f2d9 (
plain)
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
|
#pragma once
#include <Arduino.h>
#include "PublicMessageRing.h"
class FlashStore {
public:
FlashStore();
void begin();
uint16_t getMessageCount() const { return _count; }
uint32_t getSentCount() const { return _sent_count; }
uint32_t getRecvCount() const { return _recv_count; }
uint32_t getLatestTimestamp() const { return _latest_timestamp; }
uint32_t getTotalLineCount() const { return _total_lines; }
uint16_t getBlankPageCount() const { return _blank_pages; }
uint16_t getInvalidPageCount() const { return _invalid_pages; }
uint16_t getPhysicalBreakCount() const { return _physical_breaks; }
uint16_t getNextPage() const { return _next_page; }
bool getMessage(uint16_t idx, PublicMessage& message) const;
bool appendMessage(uint32_t timestamp, const char* text, bool outbound, const uint8_t* hash = NULL, bool rebroadcasted = false);
private:
static const uint32_t kBaseAddr = 0x0000UL;
static const uint32_t kFlashSize = 128UL * 1024UL;
static const uint16_t kSectorSize = 4096;
static const uint16_t kPageSize = 256;
static const uint16_t kPageCount = kFlashSize / kPageSize;
static const uint8_t kPagesPerSector = kSectorSize / kPageSize;
static const uint32_t kMagic = 0x4D585253UL; // 'SRXM'
enum MessageFlags : uint8_t {
kFlagOutbound = 1 << 0,
};
struct MessageRecord {
uint32_t magic;
uint16_t version;
uint16_t crc;
uint32_t sequence;
uint32_t timestamp;
uint8_t flags;
uint8_t line_count;
uint8_t hash[MAX_HASH_SIZE];
char text[sizeof(PublicMessage::text)];
uint8_t reserved[kPageSize - 4 - 2 - 2 - 4 - 4 - 1 - 1 - MAX_HASH_SIZE - sizeof(PublicMessage::text)];
};
static_assert(sizeof(MessageRecord) == kPageSize, "Flash message record size must match a flash page");
MessageRecord _record_scratch;
uint16_t _pages[kPageCount];
uint32_t _sequences[kPageCount];
uint16_t _next_page;
uint16_t _count;
uint32_t _next_sequence;
uint32_t _sent_count;
uint32_t _recv_count;
uint32_t _latest_timestamp;
uint32_t _total_lines;
uint16_t _blank_pages;
uint16_t _invalid_pages;
uint16_t _physical_breaks;
static uint16_t crc16(const uint8_t* data, size_t len);
static bool isBlank(const uint8_t* data, size_t len);
static bool isValidRecord(const MessageRecord& record);
static PublicMessage messageFrom(const MessageRecord& record);
void resetStats();
void insertPageSorted(uint16_t page, uint32_t sequence);
void removePageAt(uint16_t idx);
void updatePhysicalBreaks();
uint16_t findNextBlankPage(uint16_t start_page) const;
bool pageInUse(uint16_t page) const;
bool sectorHasActivePages(uint16_t sector) const;
bool readRecord(uint16_t page, MessageRecord& record) const;
uint16_t pageForIndex(uint16_t idx) const;
bool writeRecord(uint16_t page, const MessageRecord& record);
bool eraseSector(uint16_t sector);
bool prepareNextPageForWrite();
void dropSectorFromStats(uint16_t sector);
};
|