libraries / Mitov / Mitov_Packet.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_PACKET_h
  11#define _MITOV_PACKET_h
  12
  13#include <Mitov.h>
  14
  15namespace Mitov
  16{
  17//---------------------------------------------------------------------------
  18        class TPacketAccumulator : public Mitov::SimpleList<unsigned char>
  19        {
  20        public:
  21                bool SkipBytes( int ACount )
  22                {
  23                        if( size() < ACount )
  24                                return false;
  25
  26                        pop_front( ACount );
  27                        return true;
  28                }
  29
  30                bool FindBytes( int ASize, unsigned char *ABytesPtr, int AStartPos, int ASearchSize, int &APosition )
  31                {
  32                        for( APosition = AStartPos; APosition < MitovMin( (int)( _size - ASize ), ASearchSize ); ++APosition )
  33                                if( memcmp( ABytesPtr, _list + APosition, ASize ) == 0 )
  34                                {
  35                                        APosition += ASize;
  36                                        return true;
  37                                }
  38
  39                        return false;
  40                }
  41
  42                bool FindBytes( int ASize, unsigned char *ABytesPtr, int &APosition )
  43                {
  44                        return FindBytes( ASize, ABytesPtr, 0, _size, APosition );
  45                }
  46
  47                bool ExtractBytes( int ASize, void *ABytesPtr )
  48                {
  49                        if( size() < ASize )
  50                                return false;
  51
  52                        memcpy( ABytesPtr, _list, ASize );
  53                        pop_front( ASize );
  54                        return true;
  55                }
  56
  57                bool PeekBytes( int ASize, void *ABytesPtr )
  58                {
  59                        if( size() < ASize )
  60                                return false;
  61
  62                        memcpy( ABytesPtr, _list, ASize );
  63                        return true;
  64                }
  65
  66        };
  67//---------------------------------------------------------------------------
  68        class BasicPacketElement : public OpenWire::Component
  69        {
  70        public:
  71                virtual int      GetSize( bool &Alligned ) { Alligned = true; return 0; }
  72                virtual bool GetIsPopulated() { return true; }
  73                virtual bool GetIsModified() { return false; }
  74                virtual void ClearModified() {}
  75                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) {}
  76                virtual bool Expand( unsigned char *AInBuffer, unsigned char *AOutBuffer, int &ASize ) { return false; }
  77        };
  78//---------------------------------------------------------------------------
  79        class BasicUnpacketElement : public OpenWire::Component
  80        {
  81        public:
  82                virtual int  Start( bool &AAllign ) { AAllign = false; return 0; }
  83                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) { return false; }
  84                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) { return true; }
  85
  86        };
  87//---------------------------------------------------------------------------
  88        class BasicPacketSinkElement : public BasicPacketElement
  89        {
  90        public:
  91                OpenWire::SinkPin       InputPin;
  92
  93        protected:
  94                virtual void DoReceive( void *_Data ) = 0;
  95
  96        public:
  97                BasicPacketSinkElement()
  98                {
  99                        InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&BasicPacketSinkElement::DoReceive );
 100                }
 101
 102        };
 103//---------------------------------------------------------------------------
 104        template<typename T> class BasicTypedPacketSinkElement : public BasicPacketSinkElement
 105        {
 106        protected:
 107                T               FValue;
 108                bool    FPopulated : 1;
 109                bool    FModified : 1;
 110
 111/*
 112        public:
 113                T       InitialValue;
 114
 115                virtual void SystemInit()
 116                {
 117                        inherited::SystemInit();
 118                        FValue = InitialValue;
 119                }
 120*/
 121        public:
 122                virtual int      GetSize( bool &Alligned ) override 
 123                { 
 124                        Alligned = true;
 125//                      Serial.println( sizeof( double ) );
 126                        return sizeof( T ) * 8; 
 127                }
 128
 129                virtual bool    GetIsPopulated() override
 130                { 
 131                        return FPopulated;
 132                }
 133
 134                virtual bool    GetIsModified() override
 135                { 
 136                        return FModified;
 137                }
 138
 139                virtual void ClearModified() override
 140                {
 141                        FModified = false;
 142                }
 143
 144                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override
 145                { 
 146                        if( AOffset )
 147                        {
 148                                ++AData;
 149                                AOffset = 0;
 150                        }
 151
 152                        *(T*)AData = FValue;
 153//                      memcpy( AData, &FValue, sizeof( T ));
 154                        AData += sizeof( T );
 155                }
 156
 157        protected:
 158                virtual void DoReceive( void *_Data ) override
 159                {
 160                        T AValue = *(T*)_Data;
 161                        FPopulated = true;
 162                        if( AValue == FValue )
 163                                return;
 164
 165                        FValue = AValue;
 166                        FModified = true;
 167                }
 168
 169        public:
 170                BasicTypedPacketSinkElement() :
 171                        FPopulated( false ),
 172                        FModified( false )
 173                {
 174                }
 175
 176        };
 177//---------------------------------------------------------------------------
 178        template<typename T> class BasicTypedUnpacketSourceElement : public BasicUnpacketElement
 179        {
 180        public:
 181                OpenWire::SourcePin     OutputPin;
 182
 183        public:
 184                virtual int  Start( bool &AAllign ) override
 185                { 
 186                        AAllign = true; 
 187                        return sizeof( T ) * 8; 
 188                }
 189
 190                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override
 191                { 
 192                        if( AOffset )
 193                        {
 194                                if( ! AAccumulator->SkipBytes( 1 ))
 195                                        return false;
 196
 197                                AOffset = 0;
 198                        }
 199
 200                        T AValue;
 201                        if( ! AAccumulator->ExtractBytes( sizeof( T ), &AValue ))
 202                                return false;
 203
 204                        OutputPin.Notify( &AValue );
 205
 206                        return true;
 207                }
 208
 209                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 210                { 
 211                        APosition = ( APosition + 7 ) / 8;
 212                        APosition *= 8;
 213                        APosition += sizeof( T ) * 8;
 214                        return false;
 215                }
 216        };
 217//---------------------------------------------------------------------------
 218        class UnpacketDigitalBinaryElement : public BasicTypedUnpacketSourceElement<bool>
 219        {
 220        public:
 221                virtual int  Start( bool &AAllign ) override
 222                { 
 223                        AAllign = false;
 224                        return 1; 
 225                }
 226
 227                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override
 228                {
 229                        unsigned char AValue;
 230                        if( ! AAccumulator->PeekBytes( 1, &AValue ))
 231                                return false;
 232
 233                        bool ABoolValue = (( AValue & ( 1 << AOffset )) != 0 );
 234                        ++AOffset;
 235
 236                        if( AOffset == 8 )
 237                        {
 238                                AOffset = 0;
 239                                if( ! AAccumulator->SkipBytes( 1 ))
 240                                        return false;
 241
 242                        }
 243
 244                        OutputPin.Notify( &ABoolValue );
 245
 246                        return true;
 247                }
 248
 249                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 250                { 
 251                        ++ APosition;
 252                        return false;
 253                }
 254        };
 255//---------------------------------------------------------------------------
 256        class PacketBasicMarkerBinaryElement : public BasicPacketElement
 257        {
 258        public:
 259                Mitov::Bytes    Bytes;
 260
 261        };
 262//---------------------------------------------------------------------------
 263        class UnpacketBasicMarkerBinaryElement : public BasicUnpacketElement
 264        {
 265        public:
 266                Mitov::Bytes    Bytes;
 267
 268        public:
 269                virtual int  Start( bool &AAllign ) override
 270                { 
 271                        AAllign = true; 
 272                        return Bytes._BytesSize * 2 * 8; 
 273                }
 274
 275/*
 276                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 277                { 
 278                        return false; 
 279                }
 280
 281                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override { return true; }
 282*/
 283
 284        };
 285//---------------------------------------------------------------------------
 286        class UnpacketMarkerBinaryElement : public UnpacketBasicMarkerBinaryElement
 287        {
 288        public:
 289                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 290                { 
 291                        APosition = ( APosition + 7 ) / 8;
 292                        APosition *= 8;
 293
 294                        int ABytesSize = Bytes._BytesSize;
 295                        int ASearchPos;
 296                        if( ! AInAccumulator->FindBytes( ABytesSize, Bytes._Bytes, APosition / 8, Bytes._BytesSize, ASearchPos ))
 297                                AIsCorruptedPacket = true;
 298
 299                        else if( ASearchPos != APosition / 8 + ABytesSize )
 300                                AIsCorruptedPacket = true;
 301
 302                        APosition += ABytesSize * 8;
 303                        return false; 
 304                }
 305
 306                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override
 307                { 
 308                        if( AOffset != 0 )
 309                        {
 310                                if( !AAccumulator->SkipBytes( 1 ))
 311                                        return false;
 312
 313                                AOffset = 0;
 314                        }
 315
 316                        if( ! AAccumulator->SkipBytes( Bytes._BytesSize ))
 317                                return false;
 318
 319                        return true; 
 320                }
 321        };
 322//---------------------------------------------------------------------------
 323        class UnpacketChecksumElement : public BasicUnpacketElement
 324        {
 325                virtual int  Start( bool &AAllign ) override
 326        {
 327            AAllign = true;
 328            return 8;
 329        }
 330
 331                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 332        {
 333                        APosition = ( APosition + 7 ) / 8;
 334                        APosition *= 8;
 335
 336            unsigned char *ABytes = new unsigned char[ APosition / 8 + 1 ];
 337//            SetLength( ABytes, APosition + 1 );
 338
 339            if( ! AInAccumulator->PeekBytes( APosition / 8 + 1, ABytes ))
 340            {
 341                AIsValid = false;
 342                delete [] ABytes;
 343                return false;
 344            }
 345
 346            unsigned char AChecksum = 0;
 347
 348//            for AByte in ABytes do
 349//                AChecksum ^= AByte;
 350            for( int i = 0; i < APosition / 8 + 1; ++i )
 351                AChecksum ^= ABytes[ i ];
 352
 353            delete [] ABytes;
 354
 355            if( AChecksum )
 356            {
 357                AIsCorruptedPacket = true;
 358                return false;
 359            }
 360
 361            APosition += 8;
 362            return false;
 363        }
 364
 365                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override
 366        {
 367            if( AOffset )
 368            {
 369                if( ! AAccumulator->SkipBytes( 1 ))
 370                  return false;
 371
 372                AOffset = 0;
 373            }
 374
 375            AAccumulator->SkipBytes( 1 );
 376            return true;
 377        }
 378        };
 379//---------------------------------------------------------------------------
 380        class PacketMarkerBinaryElement : public PacketBasicMarkerBinaryElement
 381        {
 382        public:
 383                virtual int      GetSize( bool &Alligned ) override
 384                { 
 385                        Alligned = true;
 386                        return Bytes._BytesSize * 8;
 387                }
 388
 389                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override
 390                {
 391                        if( Bytes._BytesSize == 0 )
 392                                return;
 393
 394                        if( AOffset )
 395                        {
 396                                ++AData;
 397                                AOffset = 0;
 398                        }
 399
 400                        memcpy( AData, Bytes._Bytes, Bytes._BytesSize );
 401                        AData += Bytes._BytesSize;
 402                }
 403
 404        };
 405//---------------------------------------------------------------------------
 406        class PacketChecksumElement : public BasicPacketElement
 407        {
 408        public:
 409                bool    Enabled = true;
 410
 411        public:
 412                virtual int      GetSize( bool &Alligned ) override
 413                { 
 414                        if( Enabled )
 415                        {
 416                                Alligned = true;
 417                                return 8;
 418                        }
 419
 420                        return 0;
 421                }
 422
 423                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override
 424                {
 425                        if( !Enabled )
 426                                return;
 427
 428                        if( AOffset )
 429                        {
 430                                ++AData;
 431                                AOffset = 0;
 432                        }
 433
 434                        unsigned char   AChecksum = 0;
 435                        for( ;ADataStart < AData; ++ADataStart )
 436                                AChecksum ^= *ADataStart;
 437
 438                        *AData = AChecksum;
 439                        ++AData;
 440                }
 441
 442        };
 443//---------------------------------------------------------------------------
 444        class UnpacketHeadMarkerBinaryElement : public UnpacketBasicMarkerBinaryElement
 445        {
 446        protected:
 447                Mitov::SimpleList<unsigned char>        FDoubledBytes;
 448
 449        public:
 450                virtual int  Start( bool &AAllign ) override
 451                { 
 452                        for( int i = 0; i < Bytes._BytesSize; ++i )
 453                                FDoubledBytes.push_back( Bytes._Bytes[ i ] );
 454
 455                        for( int i = 0; i < Bytes._BytesSize; ++i )
 456                                FDoubledBytes.push_back( Bytes._Bytes[ i ] );
 457
 458                        AAllign = true; 
 459                        return Bytes._BytesSize * 2 * 8; 
 460                }
 461
 462                virtual bool Process( TPacketAccumulator *AAccumulator, unsigned char &AOffset ) override
 463                {
 464                        if( AOffset )
 465                        {
 466                                if( ! AAccumulator->SkipBytes( 1 ))
 467                                        return false;
 468
 469                                AOffset = 0;
 470                        }
 471
 472                        //  AOldDebugBuf := AAccumulator.GetAsBuffer();
 473                        AAccumulator->SkipBytes( FDoubledBytes.size() );
 474                        return true;
 475                }
 476
 477                virtual bool ExpandBuffers( TPacketAccumulator *AInAccumulator, TPacketAccumulator *AOutAccumulator, int &ASize, int &APosition, bool &AIsValid, bool &AIsCorruptedPacket ) override
 478                { 
 479                        APosition = ( APosition + 7 ) / 8;
 480                        APosition *= 8;
 481
 482                        int ABytesSize = Bytes._BytesSize;
 483                        if( !ABytesSize )
 484                                return false;
 485
 486                        unsigned char *ABytes = Bytes._Bytes;
 487                        //  if( not AInAccumulator.FindSkipBytes( ABytesSize * 2, @FDoubledBytes[ 0 ], ASkipped )) then
 488                        //    Exit( False );
 489
 490                        int AFindPosition;
 491
 492                        if( !AInAccumulator->FindBytes( ABytesSize * 2, FDoubledBytes.begin(), AFindPosition ))
 493                        {
 494                                AIsValid = false;
 495                                return false;
 496                        }
 497
 498                        AFindPosition -= ABytesSize * 2;
 499                        AInAccumulator->SkipBytes( AFindPosition );
 500
 501                        APosition += ABytesSize * 2 * 8;
 502
 503                        //  Dec( ASize, AFindPosition );
 504
 505                        //  if( ASize <= ABytesSize * 2 ) then
 506                        //    Exit( False );
 507
 508                        //  ANewDebugBuf := AInAccumulator.GetAsBuffer();
 509
 510                        if( !AInAccumulator->FindBytes( ABytesSize, ABytes, ABytesSize * 2, ASize - ABytesSize * 2, AFindPosition ))
 511                                return false;
 512
 513                        //  ANewDebugBuf := AInAccumulator.GetAsBuffer();
 514//                      AMarkerBuffer := TSLBlockBuffer.CreateData( ABytes, ABytesSize );
 515
 516                        //  if( not AInAccumulator.FindBytes( ABytesSize, ABytes, ASize - ABytesSize * 2, AFindPosition )) then
 517                        //    Exit( False );
 518
 519                        AOutAccumulator->append( ABytes, ABytesSize );
 520                        AOutAccumulator->append( ABytes, ABytesSize );
 521
 522                        for(;;)
 523                        {
 524                                Mitov::SimpleList<unsigned char>        ABuffer;
 525                                ABuffer.AddCount( AFindPosition );
 526//                              ABuffer := TSLBlockBuffer.CreateSize( AFindPosition );
 527                                AInAccumulator->ExtractBytes( AFindPosition, ABuffer );
 528                                AOutAccumulator->append( ABuffer, AFindPosition );
 529
 530                                unsigned char ACount;
 531                                AInAccumulator->ExtractBytes( 1, &ACount );
 532
 533                                for( int i = 0; i <= ACount; ++i )
 534                                        AOutAccumulator->append( ABytes, ABytesSize );
 535
 536                                ASize = ABytesSize * ACount + 1;
 537
 538                                if( ! AInAccumulator->FindBytes( ABytesSize, ABytes, AFindPosition, ASize - AFindPosition, AFindPosition ))
 539                                        return true;
 540
 541                        }
 542
 543                        return true;
 544                }
 545
 546        public:
 547                void SkipHeader( TPacketAccumulator *AAccumulator ) 
 548                {
 549                        AAccumulator->SkipBytes( Bytes._BytesSize * 2 );
 550                }
 551
 552        };
 553//---------------------------------------------------------------------------
 554        class PacketHeadMarkerBinaryElement : public PacketMarkerBinaryElement
 555        {
 556        public:
 557                virtual int      GetSize( bool &Alligned ) override
 558                { 
 559                        Alligned = true;
 560                        return Bytes._BytesSize * 2 * 8; 
 561                }
 562
 563                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override
 564                {
 565                        if( Bytes._BytesSize == 0 )
 566                                return;
 567
 568                        if( AOffset )
 569                        {
 570                                ++AData;
 571                                AOffset = 0;
 572                        }
 573
 574                        memcpy( AData, Bytes._Bytes, Bytes._BytesSize );
 575                        AData += Bytes._BytesSize;
 576
 577                        memcpy( AData, Bytes._Bytes, Bytes._BytesSize );
 578                        AData += Bytes._BytesSize;
 579                }
 580
 581                virtual bool Expand( unsigned char *AInBuffer, unsigned char *AOutBuffer, int &ASize ) override
 582                {
 583                        if( Bytes._BytesSize == 0 )
 584                                return false;
 585
 586//                      memcpy( AOutBuffer, AInBuffer, ASize );
 587//                      return true;
 588
 589                        unsigned char *ABytes = Bytes._Bytes;
 590                        int ABytesSize = Bytes._BytesSize;
 591
 592                        int AOutSize = ABytesSize * 2;
 593
 594                        memcpy( AOutBuffer, AInBuffer, AOutSize );
 595                        AOutBuffer += AOutSize;
 596                        AInBuffer += AOutSize;
 597
 598                        int i = AOutSize;
 599                        for( ; i < ASize - ABytesSize * 2 + 1; ++i )
 600                        {
 601                                if( memcmp( AInBuffer, ABytes, ABytesSize ) == 0 )
 602                                        if( memcmp( AInBuffer + ABytesSize, ABytes, ABytesSize ) == 0 )
 603                                        {
 604                                                memcpy( AOutBuffer, AInBuffer, ABytesSize );
 605                                                AInBuffer += ABytesSize * 2;
 606
 607//                                              Serial.println( "START" );
 608                                                AOutBuffer += ABytesSize;
 609                                                unsigned char ACount = 0;
 610                                                i += ABytesSize;
 611                                                for( ; i < ASize - ABytesSize + 1; i += ABytesSize )
 612                                                {
 613                                                        if( memcmp( AInBuffer, ABytes, ABytesSize ) != 0 )
 614                                                                break;
 615
 616//                                                      Serial.println( "INC" );
 617                                                        ++ACount;
 618                                                        if( ACount == 255 )
 619                                                                break;
 620
 621                                                        AInBuffer += ABytesSize;
 622                                                }
 623
 624                                                if( ACount == *ABytes )
 625                                                {
 626                                                        if( ACount > 0 )
 627                                                        {
 628//                                                              Serial.println( "DEC" );
 629                                                                --ACount;
 630                                                                AInBuffer -= ABytesSize;
 631                                                                i -= ABytesSize;
 632                                                        }
 633                                                }
 634
 635                                                *AOutBuffer++ = ACount;
 636                                                AOutSize += ABytesSize + 1;
 637                                                continue;
 638                                        }
 639
 640                                *AOutBuffer++ = *AInBuffer++;
 641//Serial.print( "++AOutSize" );
 642                                ++AOutSize;
 643                        }
 644
 645                        int ACorrection = ASize - i;
 646                        memcpy( AOutBuffer, AInBuffer, ACorrection );
 647//                      *AOutBuffer = 5;
 648
 649//                      Serial.print( "ADebugCount : " );
 650//                      Serial.println( ADebugCount );
 651
 652//                      Serial.print( "AOutSize : " );
 653//                      Serial.println( AOutSize );
 654
 655//                      Serial.print( "TEST : " );
 656//                      Serial.println( ACorrection );
 657//                      Serial.println( i );
 658
 659                        ASize = AOutSize + ACorrection;
 660                        return true; 
 661                }
 662
 663        };
 664//---------------------------------------------------------------------------
 665        class PacketDigitalBinaryElement : public BasicTypedPacketSinkElement<bool>
 666        {
 667        public:
 668                virtual int      GetSize( bool &Alligned ) override
 669                { 
 670                        Alligned = false;
 671                        return 1; 
 672                }
 673
 674                virtual void GetData( unsigned char *ADataStart, unsigned char *&AData, unsigned char &AOffset ) override
 675                {
 676                        *AData &= 0xFF >> ( 8 - AOffset ); // Zero the upper bits
 677                        if( FValue )
 678                                *AData |= 1 << AOffset; // Set the bit
 679
 680                        ++AOffset;
 681                        if( AOffset == 8 )
 682                        {
 683                                AOffset = 0;
 684                                ++AData;
 685                        }
 686                }
 687        };
 688//---------------------------------------------------------------------------
 689        class Packet : public Mitov::CommonSource, public Mitov::ClockingSupport
 690        {
 691                typedef Mitov::CommonSource inherited;
 692
 693        public:
 694                Mitov::SimpleObjectList<BasicPacketElement*>    Elements;
 695
 696                bool    OnlyModified = false;
 697
 698                PacketHeadMarkerBinaryElement   HeadMarker;
 699                PacketChecksumElement                   Checksum;
 700
 701        protected:
 702                int     FBufferSize;
 703
 704                unsigned char *FBuffers[ 2 ];
 705                Mitov::SimpleList<BasicPacketElement*>  FAllElements;
 706
 707        protected:
 708                virtual void DoClockReceive( void *_Data ) override
 709                {
 710//                      Serial.println( "++++++" );
 711                        int AElementCount = FAllElements.size();
 712                        if( OnlyModified )
 713                        {
 714                                bool AModified = false;
 715                                for( int i = 0; i < AElementCount; ++i )
 716                                        if( FAllElements[ i ]->GetIsModified() )
 717                                        {
 718                                                AModified = true;
 719                                                break;
 720                                        }
 721
 722                                if( !AModified )
 723                                        return;
 724                        }
 725                        else
 726                        {
 727                                for( int i = 0; i < AElementCount; ++i )
 728                                        if( ! FAllElements[ i ]->GetIsPopulated() )
 729                                                return;
 730
 731                        }
 732
 733                        unsigned char *ADataPtr = FBuffers[ 0 ];
 734                        unsigned char AOffset = 0;
 735                        for( int i = 0; i < AElementCount; ++i )
 736                        {
 737                                FAllElements[ i ]->GetData( FBuffers[ 0 ], ADataPtr, AOffset );
 738//                              while( AElementSize-- )
 739//                                      OutputPin.Notify( AData++ );
 740
 741
 742                        }
 743
 744                        int ASize = FBufferSize;
 745//                      Serial.println( ASize );
 746                        int ABufferIndex = 0;
 747//                      Serial.println( "--------" );
 748                        for( int i = 0; i < AElementCount; ++i )
 749                        {
 750//                              Serial.println( ABufferIndex & 1 );
 751//                              Serial.println( 1 ^ ( ABufferIndex & 1 ) );
 752                                unsigned char *AInBuffer = FBuffers[ ABufferIndex & 1 ];
 753                                unsigned char *AOutBuffer = FBuffers[ 1 ^ ( ABufferIndex & 1 )];
 754                                if( FAllElements[ i ]->Expand( AInBuffer, AOutBuffer, ASize ))
 755                                        ++ ABufferIndex;
 756                        }
 757
 758                        ADataPtr = FBuffers[ ABufferIndex & 1 ];
 759                        OutputPin.SendValue( Mitov::TDataBlock( ASize, ADataPtr ));
 760
 761//                      Serial.println( ASize );
 762//                      while( ASize-- )
 763//                              OutputPin.Notify( ADataPtr++ );
 764
 765                }
 766
 767        protected:
 768                virtual void SystemLoopBegin( unsigned long currentMicros )
 769                {
 770                        if( !ClockInputPin.IsConnected() )
 771                                DoClockReceive( NULL );
 772
 773//                      delay( 1000 );
 774                        inherited::SystemLoopBegin( currentMicros );
 775                }
 776
 777                virtual void SystemStart()
 778                {
 779                        FBufferSize = 0;
 780                        FAllElements.push_back( &HeadMarker );
 781                        for( int i = 0; i < Elements.size(); ++i )
 782                                FAllElements.push_back( Elements[ i ] );
 783
 784                        FAllElements.push_back( &Checksum );
 785
 786                        for( int i = 0; i < FAllElements.size(); ++i )
 787                        {
 788                                bool AAlligned = false;
 789                                FBufferSize += FAllElements[ i ]->GetSize( AAlligned );
 790//                              Serial.println( FBufferSize );
 791                                if( AAlligned )
 792                                {
 793                                        FBufferSize = ( FBufferSize + 7 ) / 8;
 794                                        FBufferSize *= 8;
 795                                }
 796
 797                        }
 798
 799//                      Serial.println( FBufferSize );
 800
 801                        FBufferSize = ( FBufferSize + 7 ) / 8;
 802                        FBuffers[ 0 ] = new unsigned char[ FBufferSize * 2 ];
 803                        FBuffers[ 1 ] = new unsigned char[ FBufferSize * 2 ];
 804
 805                        inherited::SystemStart();
 806                }
 807
 808/*
 809                virtual ~Packet()
 810                {
 811                        delete []FBuffers[ 1 ];
 812                        delete []FBuffers[ 0 ];
 813                }
 814*/
 815        };
 816//---------------------------------------------------------------------------
 817        class Unpacket : public Mitov::CommonSink
 818        {
 819                typedef Mitov::CommonSink inherited;
 820
 821        public:
 822                Mitov::SimpleObjectList<BasicUnpacketElement*>  Elements;
 823
 824                UnpacketHeadMarkerBinaryElement HeadMarker;
 825                UnpacketChecksumElement                 Checksum;
 826
 827        protected:
 828                TPacketAccumulator      FAccumulator;
 829                int                                     FMinSize = 0;
 830                Mitov::SimpleList<BasicUnpacketElement*>        FAllElements;
 831
 832        protected:
 833                virtual void DoReceive( void *_Data ) override
 834                {
 835                        if( FMinSize == 0 )
 836                                return;
 837
 838//                      Serial.println( "FMinSize" );
 839//                      Serial.println( FMinSize );
 840///                     Serial.println( "T0:" );
 841///                     Serial.println( FAccumulator.size() );
 842                        Mitov::TDataBlock ABlock = *(Mitov::TDataBlock *)_Data;
 843                        while( ABlock.Size-- )
 844                          FAccumulator.push_back( *ABlock.Data++ );
 845
 846///                     Serial.println( FAccumulator.size() );
 847
 848//                      Serial.println( "T1" );
 849
 850                        TPacketAccumulator      AOldAccumulator;
 851                        TPacketAccumulator      *AInAccumulator;
 852                        TPacketAccumulator      ARealOutAccumulator;
 853                        TPacketAccumulator      *AOutAccumulator = &ARealOutAccumulator;
 854                        TPacketAccumulator      *AAccumulator;
 855
 856//                      while( FAccumulator.size() >= FMinSize )
 857                        while( FAccumulator.size() >= FMinSize )
 858                        {
 859//                      Serial.println( "FMinSize" );
 860//                      Serial.println( FMinSize );
 861///                             Serial.println( "T2" );
 862//AOldAccumulator.clear();
 863//AOldAccumulator.append( FAccumulator, FAccumulator.size() );
 864//return;
 865                                AOldAccumulator = FAccumulator;
 866//return;
 867                                AInAccumulator = &FAccumulator;
 868
 869                                AOutAccumulator->clear();
 870                                AAccumulator = &FAccumulator;
 871                                int ASize = FMinSize;
 872                                bool AIsValid = true;
 873
 874                                bool AIsCorruptedPacket = false;
 875                                int APosition = 0;
 876//return;
 877                                for( int i = 0; i < FAllElements.size(); ++i )
 878                                {
 879//                                      Serial.println( "enter" );
 880//                                      Serial.println( FAccumulator.size() );
 881                                        if( FAllElements[ i ]->ExpandBuffers( AInAccumulator, AOutAccumulator, ASize, APosition, AIsValid, AIsCorruptedPacket ))
 882                                        {
 883//                                              Serial.println( "ExpandBuffers" );
 884//return;
 885                                                if( AIsCorruptedPacket )
 886                                                {
 887                                                        FAccumulator = AOldAccumulator;
 888                                                        HeadMarker.SkipHeader( &FAccumulator );
 889                                                        break;
 890                                                }
 891
 892                                                AAccumulator = AOutAccumulator;
 893                                                if( AAccumulator == &FAccumulator )
 894                                                {
 895//                                                      Serial.println( "AAccumulator == &FAccumulator" );
 896                                                        AInAccumulator = AOutAccumulator;
 897                                                        AOutAccumulator->clear();
 898                                                }
 899
 900                                                else
 901                                                        swap( AInAccumulator, AOutAccumulator );
 902
 903                                        }
 904
 905//                                      Serial.println( "Step1" );
 906                                        if( AIsCorruptedPacket )
 907                                        {
 908//                                              Serial.println( "AIsCorruptedPacket" );
 909                                                FAccumulator = AOldAccumulator;
 910                                                HeadMarker.SkipHeader( &FAccumulator );
 911                                                break;
 912                                        }
 913
 914                                        if( ! AIsValid )
 915                                        {
 916                                                FAccumulator = AOldAccumulator;
 917                                                return;
 918                                        }
 919
 920                                }
 921
 922//                              Serial.println( "ExpandBuffers OUT" );
 923                                if( AIsCorruptedPacket )
 924                                {
 925//                                      Serial.println( "AIsCorruptedPacket SKIPPING" );
 926//return;
 927//                                      if( ! HeadMarker.Bytes._BytesSize )
 928                                                FAccumulator.SkipBytes( 1 );
 929
 930                                        continue;
 931                                }
 932
 933                                if( AAccumulator->size() < FMinSize )
 934                                {
 935                                        FAccumulator = AOldAccumulator;
 936                                        return;
 937                                }
 938
 939                                if( ASize < FMinSize )
 940                //      for AItem in FAllElements do
 941                //        if( not AItem.CanProcess( AAccumulator )) then
 942                                {
 943                                        FAccumulator = AOldAccumulator;
 944                                        return;
 945                                }
 946
 947//                              Serial.println( "PROCESS" );
 948                                unsigned char AOffset = 0;
 949                                for( int i = 0; i < FAllElements.size(); ++i )
 950                                {
 951                                        if( ! FAllElements[ i ]->Process( AAccumulator, AOffset ))
 952                                                break;
 953
 954//break;
 955                                }
 956
 957
 958//                              Serial.println( "exit" );
 959//                              Serial.println( FAllElements.size() );
 960//                              return;
 961
 962                        }
 963                }
 964
 965                virtual void SystemStart() override
 966                {
 967//                      Serial.println( "FMinSize" );
 968                        FAllElements.push_back( &HeadMarker );
 969
 970                        for( int i = 0; i < Elements.size(); ++i )
 971                                FAllElements.push_back( Elements[ i ] );
 972
 973                        FAllElements.push_back( &Checksum );
 974
 975                        FMinSize = 0;
 976                        for( int i = 0; i < FAllElements.size(); ++i )
 977                        {
 978                                  bool AAlligned = false;
 979                                  FMinSize += FAllElements[ i ]->Start( AAlligned );
 980                                  if( AAlligned )
 981                                  {
 982                                          FMinSize = ( FMinSize + 7 ) / 8;
 983                                          FMinSize = FMinSize * 8;
 984                                  }
 985                        }
 986
 987                        FMinSize = ( FMinSize + 7 ) / 8;
 988
 989//                      Serial.println( "FMinSize" );
 990//                      Serial.println( FMinSize );
 991
 992                        inherited::SystemStart();
 993                }
 994        };
 995//---------------------------------------------------------------------------
 996
 997}
 998
 999#endif