The metadata kept for each pointID.
Esempio n. 1
0
 private void WriteQualityChange(uint quality, TsscPointMetadata point)
 {
     if (point.PrevQuality2 == quality)
     {
         m_lastPoint.WriteCode(TsscCodeWords.Quality2);
     }
     else
     {
         m_lastPoint.WriteCode(TsscCodeWords.Quality7Bit32);
         Encoding7Bit.Write(m_data, ref m_position, quality);
     }
     point.PrevQuality2 = point.PrevQuality1;
     point.PrevQuality1 = quality;
 }
Esempio n. 2
0
        /// <summary>
        /// Resets the TSSC Decoder to the initial state.
        /// </summary>
        /// <remarks>
        /// TSSC is a stateful encoder that requires a state
        /// of the previous data to be maintained. Therefore, if
        /// the state ever becomes corrupt (out of order, dropped, corrupted, or duplicated)
        /// the state must be reset on both ends.
        /// </remarks>
        public void Reset()
        {
            m_points       = new IndexedArray <TsscPointMetadata>();
            m_lastPoint    = new TsscPointMetadata(null, ReadBit, ReadBits5);
            m_data         = EmptyArray <byte> .Empty;
            m_position     = 0;
            m_lastPosition = 0;
            ClearBitStream();

            m_prevTimeDelta1 = long.MaxValue;
            m_prevTimeDelta2 = long.MaxValue;
            m_prevTimeDelta3 = long.MaxValue;
            m_prevTimeDelta4 = long.MaxValue;
            m_prevTimestamp1 = 0;
            m_prevTimestamp2 = 0;
        }
Esempio n. 3
0
        private uint DecodeQuality(int code, TsscPointMetadata nextPoint)
        {
            uint quality;

            if (code == TsscCodeWords.Quality2)
            {
                quality = nextPoint.PrevQuality2;
            }
            else
            {
                quality = Encoding7Bit.ReadUInt32(m_data, ref m_position);
            }
            nextPoint.PrevQuality2 = nextPoint.PrevQuality1;
            nextPoint.PrevQuality1 = quality;
            return(quality);
        }
Esempio n. 4
0
        /// <summary>
        /// Resets the TSSC Encoder to the initial state. 
        /// </summary>
        /// <remarks>
        /// TSSC is a stateful encoder that requires a state
        /// of the previous data to be maintained. Therefore, if 
        /// the state ever becomes corrupt (out of order, dropped, corrupted, or duplicated)
        /// the state must be reset on both ends.
        /// </remarks>
        public void Reset()
        {
            m_points = new IndexedArray<TsscPointMetadata>();
            m_lastPoint = new TsscPointMetadata(WriteBits, null, null);
            m_data = EmptyArray<byte>.Empty;
            m_position = 0;
            m_lastPosition = 0;
            ClearBitStream();

            m_prevTimeDelta1 = long.MaxValue;
            m_prevTimeDelta2 = long.MaxValue;
            m_prevTimeDelta3 = long.MaxValue;
            m_prevTimeDelta4 = long.MaxValue;
            m_prevTimestamp1 = 0;
            m_prevTimestamp2 = 0;
        }
Esempio n. 5
0
 private void DecodePointID(int code, TsscPointMetadata lastPoint)
 {
     if (code == TsscCodeWords.PointIDXOR4)
     {
         lastPoint.PrevNextPointId1 ^= (ushort)ReadBits4();
     }
     else if (code == TsscCodeWords.PointIDXOR8)
     {
         lastPoint.PrevNextPointId1 ^= m_data[m_position++];
     }
     else if (code == TsscCodeWords.PointIDXOR12)
     {
         lastPoint.PrevNextPointId1 ^= (ushort)ReadBits4();
         lastPoint.PrevNextPointId1 ^= (ushort)(m_data[m_position++] << 4);
     }
     else
     {
         lastPoint.PrevNextPointId1 ^= m_data[m_position++];
         lastPoint.PrevNextPointId1 ^= (ushort)(m_data[m_position++] << 8);
     }
 }
