30static const int kNotFound = -1;
33static const int kGcThreshold = 100;
36static const int kGcIntervalSecs = 10;
39static const int kEntryMaxAgeSecs = 100;
41typedef struct can_frame CanFrame;
43bool IsFastMessagePGN(
unsigned pgn) {
44 static const std::vector<unsigned> haystack = {
47 65240u, 126208u, 126464u, 126720u, 126983u, 126984u, 126985u, 126986u,
48 126987u, 126988u, 126996u, 126998u, 127233u, 127237u, 127489u, 127490u,
49 127491u, 127494u, 127495u, 127496u, 127497u, 127498u, 127503u, 127504u,
50 127506u, 127507u, 127510u, 127513u, 128275u, 128520u, 128538u, 129029u,
51 129038u, 129039u, 129040u, 129041u, 129044u, 129045u, 129284u, 129285u,
52 129301u, 129302u, 129538u, 129540u, 129541u, 129542u, 129545u, 129547u,
53 129549u, 129550u, 129551u, 129556u, 129792u, 129793u, 129794u, 129795u,
54 129796u, 129797u, 129798u, 129799u, 129800u, 129801u, 129802u, 129803u,
55 129804u, 129805u, 129806u, 129807u, 129808u, 129809u, 129810u, 130052u,
56 130053u, 130054u, 130060u, 130061u, 130064u, 130065u, 130066u, 130067u,
57 130068u, 130069u, 130070u, 130071u, 130072u, 130073u, 130074u, 130320u,
58 130321u, 130322u, 130323u, 130324u, 130330u, 130561u, 130562u, 130563u,
59 130564u, 130565u, 130566u, 130567u, 130569u, 130570u, 130571u, 130572u,
60 130573u, 130574u, 130577u, 130578u, 130580u, 130581u, 130583u, 130584u,
61 130586u, 130816u, 130817u, 130818u, 130819u, 130820u, 130821u, 130822u,
62 130824u, 130827u, 130828u, 130831u, 130832u, 130834u, 130835u, 130836u,
63 130837u, 130838u, 130839u, 130840u, 130842u, 130843u, 130845u, 130846u,
64 130847u, 130850u, 130851u, 130856u, 130880u, 130881u, 130944u};
66 unsigned needle =
static_cast<unsigned>(pgn);
67 auto found = std::find_if(haystack.begin(), haystack.end(),
68 [needle](
unsigned i) { return i == needle; });
69 return found != haystack.end();
72unsigned long BuildCanID(
int priority,
int source,
int destination,
int pgn) {
74 unsigned long cid = 0;
75 unsigned char pf = (
unsigned char)(pgn >> 8);
77 cid = ((
unsigned long)(priority & 0x7)) << 26 | pgn << 8 |
78 ((
unsigned long)destination) << 8 | (
unsigned long)source;
80 cid = ((
unsigned long)(priority & 0x7)) << 26 | pgn << 8 |
81 (
unsigned long)source;
90 buf[0] = frame.can_id & 0xFF;
91 buf[1] = (frame.can_id >> 8) & 0xFF;
92 buf[2] = (frame.can_id >> 16) & 0xFF;
93 buf[3] = (frame.can_id >> 24) & 0xFF;
96 destination = buf[2] < 240 ? buf[1] : 255;
97 pgn = (buf[3] & 0x01) << 16 | (buf[2] << 8) | (buf[2] < 240 ? 0 : buf[1]);
98 priority = (buf[3] & 0x1c) >> 2;
102 return IsFastMessagePGN(
static_cast<unsigned>(pgn));
104 static const std::vector<unsigned> haystack = {
106 65240u, 126208u, 126464u, 126996u, 126998u, 127233u, 127237u, 127489u,
107 127496u, 127506u, 128275u, 129029u, 129038u, 129039u, 129040u, 129041u,
108 129284u, 129285u, 129540u, 129793u, 129794u, 129795u, 129797u, 129798u,
109 129801u, 129802u, 129808u, 129809u, 129810u, 130065u, 130074u, 130323u,
110 130577u, 130820u, 130822u, 130824u};
112 unsigned needle =
static_cast<unsigned>(pgn);
113 auto found = std::find_if(haystack.begin(), haystack.end(),
114 [needle](
unsigned i) { return i == needle; });
115 return found != haystack.end();
121bool FastMessageMap::IsEntryExpired(
unsigned int i) {
122 return (wxDateTime::Now() - entries[i].time_arrived >
123 wxTimeSpan(0, 0, kEntryMaxAgeSecs));
126void FastMessageMap::CheckGc() {
127 bool last_run_over_age =
128 (wxDateTime::Now() - last_gc_run) > wxTimeSpan(0, 0, kGcIntervalSecs);
129 if (last_run_over_age || entries.size() > kGcThreshold) {
131 last_gc_run = wxDateTime::Now();
136 const unsigned char sid) {
137 for (
unsigned i = 0; i < entries.size(); i++) {
138 if (((sid & 0xE0) == (entries[i].sid & 0xE0)) &&
139 (entries[i].header.pgn == header.pgn) &&
140 (entries[i].header.source == header.source) &&
141 (entries[i].header.destination == header.destination)) {
149 entries.push_back(
Entry());
150 return entries.size() - 1;
153int FastMessageMap::GarbageCollector() {
154 std::vector<unsigned> stale_entries;
159 for (
unsigned i = 0; i < entries.size(); i++) {
160 if (IsEntryExpired(i)) {
173 const unsigned char* data,
int index) {
181 if ((data[0] & 0x1F) == 0) {
184 total_data_len =
static_cast<unsigned int>(data[1]);
185 total_data_len += 7 - ((total_data_len - 6) % 7);
187 entries[index].sid =
static_cast<unsigned int>(data[0]);
188 entries[index].expected_length =
static_cast<unsigned int>(data[1]);
189 entries[index].header = header;
190 entries[index].time_arrived = wxDateTime::Now();
192 entries[index].data.resize(total_data_len);
193 memcpy(&entries[index].data[0], &data[2], 6);
196 entries[index].cursor = 6;
199 return entries[index].expected_length <= 6;
207 const unsigned char* data,
int position) {
209 if ((entries[position].sid + 1) == data[0]) {
210 memcpy(&entries[position].data[entries[position].cursor], &data[1], 7);
211 entries[position].sid = data[0];
214 entries[position].cursor += 7;
216 return entries[position].cursor >= entries[position].expected_length;
217 }
else if ((data[0] & 0x1F) == 0) {
223 entries.erase(entries.begin() + position);
233 entries.erase(entries.begin() + position);
235 if (dropped_frames == 0) {
236 dropped_frame_time = wxDateTime::Now();
255 if ((
unsigned int)(pos + 1) <= entries.size())
256 entries.erase(entries.begin() + pos);
int AddNewEntry(void)
Allocate a new, fresh entry and return index to it.
void Remove(int pos)
Remove entry at pos.
bool AppendEntry(const CanHeader hdr, const unsigned char *data, int index)
Append fragment to existing multipart message.
int FindMatchingEntry(const CanHeader header, const unsigned char sid)
Setter.
bool InsertEntry(const CanHeader header, const unsigned char *data, int index)
Insert a new entry, first part of a multipart message.
Low-level socketcan utility functions.