History

TimeSeriesPlatformLibrary: Renamed TSSCMeasurementParser to TSSCDecoder

J. Ritchie Carroll committed 7 years ago

Commit efd7c3c1 parent f6f14f310 files · +92 −89Browse files

Showing the changes to Source/Libraries/TimeSeriesPlatformLibrary/Transport/TSSCDecoder.cpp (1 of 10 files). Show all

Unified · Split

Source/Libraries/TimeSeriesPlatformLibrary/Transport/TSSCDecoder.cpp+553−0
@@ -0,0 +1,553 @@
1//******************************************************************************************************
2// TSSCDecoder.cpp - Gbtc
3//
4// Copyright © 2018, Grid Protection Alliance. All Rights Reserved.
5//
6// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
9// file except in compliance with the License. You may obtain a copy of the License at:
10//
11// http://opensource.org/licenses/MIT
12//
13// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15// License for the specific language governing permissions and limitations.
16//
17// Code Modification History:
18// ----------------------------------------------------------------------------------------------------
19// 04/11/2018 - J. Ritchie Carroll
20// Generated original version of source code.
21//
22//******************************************************************************************************
23
24#include "TSSCDecoder.h"
25#include "Constants.h"
26
27using namespace std;
28using namespace GSF;
29using namespace GSF::TimeSeries;
30using namespace GSF::TimeSeries::Transport;
31
32uint32_t Decode7BitUInt32(const uint8_t* stream, uint32_t& position);
33uint64_t Decode7BitUInt64(const uint8_t* stream, uint32_t& position);
34
35TSSCDecoder::TSSCDecoder() :
36 m_data(nullptr),
37 m_position(0),
38 m_lastPosition(0),
39 m_prevTimestamp1(0L),
40 m_prevTimestamp2(0L),
41 m_prevTimeDelta1(Int64::MaxValue),
42 m_prevTimeDelta2(Int64::MaxValue),
43 m_prevTimeDelta3(Int64::MaxValue),
44 m_prevTimeDelta4(Int64::MaxValue),
45 m_bitStreamCount(0),
46 m_bitStreamCache(0)
47{
48 m_lastPoint = NewTSSCPointMetadata();
49}
50
51void TSSCDecoder::Reset()
52{
53 m_data = nullptr;
54 m_points.clear();
55 m_lastPoint = NewTSSCPointMetadata();
56 m_position = 0;
57 m_lastPosition = 0;
58 ClearBitStream();
59 m_prevTimeDelta1 = Int64::MaxValue;
60 m_prevTimeDelta2 = Int64::MaxValue;
61 m_prevTimeDelta3 = Int64::MaxValue;
62 m_prevTimeDelta4 = Int64::MaxValue;
63 m_prevTimestamp1 = 0L;
64 m_prevTimestamp2 = 0L;
65}
66
67TSSCPointMetadataPtr TSSCDecoder::NewTSSCPointMetadata()
68{
69 return NewSharedPtr<TSSCPointMetadata>([this]() { return ReadBit(); }, [this]() { return ReadBits5(); });
70}
71
72void TSSCDecoder::SetBuffer(uint8_t* data, uint32_t offset, uint32_t length)
73{
74 ClearBitStream();
75 m_data = data;
76 m_position = offset;
77 m_lastPosition = length;
78}
79
80bool TSSCDecoder::TryGetMeasurement(uint16_t& id, int64_t& timestamp, uint32_t& quality, float32_t& value)
81{
82 if (m_position == m_lastPosition && BitStreamIsEmpty())
83 {
84 ClearBitStream();
85 id = 0;
86 timestamp = 0;
87 quality = 0;
88 value = 0.0F;
89 return false;
90 }
91
92 //Note: since I will not know the incoming pointID. The most recent
93 // measurement received will be the one that contains the
94 // coding algorithm for this measurement. Since for the more part
95 // measurements generally have some sort of sequence to them,
96 // this still ends up being a good enough assumption.
97
98 int32_t code = m_lastPoint->ReadCode();
99
100 if (code == TSSCCodeWords::EndOfStream)
101 {
102 ClearBitStream();
103 id = 0;
104 timestamp = 0;
105 quality = 0;
106 value = 0.0F;
107 return false;
108 }
109
110 if (code <= TSSCCodeWords::PointIDXOR16)
111 {
112 DecodePointID(code, m_lastPoint);
113 code = m_lastPoint->ReadCode();
114
115 if (code < TSSCCodeWords::TimeDelta1Forward)
116 {
117 stringstream errorMessageStream;
118
119 errorMessageStream << "Expecting code >= ";
120 errorMessageStream << static_cast<int>(TSSCCodeWords::TimeDelta1Forward);
121 errorMessageStream << " Received ";
122 errorMessageStream << static_cast<int>(code);
123 errorMessageStream << " at position ";
124 errorMessageStream << static_cast<int>(m_position);
125 errorMessageStream << " with last position ";
126 errorMessageStream << static_cast<int>(m_lastPosition);
127
128 throw SubscriberException(errorMessageStream.str());
129 }
130 }
131
132 id = m_lastPoint->PrevNextPointId1;
133 TSSCPointMetadataPtr nextPoint = id >= m_points.size() ? nullptr : m_points[id];
134
135 if (nextPoint == nullptr)
136 {
137 nextPoint = NewTSSCPointMetadata();
138
139 if (id >= m_points.size())
140 m_points.resize(id + 1, nullptr);
141
142 m_points[id] = nextPoint;
143
144 nextPoint->PrevNextPointId1 = static_cast<uint16_t>(id + 1);
145 }
146
147 if (code <= TSSCCodeWords::TimeXOR7Bit)
148 {
149 timestamp = DecodeTimestamp(code);
150 code = m_lastPoint->ReadCode();
151
152 if (code < TSSCCodeWords::Quality2)
153 {
154 stringstream errorMessageStream;
155
156 errorMessageStream << "Expecting code >= ";
157 errorMessageStream << static_cast<int>(TSSCCodeWords::Quality2);
158 errorMessageStream << " Received ";
159 errorMessageStream << static_cast<int>(code);
160 errorMessageStream << " at position ";
161 errorMessageStream << static_cast<int>(m_position);
162 errorMessageStream << " with last position ";
163 errorMessageStream << static_cast<int>(m_lastPosition);
164
165 throw SubscriberException(errorMessageStream.str());
166 }
167 }
168 else
169 {
170 timestamp = m_prevTimestamp1;
171 }
172
173 if (code <= TSSCCodeWords::Quality7Bit32)
174 {
175 quality = DecodeQuality(code, nextPoint);
176 code = m_lastPoint->ReadCode();
177
178 if (code < TSSCCodeWords::Value1)
179 {
180 stringstream errorMessageStream;
181
182 errorMessageStream << "Expecting code >= ";
183 errorMessageStream << static_cast<int>(TSSCCodeWords::Value1);
184 errorMessageStream << " Received ";
185 errorMessageStream << static_cast<int>(code);
186 errorMessageStream << " at position ";
187 errorMessageStream << static_cast<int>(m_position);
188 errorMessageStream << " with last position ";
189 errorMessageStream << static_cast<int>(m_lastPosition);
190
191 throw SubscriberException(errorMessageStream.str());
192 }
193 }
194 else
195 {
196 quality = nextPoint->PrevQuality1;
197 }
198
199 //Since value will almost always change,
200 //This is not put inside a function call.
201 uint32_t valueRaw;
202
203 if (code == TSSCCodeWords::Value1)
204 {
205 valueRaw = nextPoint->PrevValue1;
206 }
207 else if (code == TSSCCodeWords::Value2)
208 {
209 valueRaw = nextPoint->PrevValue2;
210 nextPoint->PrevValue2 = nextPoint->PrevValue1;
211 nextPoint->PrevValue1 = valueRaw;
212 }
213 else if (code == TSSCCodeWords::Value3)
214 {
215 valueRaw = nextPoint->PrevValue3;
216 nextPoint->PrevValue3 = nextPoint->PrevValue2;
217 nextPoint->PrevValue2 = nextPoint->PrevValue1;
218 nextPoint->PrevValue1 = valueRaw;
219 }
220 else if (code == TSSCCodeWords::ValueZero)
221 {
222 valueRaw = 0;
223 nextPoint->PrevValue3 = nextPoint->PrevValue2;
224 nextPoint->PrevValue2 = nextPoint->PrevValue1;
225 nextPoint->PrevValue1 = valueRaw;
226 }
227 else
228 {
229 switch (code)
230 {
231 case TSSCCodeWords::ValueXOR4:
232 valueRaw = static_cast<uint32_t>(ReadBits4()) ^ nextPoint->PrevValue1;
233 break;
234 case TSSCCodeWords::ValueXOR8:
235 valueRaw = static_cast<uint32_t>(m_data[m_position]) ^ nextPoint->PrevValue1;
236 m_position++;
237 break;
238 case TSSCCodeWords::ValueXOR12:
239 valueRaw = static_cast<uint32_t>(ReadBits4()) ^ static_cast<uint32_t>(m_data[m_position] << 4) ^ nextPoint->PrevValue1;
240 m_position++;
241 break;
242 case TSSCCodeWords::ValueXOR16:
243 valueRaw = static_cast<uint32_t>(m_data[m_position]) ^ static_cast<uint32_t>(m_data[m_position + 1] << 8) ^ nextPoint->PrevValue1;
244 m_position += 2;
245 break;
246 case TSSCCodeWords::ValueXOR20:
247 valueRaw = static_cast<uint32_t>(ReadBits4()) ^ static_cast<uint32_t>(m_data[m_position] << 4) ^ static_cast<uint32_t>(m_data[m_position + 1] << 12) ^ nextPoint->PrevValue1;
248 m_position += 2;
249 break;
250 case TSSCCodeWords::ValueXOR24:
251 valueRaw = static_cast<uint32_t>(m_data[m_position]) ^ static_cast<uint32_t>(m_data[m_position + 1] << 8) ^ static_cast<uint32_t>(m_data[m_position + 2] << 16) ^ nextPoint->PrevValue1;
252 m_position += 3;
253 break;
254 case TSSCCodeWords::ValueXOR28:
255 valueRaw = static_cast<uint32_t>(ReadBits4()) ^ static_cast<uint32_t>(m_data[m_position] << 4) ^ static_cast<uint32_t>(m_data[m_position + 1] << 12) ^ static_cast<uint32_t>(m_data[m_position + 2] << 20) ^ nextPoint->PrevValue1;
256 m_position += 3;
257 break;
258 case TSSCCodeWords::ValueXOR32:
259 valueRaw = static_cast<uint32_t>(m_data[m_position]) ^ static_cast<uint32_t>(m_data[m_position + 1] << 8) ^ static_cast<uint32_t>(m_data[m_position + 2] << 16) ^ static_cast<uint32_t>(m_data[m_position + 3] << 24) ^ nextPoint->PrevValue1;
260 m_position += 4;
261 break;
262 default:
263 stringstream errorMessageStream;
264
265 errorMessageStream << "Invalid code received ";
266 errorMessageStream << static_cast<int>(code);
267 errorMessageStream << " at position ";
268 errorMessageStream << static_cast<int>(m_position);
269 errorMessageStream << " with last position ";
270 errorMessageStream << static_cast<int>(m_lastPosition);
271
272 throw SubscriberException(errorMessageStream.str());
273 }
274
275 nextPoint->PrevValue3 = nextPoint->PrevValue2;
276 nextPoint->PrevValue2 = nextPoint->PrevValue1;
277 nextPoint->PrevValue1 = valueRaw;
278 }
279
280 value = *reinterpret_cast<float32_t*>(&valueRaw);
281 m_lastPoint = nextPoint;
282
283 return true;
284}
285
286void TSSCDecoder::DecodePointID(uint8_t code, const TSSCPointMetadataPtr& lastPoint)
287{
288 if (code == TSSCCodeWords::PointIDXOR4)
289 {
290 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(ReadBits4());
291 }
292 else if (code == TSSCCodeWords::PointIDXOR8)
293 {
294 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(m_data[m_position++]);
295 }
296 else if (code == TSSCCodeWords::PointIDXOR12)
297 {
298 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(ReadBits4());
299 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(m_data[m_position++] << 4);
300 }
301 else
302 {
303 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(m_data[m_position++]);
304 lastPoint->PrevNextPointId1 ^= static_cast<uint16_t>(m_data[m_position++] << 8);
305 }
306}
307
308int64_t TSSCDecoder::DecodeTimestamp(uint8_t code)
309{
310 int64_t timestamp;
311
312 if (code == TSSCCodeWords::TimeDelta1Forward)
313 {
314 timestamp = m_prevTimestamp1 + m_prevTimeDelta1;
315 }
316 else if (code == TSSCCodeWords::TimeDelta2Forward)
317 {
318 timestamp = m_prevTimestamp1 + m_prevTimeDelta2;
319 }
320 else if (code == TSSCCodeWords::TimeDelta3Forward)
321 {
322 timestamp = m_prevTimestamp1 + m_prevTimeDelta3;
323 }
324 else if (code == TSSCCodeWords::TimeDelta4Forward)
325 {
326 timestamp = m_prevTimestamp1 + m_prevTimeDelta4;
327 }
328 else if (code == TSSCCodeWords::TimeDelta1Reverse)
329 {
330 timestamp = m_prevTimestamp1 - m_prevTimeDelta1;
331 }
332 else if (code == TSSCCodeWords::TimeDelta2Reverse)
333 {
334 timestamp = m_prevTimestamp1 - m_prevTimeDelta2;
335 }
336 else if (code == TSSCCodeWords::TimeDelta3Reverse)
337 {
338 timestamp = m_prevTimestamp1 - m_prevTimeDelta3;
339 }
340 else if (code == TSSCCodeWords::TimeDelta4Reverse)
341 {
342 timestamp = m_prevTimestamp1 - m_prevTimeDelta4;
343 }
344 else if (code == TSSCCodeWords::Timestamp2)
345 {
346 timestamp = m_prevTimestamp2;
347 }
348 else
349 {
350 timestamp = m_prevTimestamp1 ^ static_cast<int64_t>(Decode7BitUInt64(&m_data[0], m_position));
351 }
352
353 // Save the smallest delta time
354 const int64_t minDelta = abs(m_prevTimestamp1 - timestamp);
355
356 if (minDelta < m_prevTimeDelta4 && minDelta != m_prevTimeDelta1 && minDelta != m_prevTimeDelta2 && minDelta != m_prevTimeDelta3)
357 {
358 if (minDelta < m_prevTimeDelta1)
359 {
360 m_prevTimeDelta4 = m_prevTimeDelta3;
361 m_prevTimeDelta3 = m_prevTimeDelta2;
362 m_prevTimeDelta2 = m_prevTimeDelta1;
363 m_prevTimeDelta1 = minDelta;
364 }
365 else if (minDelta < m_prevTimeDelta2)
366 {
367 m_prevTimeDelta4 = m_prevTimeDelta3;
368 m_prevTimeDelta3 = m_prevTimeDelta2;
369 m_prevTimeDelta2 = minDelta;
370 }
371 else if (minDelta < m_prevTimeDelta3)
372 {
373 m_prevTimeDelta4 = m_prevTimeDelta3;
374 m_prevTimeDelta3 = minDelta;
375 }
376 else
377 {
378 m_prevTimeDelta4 = minDelta;
379 }
380 }
381
382 m_prevTimestamp2 = m_prevTimestamp1;
383 m_prevTimestamp1 = timestamp;
384
385 return timestamp;
386}
387
388uint32_t TSSCDecoder::DecodeQuality(uint8_t code, const TSSCPointMetadataPtr& nextPoint)
389{
390 uint32_t quality;
391
392 if (code == TSSCCodeWords::Quality2)
393 {
394 quality = nextPoint->PrevQuality2;
395 }
396 else
397 {
398 quality = Decode7BitUInt32(&m_data[0], m_position);
399 }
400
401 nextPoint->PrevQuality2 = nextPoint->PrevQuality1;
402 nextPoint->PrevQuality1 = quality;
403
404 return quality;
405}
406
407bool TSSCDecoder::BitStreamIsEmpty() const
408{
409 return m_bitStreamCount == 0;
410}
411
412void TSSCDecoder::ClearBitStream()
413{
414 m_bitStreamCount = 0;
415 m_bitStreamCache = 0;
416}
417
418int32_t TSSCDecoder::ReadBit()
419{
420 if (m_bitStreamCount == 0)
421 {
422 m_bitStreamCount = 8;
423 m_bitStreamCache = static_cast<int32_t>(m_data[m_position++]);
424 }
425
426 m_bitStreamCount--;
427
428 return (m_bitStreamCache >> m_bitStreamCount) & 1;
429}
430
431int32_t TSSCDecoder::ReadBits4()
432{
433 return ReadBit() << 3 | ReadBit() << 2 | ReadBit() << 1 | ReadBit();;
434}
435
436int32_t TSSCDecoder::ReadBits5()
437{
438 return ReadBit() << 4 | ReadBit() << 3 | ReadBit() << 2 | ReadBit() << 1 | ReadBit();;
439}
440
441uint32_t Decode7BitUInt32(const uint8_t* stream, uint32_t& position)
442{
443 stream += position;
444 uint32_t value = *stream;
445
446 if (value < 128)
447 {
448 position++;
449 return value;
450 }
451
452 value ^= (static_cast<uint32_t>(stream[1]) << 7);
453
454 if (value < 16384)
455 {
456 position += 2;
457 return value ^ 0x80;
458 }
459
460 value ^= (static_cast<uint32_t>(stream[2]) << 14);
461
462 if (value < 2097152)
463 {
464 position += 3;
465 return value ^ 0x4080;
466 }
467
468 value ^= (static_cast<uint32_t>(stream[3]) << 21);
469
470 if (value < 268435456)
471 {
472 position += 4;
473 return value ^ 0x204080;
474 }
475
476 value ^= (static_cast<uint32_t>(stream[4]) << 28);
477 position += 5;
478
479 return value ^ 0x10204080;
480}
481
482uint64_t Decode7BitUInt64(const uint8_t* stream, uint32_t& position)
483{
484 stream += position;
485 uint64_t value = *stream;
486
487 if (value < 128UL)
488 {
489 position++;
490 return value;
491 }
492
493 value ^= (static_cast<uint64_t>(stream[1]) << 7);
494
495 if (value < 16384UL)
496 {
497 position += 2;
498 return value ^ 0x80UL;
499 }
500
501 value ^= (static_cast<uint64_t>(stream[2]) << 14);
502
503 if (value < 2097152UL)
504 {
505 position += 3;
506 return value ^ 0x4080UL;
507 }
508
509 value ^= (static_cast<uint64_t>(stream[3]) << 21);
510
511 if (value < 268435456UL)
512 {
513 position += 4;
514 return value ^ 0x204080UL;
515 }
516
517 value ^= (static_cast<uint64_t>(stream[4]) << 28);
518
519 if (value < 34359738368UL)
520 {
521 position += 5;
522 return value ^ 0x10204080UL;
523 }
524
525 value ^= (static_cast<uint64_t>(stream[5]) << 35);
526
527 if (value < 4398046511104UL)
528 {
529 position += 6;
530 return value ^ 0x810204080UL;
531 }
532
533 value ^= (static_cast<uint64_t>(stream[6]) << 42);
534
535 if (value < 562949953421312UL)
536 {
537 position += 7;
538 return value ^ 0x40810204080UL;
539 }
540
541 value ^= (static_cast<uint64_t>(stream[7]) << 49);
542
543 if (value < 72057594037927936UL)
544 {
545 position += 8;
546 return value ^ 0x2040810204080UL;
547 }
548
549 value ^= (static_cast<uint64_t>(stream[8]) << 56);
550 position += 9;
551
552 return value ^ 0x102040810204080UL;
553}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t