Esempio n. 6
0
        /// <summary>
        /// Reads the next measurement from the stream. If the end of the stream has been encountered,
        /// return false.
        /// </summary>
        /// <param name="id">the id</param>
        /// <param name="timestamp">the timestamp in ticks</param>
        /// <param name="quality">the quality</param>
        /// <param name="value">the value</param>
        /// <returns>true if successful, false otherwise.</returns>
        public unsafe bool TryGetMeasurement(out ushort id, out long timestamp, out uint quality, out float value)
        {
            TsscPointMetadata nextPoint = null;

            if (m_position == m_lastPosition && BitStreamIsEmpty)
            {
                ClearBitStream();
                id        = 0;
                timestamp = 0;
                quality   = 0;
                value     = 0;
                return(false);
            }

            //Note: since I will not know the incoming pointID. The most recent
            //      measurement received will be the one that contains the
            //      coding algorithm for this measurement. Since for the more part
            //      measurements generally have some sort of sequence to them,
            //      this still ends up being a good enough assumption.

            int code = m_lastPoint.ReadCode();

            if (code == TsscCodeWords.EndOfStream)
            {
                ClearBitStream();
                id        = 0;
                timestamp = 0;
                quality   = 0;
                value     = 0;
                return(false);
            }

            if (code <= TsscCodeWords.PointIDXOR16)
            {
                DecodePointID(code, m_lastPoint);
                code = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.TimeDelta1Forward)
                {
                    throw new Exception($"Expecting code >= {TsscCodeWords.TimeDelta1Forward} Received {code} at position {m_position} with last position { m_lastPosition}");
                }
            }

            id        = m_lastPoint.PrevNextPointId1;
            nextPoint = m_points[m_lastPoint.PrevNextPointId1];
            if (nextPoint == null)
            {
                nextPoint    = new TsscPointMetadata(null, ReadBit, ReadBits5);
                m_points[id] = nextPoint;
                nextPoint.PrevNextPointId1 = (ushort)(id + 1);
            }

            if (code <= TsscCodeWords.TimeXOR7Bit)
            {
                timestamp = DecodeTimestamp(code);
                code      = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.Quality2)
                {
                    throw new Exception($"Expecting code >= {TsscCodeWords.Quality2} Received {code} at position {m_position} with last position { m_lastPosition}");
                }
            }
            else
            {
                timestamp = m_prevTimestamp1;
            }

            if (code <= TsscCodeWords.Quality7Bit32)
            {
                quality = DecodeQuality(code, nextPoint);
                code    = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.Value1)
                {
                    throw new Exception($"Expecting code >= {TsscCodeWords.Value1} Received {code} at position {m_position} with last position { m_lastPosition}");
                }
            }
            else
            {
                quality = nextPoint.PrevQuality1;
            }

            //Since value will almost always change,
            //This is not put inside a function call.
            uint valueRaw = 0;

            if (code == TsscCodeWords.Value1)
            {
                valueRaw = nextPoint.PrevValue1;
            }
            else if (code == TsscCodeWords.Value2)
            {
                valueRaw             = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else if (code == TsscCodeWords.Value3)
            {
                valueRaw             = nextPoint.PrevValue3;
                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else if (code == TsscCodeWords.ValueZero)
            {
                valueRaw             = 0;
                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else
            {
                switch (code)
                {
                case TsscCodeWords.ValueXOR4:
                    valueRaw = (uint)ReadBits4() ^ nextPoint.PrevValue1;
                    break;

                case TsscCodeWords.ValueXOR8:
                    valueRaw   = m_data[m_position] ^ nextPoint.PrevValue1;
                    m_position = m_position + 1;
                    break;

                case TsscCodeWords.ValueXOR12:
                    valueRaw   = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ nextPoint.PrevValue1;
                    m_position = m_position + 1;
                    break;

                case TsscCodeWords.ValueXOR16:
                    valueRaw   = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ nextPoint.PrevValue1;
                    m_position = m_position + 2;
                    break;

                case TsscCodeWords.ValueXOR20:
                    valueRaw   = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ (uint)(m_data[m_position + 1] << 12) ^ nextPoint.PrevValue1;
                    m_position = m_position + 2;
                    break;

                case TsscCodeWords.ValueXOR24:
                    valueRaw   = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ (uint)(m_data[m_position + 2] << 16) ^ nextPoint.PrevValue1;
                    m_position = m_position + 3;
                    break;

                case TsscCodeWords.ValueXOR28:
                    valueRaw   = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ (uint)(m_data[m_position + 1] << 12) ^ (uint)(m_data[m_position + 2] << 20) ^ nextPoint.PrevValue1;
                    m_position = m_position + 3;
                    break;

                case TsscCodeWords.ValueXOR32:
                    valueRaw   = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ (uint)(m_data[m_position + 2] << 16) ^ (uint)(m_data[m_position + 3] << 24) ^ nextPoint.PrevValue1;
                    m_position = m_position + 4;
                    break;

                default:
                    throw new Exception($"Invalid code received {code} at position {m_position} with last position { m_lastPosition}");
                }

                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }

            value       = *(float *)&valueRaw;
            m_lastPoint = nextPoint;
            return(true);
        }
Esempio n. 7
0
 private void WriteQualityChange(uint quality, TsscPointMetadata point)
 {
     if (point.PrevQuality2 == quality)
     {
         m_lastPoint.WriteCode(TsscCodeWords.Quality2);
     }
     else
     {
         m_lastPoint.WriteCode(TsscCodeWords.Quality7Bit32);
         Encoding7Bit.Write(m_data, ref m_position, quality);
     }
     point.PrevQuality2 = point.PrevQuality1;
     point.PrevQuality1 = quality;
 }
Esempio n. 8
0
        /// <summary>
        /// Adds the supplied measurement to the stream. If the stream is full,
        /// this method returns false.
        /// </summary>
        /// <param name="id">the id</param>
        /// <param name="timestamp">the timestamp in ticks</param>
        /// <param name="quality">the quality</param>
        /// <param name="value">the value</param>
        /// <returns>true if successful, false otherwise.</returns>
        public unsafe bool TryAddMeasurement(ushort id, long timestamp, uint quality, float value)
        {
            //if there are fewer than 100 bytes available on the buffer
            //assume that we cannot add any more.
            if (m_lastPosition - m_position < 100)
                return false;

            TsscPointMetadata point = m_points[id];
            if (point == null)
            {
                point = new TsscPointMetadata(WriteBits, null, null);
                point.PrevNextPointId1 = (ushort)(id + 1);
                m_points[id] = point;
            }

            //Note: since I will not know the incoming pointID. The most recent
            //      measurement received will be the one that contains the 
            //      coding algorithm for this measurement. Since for the more part
            //      measurements generally have some sort of sequence to them, 
            //      this still ends up being a good enough assumption.

            if (m_lastPoint.PrevNextPointId1 != id)
            {
                WritePointIdChange(id);
            }

            if (m_prevTimestamp1 != timestamp)
            {
                WriteTimestampChange(timestamp);
            }

            if (point.PrevQuality1 != quality)
            {
                WriteQualityChange(quality, point);
            }

            uint valueRaw = *(uint*)&value;
            if (point.PrevValue1 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value1);
            }
            else if (point.PrevValue2 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value2);
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }
            else if (point.PrevValue3 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value3);
                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }
            else if (valueRaw == 0)
            {
                m_lastPoint.WriteCode(TsscCodeWords.ValueZero);
                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = 0;
            }
            else
            {
                uint bitsChanged = valueRaw ^ point.PrevValue1;

                if (bitsChanged <= Bits4)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR4);
                    WriteBits((byte)bitsChanged & 15, 4);
                }
                else if (bitsChanged <= Bits8)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR8);

                    m_data[m_position] = (byte)bitsChanged;
                    m_position++;
                }
                else if (bitsChanged <= Bits12)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR12);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position] = (byte)(bitsChanged >> 4);
                    m_position++;
                }
                else if (bitsChanged <= Bits16)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR16);
                    m_data[m_position] = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_position = m_position + 2;
                }
                else if (bitsChanged <= Bits20)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR20);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position] = (byte)(bitsChanged >> 4);
                    m_data[m_position + 1] = (byte)(bitsChanged >> 12);
                    m_position = m_position + 2;
                }
                else if (bitsChanged <= Bits24)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR24);

                    m_data[m_position] = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 16);
                    m_position = m_position + 3;
                }
                else if (bitsChanged <= Bits28)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR28);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position] = (byte)(bitsChanged >> 4);
                    m_data[m_position + 1] = (byte)(bitsChanged >> 12);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 20);
                    m_position = m_position + 3;
                }
                else
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR32);

                    m_data[m_position] = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 16);
                    m_data[m_position + 3] = (byte)(bitsChanged >> 24);
                    m_position = m_position + 4;
                }

                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }

            m_lastPoint = point;

            return true;
        }
