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+
27+using namespace std;
28+using namespace GSF;
29+using namespace GSF::TimeSeries;
30+using namespace GSF::TimeSeries::Transport;
31+
32+uint32_t Decode7BitUInt32(const uint8_t* stream, uint32_t& position);
33+uint64_t Decode7BitUInt64(const uint8_t* stream, uint32_t& position);
34+
35+TSSCDecoder::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+
51+void 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+
67+TSSCPointMetadataPtr TSSCDecoder::NewTSSCPointMetadata()
68+{
69+ return NewSharedPtr<TSSCPointMetadata>([this]() { return ReadBit(); }, [this]() { return ReadBits5(); });
70+}
71+
72+void 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+
80+bool 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+
286+void 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+
308+int64_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+
388+uint32_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+
407+bool TSSCDecoder::BitStreamIsEmpty() const
408+{
409+ return m_bitStreamCount == 0;
410+}
411+
412+void TSSCDecoder::ClearBitStream()
413+{
414+ m_bitStreamCount = 0;
415+ m_bitStreamCache = 0;
416+}
417+
418+int32_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+
431+int32_t TSSCDecoder::ReadBits4()
432+{
433+ return ReadBit() << 3 | ReadBit() << 2 | ReadBit() << 1 | ReadBit();;
434+}
435+
436+int32_t TSSCDecoder::ReadBits5()
437+{
438+ return ReadBit() << 4 | ReadBit() << 3 | ReadBit() << 2 | ReadBit() << 1 | ReadBit();;
439+}
440+
441+uint32_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+
482+uint64_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