Esempio n. 9
0
        /// <summary>
        /// Adds the supplied measurement to the stream. If the stream is full,
        /// this method returns false.
        /// </summary>
        /// <param name="id">the id</param>
        /// <param name="timestamp">the timestamp in ticks</param>
        /// <param name="quality">the quality</param>
        /// <param name="value">the value</param>
        /// <returns>true if successful, false otherwise.</returns>
        public unsafe bool TryAddMeasurement(ushort id, long timestamp, uint quality, float value)
        {
            //if there are fewer than 100 bytes available on the buffer
            //assume that we cannot add any more.
            if (m_lastPosition - m_position < 100)
            {
                return(false);
            }

            TsscPointMetadata point = m_points[id];

            if (point == null)
            {
                point = new TsscPointMetadata(WriteBits, null, null);
                point.PrevNextPointId1 = (ushort)(id + 1);
                m_points[id]           = point;
            }

            //Note: since I will not know the incoming pointID. The most recent
            //      measurement received will be the one that contains the
            //      coding algorithm for this measurement. Since for the more part
            //      measurements generally have some sort of sequence to them,
            //      this still ends up being a good enough assumption.

            if (m_lastPoint.PrevNextPointId1 != id)
            {
                WritePointIdChange(id);
            }

            if (m_prevTimestamp1 != timestamp)
            {
                WriteTimestampChange(timestamp);
            }

            if (point.PrevQuality1 != quality)
            {
                WriteQualityChange(quality, point);
            }

            uint valueRaw = *(uint *)&value;

            if (point.PrevValue1 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value1);
            }
            else if (point.PrevValue2 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value2);
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }
            else if (point.PrevValue3 == valueRaw)
            {
                m_lastPoint.WriteCode(TsscCodeWords.Value3);
                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }
            else if (valueRaw == 0)
            {
                m_lastPoint.WriteCode(TsscCodeWords.ValueZero);
                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = 0;
            }
            else
            {
                uint bitsChanged = valueRaw ^ point.PrevValue1;

                if (bitsChanged <= Bits4)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR4);
                    WriteBits((byte)bitsChanged & 15, 4);
                }
                else if (bitsChanged <= Bits8)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR8);

                    m_data[m_position] = (byte)bitsChanged;
                    m_position++;
                }
                else if (bitsChanged <= Bits12)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR12);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position] = (byte)(bitsChanged >> 4);
                    m_position++;
                }
                else if (bitsChanged <= Bits16)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR16);
                    m_data[m_position]     = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_position             = m_position + 2;
                }
                else if (bitsChanged <= Bits20)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR20);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position]     = (byte)(bitsChanged >> 4);
                    m_data[m_position + 1] = (byte)(bitsChanged >> 12);
                    m_position             = m_position + 2;
                }
                else if (bitsChanged <= Bits24)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR24);

                    m_data[m_position]     = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 16);
                    m_position             = m_position + 3;
                }
                else if (bitsChanged <= Bits28)
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR28);
                    WriteBits((byte)bitsChanged & 15, 4);

                    m_data[m_position]     = (byte)(bitsChanged >> 4);
                    m_data[m_position + 1] = (byte)(bitsChanged >> 12);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 20);
                    m_position             = m_position + 3;
                }
                else
                {
                    m_lastPoint.WriteCode(TsscCodeWords.ValueXOR32);

                    m_data[m_position]     = (byte)bitsChanged;
                    m_data[m_position + 1] = (byte)(bitsChanged >> 8);
                    m_data[m_position + 2] = (byte)(bitsChanged >> 16);
                    m_data[m_position + 3] = (byte)(bitsChanged >> 24);
                    m_position             = m_position + 4;
                }

                point.PrevValue3 = point.PrevValue2;
                point.PrevValue2 = point.PrevValue1;
                point.PrevValue1 = valueRaw;
            }

            m_lastPoint = point;

            return(true);
        }
Esempio n. 10
0
 private uint DecodeQuality(int code, TsscPointMetadata nextPoint)
 {
     uint quality;
     if (code == TsscCodeWords.Quality2)
     {
         quality = nextPoint.PrevQuality2;
     }
     else
     {
         quality = Encoding7Bit.ReadUInt32(m_data, ref m_position);
     }
     nextPoint.PrevQuality2 = nextPoint.PrevQuality1;
     nextPoint.PrevQuality1 = quality;
     return quality;
 }
Esempio n. 11
0
 private void DecodePointID(int code, TsscPointMetadata lastPoint)
 {
     if (code == TsscCodeWords.PointIDXOR4)
     {
         lastPoint.PrevNextPointId1 ^= (ushort)ReadBits4();
     }
     else if (code == TsscCodeWords.PointIDXOR8)
     {
         lastPoint.PrevNextPointId1 ^= m_data[m_position++];
     }
     else if (code == TsscCodeWords.PointIDXOR12)
     {
         lastPoint.PrevNextPointId1 ^= (ushort)ReadBits4();
         lastPoint.PrevNextPointId1 ^= (ushort)(m_data[m_position++] << 4);
     }
     else
     {
         lastPoint.PrevNextPointId1 ^= m_data[m_position++];
         lastPoint.PrevNextPointId1 ^= (ushort)(m_data[m_position++] << 8);
     }
 }
Esempio n. 12
0
        /// <summary>
        /// Reads the next measurement from the stream. If the end of the stream has been encountered, 
        /// return false.
        /// </summary>
        /// <param name="id">the id</param>
        /// <param name="timestamp">the timestamp in ticks</param>
        /// <param name="quality">the quality</param>
        /// <param name="value">the value</param>
        /// <returns>true if successful, false otherwise.</returns>
        public unsafe bool TryGetMeasurement(out ushort id, out long timestamp, out uint quality, out float value)
        {
            TsscPointMetadata nextPoint = null;

            if (m_position == m_lastPosition && BitStreamIsEmpty)
            {
                ClearBitStream();
                id = 0;
                timestamp = 0;
                quality = 0;
                value = 0;
                return false;
            }

            //Note: since I will not know the incoming pointID. The most recent
            //      measurement received will be the one that contains the 
            //      coding algorithm for this measurement. Since for the more part
            //      measurements generally have some sort of sequence to them, 
            //      this still ends up being a good enough assumption.

            int code = m_lastPoint.ReadCode();

            if (code == TsscCodeWords.EndOfStream)
            {
                ClearBitStream();
                id = 0;
                timestamp = 0;
                quality = 0;
                value = 0;
                return false;
            }

            if (code <= TsscCodeWords.PointIDXOR16)
            {
                DecodePointID(code, m_lastPoint);
                code = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.TimeDelta1Forward)
                    throw new Exception($"Expecting code >= {TsscCodeWords.TimeDelta1Forward} Received {code} at position {m_position} with last position { m_lastPosition}");
            }

            id = m_lastPoint.PrevNextPointId1;
            nextPoint = m_points[m_lastPoint.PrevNextPointId1];
            if (nextPoint == null)
            {
                nextPoint = new TsscPointMetadata(null, ReadBit, ReadBits5);
                m_points[id] = nextPoint;
                nextPoint.PrevNextPointId1 = (ushort)(id + 1);
            }

            if (code <= TsscCodeWords.TimeXOR7Bit)
            {
                timestamp = DecodeTimestamp(code);
                code = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.Quality2)
                    throw new Exception($"Expecting code >= {TsscCodeWords.Quality2} Received {code} at position {m_position} with last position { m_lastPosition}");
            }
            else
            {
                timestamp = m_prevTimestamp1;
            }

            if (code <= TsscCodeWords.Quality7Bit32)
            {
                quality = DecodeQuality(code, nextPoint);
                code = m_lastPoint.ReadCode();
                if (code < TsscCodeWords.Value1)
                    throw new Exception($"Expecting code >= {TsscCodeWords.Value1} Received {code} at position {m_position} with last position { m_lastPosition}");
            }
            else
            {
                quality = nextPoint.PrevQuality1;
            }

            //Since value will almost always change, 
            //This is not put inside a function call.
            uint valueRaw = 0;
            if (code == TsscCodeWords.Value1)
            {
                valueRaw = nextPoint.PrevValue1;
            }
            else if (code == TsscCodeWords.Value2)
            {
                valueRaw = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else if (code == TsscCodeWords.Value3)
            {
                valueRaw = nextPoint.PrevValue3;
                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else if (code == TsscCodeWords.ValueZero)
            {
                valueRaw = 0;
                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }
            else
            {
                switch (code)
                {
                    case TsscCodeWords.ValueXOR4:
                        valueRaw = (uint)ReadBits4() ^ nextPoint.PrevValue1;
                        break;
                    case TsscCodeWords.ValueXOR8:
                        valueRaw = m_data[m_position] ^ nextPoint.PrevValue1;
                        m_position = m_position + 1;
                        break;
                    case TsscCodeWords.ValueXOR12:
                        valueRaw = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ nextPoint.PrevValue1;
                        m_position = m_position + 1;
                        break;
                    case TsscCodeWords.ValueXOR16:
                        valueRaw = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ nextPoint.PrevValue1;
                        m_position = m_position + 2;
                        break;
                    case TsscCodeWords.ValueXOR20:
                        valueRaw = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ (uint)(m_data[m_position + 1] << 12) ^ nextPoint.PrevValue1;
                        m_position = m_position + 2;
                        break;
                    case TsscCodeWords.ValueXOR24:
                        valueRaw = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ (uint)(m_data[m_position + 2] << 16) ^ nextPoint.PrevValue1;
                        m_position = m_position + 3;
                        break;
                    case TsscCodeWords.ValueXOR28:
                        valueRaw = (uint)ReadBits4() ^ (uint)(m_data[m_position] << 4) ^ (uint)(m_data[m_position + 1] << 12) ^ (uint)(m_data[m_position + 2] << 20) ^ nextPoint.PrevValue1;
                        m_position = m_position + 3;
                        break;
                    case TsscCodeWords.ValueXOR32:
                        valueRaw = m_data[m_position] ^ (uint)(m_data[m_position + 1] << 8) ^ (uint)(m_data[m_position + 2] << 16) ^ (uint)(m_data[m_position + 3] << 24) ^ nextPoint.PrevValue1;
                        m_position = m_position + 4;
                        break;
                    default:
                        throw new Exception($"Invalid code received {code} at position {m_position} with last position { m_lastPosition}");
                }

                nextPoint.PrevValue3 = nextPoint.PrevValue2;
                nextPoint.PrevValue2 = nextPoint.PrevValue1;
                nextPoint.PrevValue1 = valueRaw;
            }

            value = *(float*)&valueRaw;
            m_lastPoint = nextPoint;
            return true;
        }