libraries / Mitov / Mitov.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_h
  11#define _MITOV_h
  12
  13#include <OpenWire.h>
  14
  15#if defined( VISUINO_TEENSY_3_0 ) || defined( VISUINO_TEENSY_3_1 ) || defined( VISUINO_TEENSY_LC )
  16  #define VISUINO_TEENSY
  17#endif
  18
  19#if defined( VISUINO_ARDUINO_DUE ) || defined( VISUINO_LINKIT_ONE ) || defined( VISUINO_TEENSY ) || defined( VISUINO_TEENSY_2_0 ) || defined( VISUINO_TEENSY_2_0_PP )
  20  #define NO_SERIAL_FORMAT
  21#endif
  22
  23#if defined( VISUINO_ESP8266 )
  24#define V_FMOD(a,b) (a - b * floor(a / b))
  25#else
  26#define V_FMOD(a,b) fmod(a,b)
  27#endif
  28
  29#ifndef PWMRANGE
  30  #define PWMRANGE 255
  31#endif
  32
  33#define MAKE_CALLBACK(A) (OpenWire::Component *)this, (OpenWire::TOnPinReceive)( void (OpenWire::Component::*) ( void *_Data ) )&A
  34
  35namespace Mitov
  36{
  37//---------------------------------------------------------------------------
  38#ifdef VISUINO_ESP8266
  39
  40template<typename T> const T& MitovMin(const T& a, const T& b)
  41{
  42    return (b < a) ? b : a;
  43}
  44
  45template<typename T> const T& MitovMax(const T& a, const T& b)
  46{
  47    return (b > a) ? b : a;
  48}
  49
  50#else
  51        #define MitovMin min
  52        #define MitovMax max
  53#endif
  54//---------------------------------------------------------------------------
  55        struct TDataBlock
  56        {
  57        public:
  58                uint32_t        Size;
  59                byte *Data;
  60
  61        public:
  62                TDataBlock( uint32_t ASize, void *AData ) :
  63                        Size( ASize), 
  64                        Data( (byte *)AData )
  65                {
  66                }
  67
  68        };
  69//---------------------------------------------------------------------------
  70        const bool GBooleanConst[] = { false, true };
  71//---------------------------------------------------------------------------
  72        #pragma pack(push, 1)
  73        struct TColor
  74        {
  75        public:
  76                uint8_t Red;
  77                uint8_t Green;
  78                uint8_t Blue;
  79                uint8_t Alpha = 0;
  80
  81        public:
  82                void SetValue( const long AValue )
  83                {
  84                        *((long *)this) = AValue & 0xFFFFFF;
  85//                      Blue = ( AValue >> 16 ) & 0xFF;
  86//                      Green = ( AValue >> 8 ) & 0xFF;
  87//                      Red = AValue & 0xFF;
  88//                      Alpha = 0;
  89                }
  90
  91                void operator =( const long AValue )
  92                {
  93                        SetValue( AValue );
  94                }
  95
  96                bool operator ==( const TColor other )
  97                {
  98                        return *((long *)this) == *((long *)&other);
  99                }
 100
 101                operator long()
 102                {
 103                        return *((long *)this);
 104                }
 105
 106        public:
 107                String ToString()
 108                {
 109                        return  String( "(" ) + 
 110                                        String((int)Red ) + "," +
 111                                        String((int)Green ) + "," +
 112                                        String((int)Blue ) + ")";
 113                }
 114
 115        public:
 116                TColor( long AValue = 0 )
 117                {
 118                        SetValue( AValue );
 119                }
 120
 121                TColor( unsigned char ARed, unsigned char AGreen, unsigned char ABlue ) :
 122                        Red( ARed ),
 123                        Green( AGreen ),
 124                        Blue( ABlue )
 125                {
 126                }
 127
 128                TColor( long AValue, bool ) // For Windows BGR support
 129                {
 130                        Red = ( AValue >> 16 ) & 0xFF;
 131                        Green = ( AValue >> 8 ) & 0xFF;
 132                        Blue = AValue & 0xFF;
 133                }
 134        };
 135        #pragma pack(pop)
 136//---------------------------------------------------------------------------
 137        const double HoursPerDay                = 24;
 138        const double MinsPerHour                = 60;
 139        const double SecsPerMin                 = 60;
 140        const double MSecsPerSec                = 1000;
 141        const double MinsPerDay                 = HoursPerDay * MinsPerHour;
 142        const double SecsPerDay                 = MinsPerDay * SecsPerMin;
 143        const double SecsPerHour                = SecsPerMin * MinsPerHour;
 144        const double MSecsPerDay                = SecsPerDay * MSecsPerSec;
 145        const int32_t   IMSecsPerDay    = MSecsPerDay;
 146// Days between 1/1/0001 and 12/31/1899
 147//      const double DateDelta                  = 693594;
 148//---------------------------------------------------------------------------
 149        const uint16_t MonthDays[2][12] =
 150        {
 151                {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 152                {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
 153        };
 154//---------------------------------------------------------------------------
 155        class TDateTime
 156        {
 157        public:
 158                int32_t Time; // Number of milliseconds since midnight
 159                int32_t Date; // One plus number of days since 1/1/0001
 160
 161        protected:
 162                inline void DivMod( int32_t Dividend, uint16_t Divisor, uint16_t &Result, uint16_t &Remainder )
 163                {
 164                        Result = Dividend / Divisor;
 165                        Remainder = Dividend % Divisor;
 166                }
 167
 168        public:
 169                void DecodeTime( uint16_t &Hour, uint16_t &Min, uint16_t &Sec, uint16_t &MSec )
 170                {
 171                        uint16_t        MinCount, MSecCount;
 172
 173                        DivMod( Time, SecsPerMin * MSecsPerSec, MinCount, MSecCount );
 174                        DivMod( MinCount, MinsPerHour, Hour, Min );
 175                        DivMod( MSecCount, MSecsPerSec, Sec, MSec );
 176                }
 177
 178                bool IsLeapYear( uint16_t Year )
 179                {
 180                        return (Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0));
 181                }
 182
 183                bool DecodeDateFully( uint16_t &Year, uint16_t &Month, uint16_t &Day, uint16_t &DOW )
 184                {
 185                        const uint32_t D1 = 365;
 186                        const uint32_t D4 = D1 * 4 + 1;
 187                        const uint32_t D100 = D4 * 25 - 1;
 188                        const uint32_t D400 = D100 * 4 + 1;
 189
 190/*
 191                var
 192                  Y, M, D, I: Word;
 193                  T: Integer;
 194                  DayTable: PDayTable;
 195                begin
 196*/
 197                        int32_t T = Date;
 198                        if( T <= 0 )
 199                        {
 200                                Year = 0;
 201                                Month = 0;
 202                                Day = 0;
 203                                DOW = 0;
 204                                return( false );
 205                        }
 206
 207                        else
 208                        {
 209                                DOW = T % 7 + 1;
 210                                --T;
 211                                uint16_t Y = 1;
 212                                while( T >= D400 )
 213                                {
 214                                        T -= D400;
 215                                        Y += 400;
 216                                }
 217
 218                                uint16_t D, I;
 219                                DivMod( T, D100, I, D );
 220                                if( I == 4 )
 221                                {
 222                                        -- I;
 223                                        D -= D100;
 224                                }
 225
 226                                Y += I * 100;
 227                                DivMod(D, D4, I, D);
 228
 229                                Y += I * 4;
 230                                DivMod(D, D1, I, D);
 231
 232                                if( I == 4 )
 233                                {
 234                                        --I;
 235                                        D += D1;
 236                                }
 237
 238                                Y += I;
 239                                bool Result = IsLeapYear(Y);
 240
 241                                const uint16_t *DayTable = MonthDays[Result];
 242                                uint16_t M = 0; // The C++ Day table is zero indexed!
 243                                for(;;)
 244                                {
 245                                        I = DayTable[M];
 246                                        if( D < I )
 247                                                break;
 248
 249                                        D -= I;
 250                                        ++ M;
 251                                }
 252
 253                                Year = Y;
 254                                Month = M + 1;
 255                                Day = D + 1;
 256
 257                return Result;
 258                        }
 259                }
 260
 261                bool TryEncodeDate( uint16_t Year, uint16_t Month, uint16_t Day )
 262                {
 263                        const uint16_t *DayTable = MonthDays[IsLeapYear(Year)];
 264                        if( (Year >= 1) && (Year <= 9999) && (Month >= 1) && (Month <= 12) &&
 265                                (Day >= 1) && (Day <= DayTable[Month]))
 266                        {
 267                                for( int i = 1; i < Month; i ++ )
 268                                        Day += DayTable[ i - 1 ];
 269
 270                                int I = Year - 1;
 271//                              Serial.println( I );
 272//                              Serial.println( Day );
 273                                Date = ((uint32_t)I) * 365 + (int)( I / 4 ) - (int)( I / 100 ) + (int)( I / 400 ) + (uint32_t)Day;
 274//                              Serial.println( Date );
 275                                return true;
 276                        }
 277
 278                        return false;
 279                }
 280
 281                bool TryEncodeTime( uint16_t Hour, uint16_t Min, uint16_t Sec, uint16_t MSec )
 282                {
 283                        if ((Hour < HoursPerDay) && (Min < MinsPerHour) && (Sec < SecsPerMin) && (MSec < MSecsPerSec))
 284                        {
 285                                Time =  (Hour * (MinsPerHour * SecsPerMin * MSecsPerSec))
 286                                          + (Min * SecsPerMin * MSecsPerSec)
 287                                          + (Sec * MSecsPerSec)
 288                                          +  MSec;
 289//                              Date = DateDelta; // This is the "zero" day for a TTimeStamp, days between 1/1/0001 and 12/30/1899 including the latter date
 290                                Date = 0; // This is the "zero" day for a TTimeStamp, days between 1/1/0001 and 12/30/1899 including the latter date
 291                                return true;
 292                        }
 293
 294                        return false;
 295                }
 296
 297                bool TryEncodeDateTime( uint16_t AYear, uint16_t AMonth, uint16_t ADay, uint16_t AHour, uint16_t AMinute, uint16_t ASecond, uint16_t AMilliSecond )
 298                {
 299                        bool Result = TryEncodeDate( AYear, AMonth, ADay );
 300                        if( Result )
 301                        {
 302                                TDateTime LTime;
 303                                Result = LTime.TryEncodeTime( AHour, AMinute, ASecond, AMilliSecond );
 304                                if( Result )
 305                                        Time = LTime.Time; 
 306
 307                        }
 308
 309            return Result;
 310                }
 311
 312                void DecodeDateTime( uint16_t &AYear, uint16_t &AMonth, uint16_t &ADay, uint16_t &AHour, uint16_t &AMinute, uint16_t &ASecond, uint16_t &AMilliSecond )
 313                {
 314                        uint16_t AWeekDay;
 315                        DecodeDateTime( AYear, AMonth, ADay, AWeekDay, AHour, AMinute, ASecond, AMilliSecond );
 316                }
 317
 318                void DecodeDateTime( uint16_t &AYear, uint16_t &AMonth, uint16_t &ADay, uint16_t &AWeekDay, uint16_t &AHour, uint16_t &AMinute, uint16_t &ASecond, uint16_t &AMilliSecond )
 319                {
 320                        DecodeDateFully( AYear, AMonth, ADay, AWeekDay );
 321                        DecodeTime( AHour, AMinute, ASecond, AMilliSecond );
 322                }
 323
 324                String ToString()
 325                {
 326                        uint16_t AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond;
 327                        DecodeDateTime( AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond );
 328                        char ABuffer[ 6 + 4 + 5 * 2 + 3 + 2 + 1 ];
 329                        sprintf( ABuffer, "(%04d.%02d.%02d %02d:%02d:%02d.%03d)", AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond );
 330                        return ABuffer;
 331                }
 332
 333        public:
 334                bool operator == ( TDateTime &AOther )
 335                {
 336                        if( Date != AOther.Date )
 337                                return false;
 338
 339                        return ( Time == AOther.Time );
 340                }
 341
 342                bool operator != ( TDateTime &AOther )
 343                {
 344                        if( Date != AOther.Date )
 345                                return true;
 346
 347                        return ( Time != AOther.Time );
 348                }
 349
 350                bool operator <= ( TDateTime &AOther )
 351                {
 352                        if( Date > AOther.Date )
 353                                return false;
 354
 355                        if( Date < AOther.Date )
 356                                return true;
 357
 358                        return ( Time <= AOther.Time );
 359                }
 360
 361                bool operator >= ( TDateTime &AOther )
 362                {
 363                        if( Date > AOther.Date )
 364                                return true;
 365
 366                        if( Date < AOther.Date )
 367                                return false;
 368
 369                        return ( Time >= AOther.Time );
 370                }
 371
 372                bool operator < ( TDateTime &AOther )
 373                {
 374                        if( Date > AOther.Date )
 375                                return false;
 376
 377                        if( Date < AOther.Date )
 378                                return true;
 379
 380                        return ( Time < AOther.Time );
 381                }
 382
 383                bool operator > ( TDateTime &AOther )
 384                {
 385                        if( Date > AOther.Date )
 386                                return true;
 387
 388                        if( Date < AOther.Date )
 389                                return false;
 390
 391                        return ( Time > AOther.Time );
 392                }
 393
 394        public:
 395                TDateTime() :
 396                        Date( 693594 ),
 397                        Time( 0 )
 398                {
 399                }
 400
 401                TDateTime( int32_t ADate, int32_t ATime ) :
 402                        Date( ADate ),
 403                        Time( ATime )
 404                {
 405                }
 406
 407                TDateTime( uint32_t ADummy ) :
 408                        Date( 693594 ),
 409                        Time( 0 )
 410                {
 411                }
 412
 413        };
 414//---------------------------------------------------------------------------
 415        template <typename T> void swap ( T& a, T& b )
 416        {
 417                T c(a); a=b; b=c;
 418        }
 419//---------------------------------------------------------------------------
 420        class Bytes
 421        {
 422        public:
 423                unsigned char *_Bytes;
 424                unsigned int  _BytesSize = 0;
 425
 426        };
 427//---------------------------------------------------------------------------
 428        class CommonSource : public OpenWire::Component
 429        {
 430        public:
 431                OpenWire::SourcePin     OutputPin;
 432
 433        };
 434//---------------------------------------------------------------------------
 435        class EnabledComponent : public OpenWire::Component
 436        {
 437        public:
 438                bool    Enabled = true;
 439
 440        };
 441//---------------------------------------------------------------------------
 442        class ClockingSupport : public OpenWire::Object
 443        {
 444        public:
 445                OpenWire::ConnectSinkPin        ClockInputPin;
 446
 447        protected:
 448                virtual void DoClockReceive( void *_Data ) = 0;
 449
 450        public:
 451                ClockingSupport()
 452                {
 453                        ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ClockingSupport::DoClockReceive );
 454                }
 455
 456        };
 457//---------------------------------------------------------------------------
 458        class CommonEnableSource : public CommonSource
 459        {
 460    public:
 461        bool Enabled = true;
 462
 463        };
 464//---------------------------------------------------------------------------
 465        class CommonSink : public OpenWire::Component
 466        {
 467        public:
 468                OpenWire::SinkPin       InputPin;
 469
 470        protected:
 471                virtual void DoReceive( void *_Data ) = 0;
 472
 473        public:
 474                CommonSink()
 475                {
 476                        InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&CommonSink::DoReceive );
 477                }
 478        };
 479//---------------------------------------------------------------------------
 480        class CommonFilter : public CommonSource
 481        {
 482        public:
 483                OpenWire::SinkPin       InputPin;
 484
 485        protected:
 486                virtual void DoReceive( void *_Data ) = 0;
 487
 488        public:
 489                CommonFilter()
 490                {
 491                        InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&CommonFilter::DoReceive );
 492                }
 493        };
 494//---------------------------------------------------------------------------
 495        class CommonEnableFilter : public CommonFilter
 496        {
 497    public:
 498        bool Enabled = true;
 499
 500        };
 501//---------------------------------------------------------------------------
 502        class CommonImplementedEnableFilter : public CommonEnableFilter
 503        {
 504        protected:
 505                virtual void ReceiveValue( void *_Data ) = 0;
 506
 507                virtual void DoReceive( void *_Data ) override
 508        {
 509            if( ! Enabled )
 510            {
 511                            OutputPin.Notify( _Data );
 512                return;
 513            }
 514
 515                        ReceiveValue( _Data );
 516        }
 517
 518        };
 519//---------------------------------------------------------------------------
 520        template<typename T_IN, typename T_OUT> class CommonTypedInOutFilter : public CommonImplementedEnableFilter
 521    {
 522        protected:
 523        virtual T_OUT FilterValue( T_IN AValue ) = 0;
 524
 525        protected:
 526                virtual void ReceiveValue( void *_Data ) override
 527        {
 528                        T_IN AInValue = *(T_IN*)_Data;
 529
 530            T_OUT AOutValue = FilterValue( AInValue );
 531
 532                        OutputPin.Notify( &AOutValue );
 533        }
 534
 535    };
 536//---------------------------------------------------------------------------
 537        template<typename T> class CommonTypedFilter : public CommonTypedInOutFilter<T, T>
 538    {
 539    };
 540//---------------------------------------------------------------------------
 541        class CommonGenerator : public CommonSource
 542        {
 543                typedef Mitov::CommonSource inherited;
 544
 545        protected:
 546                unsigned long FLastTime = 0;
 547                unsigned long FPeriod = 0;
 548
 549        public:
 550                bool    Enabled = true;
 551                float   Frequency = 1.0;
 552
 553        public:
 554                void SetFrequency( float AValue )
 555                {
 556                        if( Frequency == AValue )
 557                                return;
 558
 559                        Frequency = AValue;
 560                        CalculateFields();
 561                }
 562
 563        protected:
 564                virtual void Clock() = 0;
 565
 566        protected:
 567                virtual void CalculateFields()
 568                {
 569                        FPeriod = ( (( 1 / Frequency ) * 1000000 ) + 0.5 );
 570                }
 571
 572                virtual void SystemLoopBegin( unsigned long currentMicros ) override
 573                {
 574                        while( currentMicros - FLastTime >= FPeriod )
 575                        {
 576                                if( Enabled )
 577                                        Clock();
 578
 579                                FLastTime += FPeriod;
 580                        }
 581
 582                        inherited::SystemLoopBegin( currentMicros );
 583                }
 584
 585                virtual void SystemStart() override
 586                {
 587                        inherited::SystemStart();
 588                        FLastTime = micros();
 589                }
 590
 591        };
 592//---------------------------------------------------------------------------
 593        template<typename T> class ValueSource : public Mitov::CommonSource
 594        {
 595                typedef Mitov::CommonSource inherited;
 596
 597        public:
 598                OpenWire::SinkPin       ClockInputPin;
 599
 600        public:
 601                T Value;
 602
 603        protected:
 604                virtual void SystemStart()
 605                {
 606                        inherited::SystemStart();
 607                        OutputPin.Notify( &Value );
 608                }
 609
 610                void DoClockReceive( void *_Data )
 611                {
 612                        OutputPin.Notify( &Value );
 613                }
 614
 615        public:
 616                ValueSource( T AValue ) :
 617                        Value( AValue )
 618                {
 619                        ClockInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ValueSource::DoClockReceive );
 620                }
 621
 622        };
 623//---------------------------------------------------------------------------
 624        template<typename T> class BindableValueSource : public Mitov::ValueSource<T>
 625        {
 626                typedef Mitov::ValueSource<T> inherited;
 627
 628        protected:
 629                T OldValue;
 630
 631        protected:
 632                virtual void SystemInit()
 633                {
 634                        inherited::SystemInit();
 635                        OldValue = inherited::Value;
 636                }
 637
 638                virtual void SystemLoopBegin( unsigned long currentMicros )
 639                {
 640                        if( inherited::Value == OldValue )
 641                                return;
 642
 643                        OldValue = inherited::Value;
 644                        inherited::OutputPin.Notify( &OldValue );
 645                }
 646
 647        public:
 648                BindableValueSource( T AValue ) :
 649                        inherited( AValue ),
 650                        OldValue( AValue )
 651                {
 652                }
 653
 654        };
 655//---------------------------------------------------------------------------
 656        template<typename T, typename T_OUT> class BasicMultiInput : public Mitov::CommonSource
 657        {
 658                typedef Mitov::CommonSource     inherited;
 659
 660        protected:
 661                bool    FModified = false;
 662                T_OUT   FLastOutput;
 663
 664        protected:
 665                void DoReceive( void *_Data )
 666                {
 667                        FModified = true;
 668                }
 669
 670        protected:
 671                virtual T_OUT CalculateOutput() = 0;
 672
 673                inline void CallCalculateSendOutput( bool AFromStart ) // Work around compiler bug
 674                {
 675                        CalculateSendOutput( AFromStart );
 676                }
 677
 678                virtual void CalculateSendOutput( bool AFromStart )
 679                {
 680//                      Serial.println( "CalculateSendOutput+++" );
 681                        T_OUT AValue = CalculateOutput();
 682//                      Serial.println( AValue );
 683                        if( ! AFromStart )
 684                                if( FLastOutput == AValue )
 685                                        return;
 686
 687                        OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility!
 688                        FLastOutput = AValue;
 689
 690                        FModified = false;
 691                }
 692
 693                virtual void SystemStart()
 694                {
 695                        CalculateSendOutput( true );
 696                }
 697
 698                virtual void SystemLoopEnd()
 699                {
 700                        if( FModified )
 701                                CalculateSendOutput( false );
 702
 703                }
 704
 705        };
 706//---------------------------------------------------------------------------
 707        template<typename T, typename T_OUT, int C_NUM_INPUTS> class BasicCommonMultiInput : public Mitov::BasicMultiInput<T, T_OUT>
 708        {
 709                typedef Mitov::BasicMultiInput<T, T_OUT>        inherited;
 710
 711        public:
 712                OpenWire::VlaueSinkPin<T> InputPins[ C_NUM_INPUTS ];
 713
 714        protected:
 715                virtual void SystemInit()
 716                {
 717                        inherited::SystemInit();
 718
 719                        for( int i = 0; i < C_NUM_INPUTS; ++i )
 720                                InputPins[ i ].SetCallback( this, (OpenWire::TOnPinReceive)&BasicCommonMultiInput::DoReceive );
 721
 722                }
 723        };
 724//---------------------------------------------------------------------------
 725        template<typename T, int C_NUM_INPUTS> class CommonMultiInput : public Mitov::BasicCommonMultiInput<T,T, C_NUM_INPUTS>
 726        {
 727                typedef Mitov::BasicCommonMultiInput<T,T, C_NUM_INPUTS> inherited;
 728
 729        };
 730//---------------------------------------------------------------------------
 731        template<typename T, int C_NUM_INPUTS> class CommonClockedMultiInput : public Mitov::CommonMultiInput<T, C_NUM_INPUTS>, public ClockingSupport
 732        {
 733                typedef Mitov::CommonMultiInput<T, C_NUM_INPUTS>        inherited;
 734
 735        protected:
 736                virtual void CalculateSendOutput( bool AFromStart )
 737                {
 738                        if( ClockInputPin.IsConnected() )
 739                                return;
 740
 741                        inherited::CalculateSendOutput( AFromStart );
 742/*
 743                        T_OUT AValue = CalculateOutput();
 744//                      Serial.println( AValue );
 745                        if( ! AFromStart )
 746                                if( FLastOutput == AValue )
 747                                        return;
 748
 749                        OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility!
 750                        FLastOutput = AValue;
 751
 752                        FModified = false;
 753*/
 754                }
 755
 756        protected:
 757                virtual T CalculateOutput() = 0;
 758
 759                void DoClockReceive( void *_Data )
 760                {
 761                        T AValue = CalculateOutput();
 762//                      if( FLastOutput == AValue )
 763//                              return;
 764
 765                        inherited::OutputPin.SendValue( AValue ); // Use Send Value for String Compatibility!
 766                        inherited::FLastOutput = AValue;
 767
 768                        inherited::FModified = false;
 769                }
 770
 771        };
 772//---------------------------------------------------------------------------
 773        class DigitalInput : public CommonSource
 774        {
 775                typedef Mitov::CommonSource     inherited;
 776
 777        public:
 778                uint8_t PinNumber;
 779
 780
 781        protected:
 782                virtual void SystemInit()
 783                {
 784                        inherited::SystemInit();
 785                        pinMode(PinNumber, INPUT);
 786                }
 787
 788                virtual void SystemLoopBegin( unsigned long currentMicros )
 789                {
 790                        bool AValue = digitalRead( PinNumber );
 791                        OutputPin.Notify( &AValue );
 792                }
 793
 794        public:
 795                DigitalInput( int APinNumber ) :
 796                        PinNumber( APinNumber )
 797                {
 798                }
 799        };
 800//---------------------------------------------------------------------------
 801        class DigitalOutput : public CommonSink
 802        {
 803                typedef Mitov::CommonSink       inherited;
 804
 805        protected:
 806                virtual void DoReceive( void *_Data )
 807                {
 808//                      Serial.println( "Test1" );
 809                        if( *(bool*)_Data )
 810                                digitalWrite( PinNumber, HIGH );
 811
 812                        else
 813                                digitalWrite( PinNumber, LOW );
 814
 815                }
 816
 817        public:
 818                uint8_t PinNumber;
 819
 820        protected:
 821                virtual void SystemInit()
 822                {
 823                        inherited::SystemInit();
 824                        pinMode(PinNumber, OUTPUT);
 825                }
 826
 827        public:
 828                DigitalOutput( int APinNumber ) :
 829                        PinNumber( APinNumber )
 830                {
 831                }
 832        };
 833//---------------------------------------------------------------------------
 834        class ArduinoBasicAnalogInputChannel : public CommonSource
 835        {
 836                typedef Mitov::CommonSource     inherited;
 837
 838        protected:
 839                uint8_t FPinNumber;
 840                float   FLastOutput;
 841
 842        public:
 843                ArduinoBasicAnalogInputChannel( int APinNumber ) :
 844                        FPinNumber( APinNumber )
 845                {
 846                }
 847        };
 848//---------------------------------------------------------------------------
 849        class ArduinoAnalogInputChannel : public ArduinoBasicAnalogInputChannel
 850        {
 851                typedef Mitov::ArduinoBasicAnalogInputChannel   inherited;
 852
 853#ifdef VISUINO_TEENSY
 854        protected:
 855                unsigned int FResolution = 0;
 856                float            FDivider = 1023.0;
 857
 858        public:
 859                void SetResolution( unsigned int AResolution )
 860                {
 861                        if( AResolution == FResolution )
 862                                return;
 863
 864                        FResolution = AResolution;
 865                        analogReadRes( FResolution );
 866                        CalculateMultiplier();
 867                }
 868
 869        protected:
 870                void CalculateMultiplier()
 871                {
 872                        FDivider = pow( 2, FResolution ) - 1;
 873                }
 874
 875#endif
 876        protected:
 877                virtual void SystemStart()
 878                {
 879#ifdef VISUINO_TEENSY
 880                        analogReadRes( FResolution );
 881                        FLastOutput = analogRead( FPinNumber ) / FDivider;
 882#else
 883                        FLastOutput = analogRead( FPinNumber ) / 1023.0;
 884#endif
 885                OutputPin.Notify( &FLastOutput );
 886                }
 887
 888                virtual void SystemLoopBegin( unsigned long currentMicros )
 889                {
 890#ifdef VISUINO_TEENSY
 891                        float AValue = analogRead( FPinNumber ) / FDivider;
 892#else
 893                        float AValue = analogRead( FPinNumber ) / 1023.0;
 894#endif
 895                        if( AValue == FLastOutput )
 896                                return;
 897
 898                        FLastOutput = AValue;
 899                        OutputPin.Notify( &AValue );
 900                }
 901
 902        public:
 903                ArduinoAnalogInputChannel( int APinNumber ) :
 904                        inherited( APinNumber )
 905                {
 906                }
 907
 908#ifdef VISUINO_TEENSY
 909                ArduinoAnalogInputChannel( int APinNumber, unsigned int AResolution ) :
 910                        inherited( APinNumber ),
 911                        FResolution( AResolution )
 912                {
 913                        CalculateMultiplier();
 914                }
 915
 916#endif
 917        };
 918//---------------------------------------------------------------------------
 919#ifdef VISUINO_TEENSY
 920//---------------------------------------------------------------------------
 921        class ArduinoTouchAnalogInputChannel : public ArduinoBasicAnalogInputChannel
 922        {
 923                typedef Mitov::ArduinoBasicAnalogInputChannel   inherited;
 924
 925        protected:
 926                virtual void SystemStart()
 927                {
 928                        FLastOutput = touchRead( FPinNumber );
 929                OutputPin.Notify( &FLastOutput );
 930                }
 931
 932                virtual void SystemLoopBegin( unsigned long currentMicros )
 933                {
 934                        float AValue = touchRead( FPinNumber );
 935                        if( AValue == FLastOutput )
 936                                return;
 937
 938                        FLastOutput = AValue;
 939                        OutputPin.Notify( &AValue );
 940                }
 941
 942        public:
 943                ArduinoTouchAnalogInputChannel( int APinNumber ) :
 944                        inherited( APinNumber )
 945                {
 946                }
 947        };
 948//---------------------------------------------------------------------------
 949/*
 950        template <int V_PIN> void SetArduinoAnalogInputResolutionChannel( unsigned int AValue )
 951        {
 952                analogReadRes( AValue );
 953        }
 954*/
 955//---------------------------------------------------------------------------
 956#endif // VISUINO_TEENSY
 957//---------------------------------------------------------------------------
 958        class AnalogOutput : public CommonSink
 959        {
 960                typedef Mitov::CommonSink       inherited;
 961
 962        protected:
 963                virtual void DoReceive( void *_Data )
 964                {
 965                        float AValue = *(float*)_Data;
 966                        analogWrite( PinNumber, ( AValue * PWMRANGE ) + 0.5 );
 967                }
 968
 969        public:
 970                uint8_t PinNumber;
 971
 972        protected:
 973                virtual void SystemInit()
 974                {
 975                        inherited::SystemInit();
 976
 977                        pinMode(PinNumber, OUTPUT);
 978                }
 979
 980        public:
 981                AnalogOutput( int APinNumber ) :
 982                        PinNumber( APinNumber )
 983                {
 984                }
 985        };
 986//---------------------------------------------------------------------------
 987    class ArduinoDigitalChannel : public CommonSource
 988    {
 989                typedef Mitov::CommonSource     inherited;
 990
 991        protected:
 992                uint8_t  FPinNumber;
 993        bool FIsOutput : 1;
 994        bool FIsPullUp : 1;
 995        bool FIsAnalog : 1;
 996                bool FCombinedInOut : 1;
 997                bool FLastOutput : 1;
 998                bool FRawInput : 1;
 999
1000        public:
1001                OpenWire::SinkPin       DigitalInputPin;
1002                OpenWire::SinkPin       AnalogInputPin;
1003
1004        protected:
1005        void PinDirectionsInit()
1006        {
1007                        if( FRawInput )
1008                                return;
1009
1010            if( FIsOutput )
1011                pinMode( FPinNumber, OUTPUT );
1012
1013            else
1014            {
1015                if( FIsPullUp )
1016                    pinMode( FPinNumber, INPUT_PULLUP );
1017
1018                else
1019                    pinMode( FPinNumber, INPUT );
1020            }
1021        }
1022
1023        protected:
1024                virtual void SystemInit()
1025                {
1026                        inherited::SystemInit();
1027
1028            PinDirectionsInit();
1029                }
1030
1031                virtual void SystemStart()
1032                {
1033                        if( FRawInput )
1034                                return;
1035
1036                        FLastOutput = ( digitalRead( FPinNumber ) == HIGH );
1037                OutputPin.SendValue( FLastOutput );
1038                }
1039
1040                virtual void SystemLoopBegin( unsigned long currentMicros )
1041        {
1042            if( !FIsOutput )
1043            {
1044                        bool AValue = ( digitalRead( FPinNumber ) == HIGH );
1045                                if( AValue == FLastOutput )
1046                                        return;
1047
1048                                FLastOutput = AValue;
1049//      Serial.println( AData.Value );
1050                        OutputPin.Notify( &AValue );
1051            }
1052        }
1053
1054        protected:
1055                void DoAnalogReceive( void *_Data )
1056        {
1057            if( FIsOutput && FIsAnalog )
1058            {
1059                float AValue = *(float*)_Data;
1060                analogWrite( FPinNumber, ( AValue * PWMRANGE ) + 0.5 );
1061            }
1062        }
1063
1064/*
1065                void DoDigitalOutputReceive( void *_Data )
1066                {
1067                        *((int*)_Data) = FPinNumber;
1068                }
1069*/
1070                void DoDigitalReceive( void *_Data )
1071                {
1072                        if( FRawInput )
1073                        {
1074                                *((int*)_Data) = FPinNumber;
1075                                return;
1076                        }
1077
1078            if( ( FCombinedInOut || FIsOutput ) && (! FIsAnalog ))
1079            {
1080                                bool AValue = *(bool *)_Data;
1081
1082                                if( AValue )
1083                                  if( FCombinedInOut )
1084                                          pinMode( FPinNumber, OUTPUT );
1085
1086                if( AValue )
1087                    digitalWrite( FPinNumber, HIGH );
1088
1089                else
1090                    digitalWrite( FPinNumber, LOW );
1091
1092                                if( ! AValue )
1093                                        if( FCombinedInOut )
1094                                                if( FIsPullUp )
1095                                                        pinMode( FPinNumber, INPUT_PULLUP );
1096
1097                                                else
1098                                                        pinMode( FPinNumber, INPUT );
1099
1100            }
1101                }
1102
1103        public:
1104        void SetIsOutput( bool AValue )
1105        {
1106            if( FIsOutput == AValue )
1107                return;
1108
1109            FIsOutput = AValue;
1110            PinDirectionsInit();
1111        }
1112
1113        void SetIsPullUp( bool AValue )
1114        {
1115            if( FIsPullUp == AValue )
1116                return;
1117
1118            FIsPullUp = AValue;
1119            PinDirectionsInit();
1120        }
1121
1122        void SetIsAnalog( bool AValue )
1123        {
1124            if( FIsAnalog == AValue )
1125                return;
1126
1127            FIsAnalog = AValue;
1128            PinDirectionsInit();
1129        }
1130
1131        public:
1132                ArduinoDigitalChannel( int APinNumber, bool AIsOutput, bool AIsPullUp, bool AIsAnalog, bool ACombinedInOut, bool ARawInput ) :
1133                        FPinNumber( APinNumber ),
1134            FIsOutput( AIsOutput ),
1135            FIsPullUp( AIsPullUp ),
1136            FIsAnalog( AIsAnalog ),
1137                        FRawInput( ARawInput ),
1138                        FCombinedInOut( ACombinedInOut )
1139
1140                {
1141                        DigitalInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ArduinoDigitalChannel::DoDigitalReceive );
1142                        AnalogInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&ArduinoDigitalChannel::DoAnalogReceive );
1143                }
1144    };
1145//---------------------------------------------------------------------------
1146    class ArduinoAnalogOutputChannel : public CommonSink
1147    {
1148                typedef Mitov::CommonSink       inherited;
1149
1150        protected:
1151                uint8_t  FPinNumber;
1152
1153        protected:
1154                virtual void DoReceive( void *_Data )
1155                {
1156            float AValue = *(float*)_Data;
1157            analogWrite( FPinNumber, ( AValue * PWMRANGE ) + 0.5 );
1158                }
1159
1160        public:
1161                ArduinoAnalogOutputChannel( int APinNumber ) : 
1162                        FPinNumber( APinNumber )
1163                {
1164                }
1165
1166        };
1167//---------------------------------------------------------------------------
1168#ifdef HAVE_CDCSERIAL
1169        #define SERIAL_TYPE Serial_
1170#else
1171        #define SERIAL_TYPE HardwareSerial
1172#endif
1173//---------------------------------------------------------------------------
1174        enum TArduinoSerialParity { spNone, spEven, slOdd, slMark, slSpace };
1175//---------------------------------------------------------------------------
1176        class BasicSerialPort : public OpenWire::Component
1177        {
1178                typedef OpenWire::Component     inherited;
1179
1180        public:
1181                OpenWire::SourcePin     SendingOutputPin;
1182
1183        public:
1184                bool    Enabled : 1;
1185
1186        protected:
1187                bool    FSending : 1;
1188
1189        public:
1190                uint32_t        AfterSendingDelay = 10000;
1191
1192        public:
1193                virtual Stream &GetStream() = 0;
1194
1195        protected:
1196                uint32_t        FStartTime;
1197
1198        public:
1199                template<typename T> void Print( T AValue )
1200                {
1201                        if( Enabled )
1202                        {
1203                                FSending = true;
1204                                SendingOutputPin.SendValue( FSending );
1205                                FStartTime = micros();
1206                                GetStream().println( AValue );
1207
1208                        }
1209                }
1210
1211                template<typename T> void PrintChar( T AValue )
1212                {
1213                        if( Enabled )
1214                        {
1215                                FSending = true;
1216                                SendingOutputPin.SendValue( FSending );
1217                                FStartTime = micros();
1218                                GetStream().print( AValue );
1219                        }
1220                }
1221
1222        protected:
1223                virtual void SystemLoopBegin( unsigned long currentMicros )
1224                {
1225                        if( FSending )
1226                        {
1227                                if( currentMicros - FStartTime >= AfterSendingDelay )
1228                                {
1229                                        FSending = false;
1230                                        SendingOutputPin.SendValue( FSending );
1231                                }
1232                        }
1233
1234                        inherited::SystemLoopBegin( currentMicros );
1235                }
1236
1237        public:
1238                BasicSerialPort() :
1239                        Enabled( true ),
1240                        FSending( false )
1241                {
1242                }
1243        };
1244//---------------------------------------------------------------------------
1245        template<typename T_SERIAL_TYPE, T_SERIAL_TYPE *T_SERIAL> class BasicTypedSerialPort : public Mitov::BasicSerialPort
1246        {
1247                typedef Mitov::BasicSerialPort  inherited;
1248
1249        public:
1250                virtual Stream &GetStream() { return *T_SERIAL; }
1251
1252        protected:
1253                virtual void SystemInit()
1254                {
1255                        if( Enabled )
1256                                StartPort();
1257
1258                        inherited::SystemInit();
1259                }
1260
1261        protected:
1262                virtual void StartPort() = 0;
1263
1264        void RestartPort()
1265                {
1266                        if( ! Enabled )
1267                                return;
1268
1269                        T_SERIAL->end();
1270                        StartPort();
1271                }
1272
1273        public:
1274                void SetEnabled( bool AValue )
1275                {
1276            if( Enabled == AValue )
1277                return;
1278
1279            Enabled = AValue;
1280                        if( Enabled )
1281                                StartPort();
1282
1283                        else
1284                                T_SERIAL->end();
1285                }
1286
1287        };
1288//---------------------------------------------------------------------------
1289        template<typename T_SERIAL_TYPE, T_SERIAL_TYPE *T_SERIAL> class SpeedSerialPort : public Mitov::BasicTypedSerialPort<T_SERIAL_TYPE, T_SERIAL>
1290        {
1291                typedef Mitov::BasicTypedSerialPort<T_SERIAL_TYPE, T_SERIAL>    inherited;
1292
1293        public:
1294                unsigned long   Speed = 9600;
1295
1296        public:
1297                void SetSpeed( unsigned int AValue )
1298                {
1299            if( Speed == AValue )
1300                return;
1301
1302            Speed = AValue;
1303            inherited::RestartPort();
1304                }
1305
1306        protected:
1307                virtual void StartPort()
1308                {
1309                        T_SERIAL->begin( Speed );
1310                }
1311
1312        };
1313//---------------------------------------------------------------------------
1314        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE, typename T> class ArduinoSerialInput : public Mitov::CommonSink
1315        {
1316                typedef Mitov::CommonSink       inherited;
1317
1318        protected:
1319                virtual void DoReceive( void *_Data ) override
1320                {
1321                        T_SERIAL_INSTANCE->Print( *(T*)_Data );
1322                }
1323        };
1324//---------------------------------------------------------------------------
1325        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoSerialInput<T_INSTANCE, T_SERIAL_INSTANCE, bool> : public Mitov::CommonSink
1326        {
1327                typedef Mitov::CommonSink       inherited;
1328
1329        protected:
1330                virtual void DoReceive( void *_Data ) override
1331                {
1332                        T_SERIAL_INSTANCE->Print( *(bool*)_Data ? "true" : "false" );
1333                }
1334        };
1335//---------------------------------------------------------------------------
1336        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoSerialInput<T_INSTANCE, T_SERIAL_INSTANCE, char> : public Mitov::CommonSink
1337        {
1338                typedef Mitov::CommonSink       inherited;
1339
1340        protected:
1341                virtual void DoReceive( void *_Data ) override
1342                {
1343                        if( *(char*)_Data == '\r' )
1344                                T_SERIAL_INSTANCE->Print( "" );
1345
1346                        else
1347                                T_SERIAL_INSTANCE->PrintChar( *(char*)_Data );
1348                }
1349        };
1350//---------------------------------------------------------------------------
1351        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoSerialBinaryInput : public Mitov::CommonSink
1352        {
1353                typedef Mitov::CommonSink       inherited;
1354
1355        protected:
1356                virtual void DoReceive( void *_Data ) override
1357                {
1358                        if( T_SERIAL_INSTANCE->Enabled )
1359                        {
1360                                Mitov::TDataBlock ADataBlock = *(Mitov::TDataBlock*)_Data;
1361                                T_SERIAL_INSTANCE->GetStream().write((uint8_t *) ADataBlock.Data, ADataBlock.Size );
1362//                              T_SERIAL_INSTANCE->GetStream().write( *(unsigned char*)_Data );
1363                        }
1364                }
1365        };
1366//---------------------------------------------------------------------------
1367        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoSerialStringInput : public Mitov::CommonSink
1368        {
1369                typedef Mitov::CommonSink       inherited;
1370
1371        protected:
1372                virtual void DoReceive( void *_Data ) override
1373                {
1374                        T_SERIAL_INSTANCE->Print( (char*)_Data );
1375                }
1376        };
1377//---------------------------------------------------------------------------
1378        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE, typename T_OBJECT> class ArduinoSerialObjectInput : public Mitov::CommonSink
1379        {
1380                typedef Mitov::CommonSink       inherited;
1381
1382        protected:
1383                virtual void DoReceive( void *_Data ) override
1384                {
1385                        T_SERIAL_INSTANCE->Print( ((T_OBJECT *)_Data)->ToString().c_str() );
1386                }
1387        };
1388//---------------------------------------------------------------------------
1389        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoDirectSerialInput : public Mitov::CommonSink
1390        {
1391                typedef Mitov::CommonSink       inherited;
1392
1393        public:
1394                virtual Stream &GetStream()
1395                {
1396                        return T_SERIAL_INSTANCE->GetStream();
1397                }
1398
1399        protected:
1400                virtual void DoReceive( void *_Data ) override
1401                {
1402//                      if( T_SERIAL_INSTANCE->Enabled )
1403//                              T_SERIAL->write( *(unsigned char*)_Data );
1404                }
1405        };
1406//---------------------------------------------------------------------------
1407        template<typename T_INSTANCE, T_INSTANCE *T_SERIAL_INSTANCE> class ArduinoSerialOutput : public Mitov::CommonSource
1408        {
1409                typedef Mitov::CommonSource     inherited;
1410
1411//      protected:
1412//              byte FData[ 2 ];
1413
1414        protected:
1415                virtual void SystemLoopBegin( unsigned long currentMicros ) override
1416                {
1417                        if( ! T_SERIAL_INSTANCE->Enabled )
1418                                return;
1419
1420//                      if( Serial.available() )
1421                        {
1422                                int AData = T_SERIAL_INSTANCE->GetStream().read();
1423                                if( AData >= 0 )
1424                                {
1425//                                      FData[ 0 ] = AData;
1426//                                      OutputPin.Notify( FData );
1427
1428                                        unsigned char AByte = AData;
1429                                        OutputPin.SendValue( Mitov::TDataBlock( 1, &AByte ));
1430                                }
1431                        }
1432
1433                        inherited::SystemLoopBegin( currentMicros );
1434                }
1435
1436/*
1437        public:
1438                ArduinoSerialOutput()
1439                {
1440                        FData[ 1 ] = 0;
1441                }
1442*/
1443        };
1444//---------------------------------------------------------------------------
1445        class ArduinoI2C_Command
1446        {
1447        public:
1448                virtual void Execute() = 0;
1449
1450        };
1451//---------------------------------------------------------------------------
1452        class ArduinoI2CInput : public Mitov::CommonSink
1453        {
1454                typedef Mitov::CommonSink       inherited;
1455
1456        protected:
1457                virtual void DoReceive( void *_Data ) override
1458                {
1459                        ((ArduinoI2C_Command*)_Data )->Execute();
1460//                      Wire.println( *(ArduinoI2C_Command*)_Data );
1461                }
1462        };
1463//---------------------------------------------------------------------------
1464        class GPRSAccessPoint
1465        {
1466        public:
1467                bool    Enabled = true;
1468
1469                String  AccessPoint;
1470                String  UserName;
1471                String  Password;
1472
1473                int32_t NumberRetries = 5;
1474                int32_t RetryInterval = 30000;
1475
1476        public:
1477                int32_t FRetryCount = 0;
1478                unsigned long FLastTime = 0;
1479
1480        public:
1481                bool CanRetry( unsigned long currentMicros )
1482                {
1483                        if( FRetryCount > NumberRetries )
1484                                return false;
1485
1486                        if(( currentMicros - FLastTime ) < RetryInterval )
1487                                return false;
1488
1489                        return true;
1490                }
1491
1492        };
1493//---------------------------------------------------------------------------
1494        class CommonConverter : public OpenWire::SinkPin
1495        {
1496        public:
1497                OpenWire::SourcePin     OutputPin;
1498
1499        };
1500//---------------------------------------------------------------------------
1501        class Convert_BinaryBlockToChar : public Mitov::CommonConverter
1502        {
1503        protected:
1504                virtual void DoReceive( void *_Data )
1505                {
1506                        Mitov::TDataBlock ABlock = *(Mitov::TDataBlock *)_Data;
1507                        while( ABlock.Size-- )
1508                          OutputPin.Notify( ABlock.Data++ );
1509                }
1510
1511        };
1512//---------------------------------------------------------------------------
1513        class Convert_BinaryToClock : public Mitov::CommonConverter
1514        {
1515        protected:
1516                bool    FLastValue = false;
1517
1518        protected:
1519                virtual void DoReceive( void *_Data )
1520                {
1521                        bool AValue = *(bool *)_Data;
1522                        if( AValue == FLastValue )
1523                                return;
1524
1525                        FLastValue = AValue;
1526                        if( AValue )
1527                                OutputPin.Notify( NULL );
1528
1529                }
1530
1531        };
1532//---------------------------------------------------------------------------
1533        inline uint8_t FromBcdToDec(const uint8_t bcd) 
1534        {
1535                return (10 * ((bcd & 0xF0) >> 4) + (bcd & 0x0F));
1536        }
1537//---------------------------------------------------------------------------
1538        inline uint8_t FromDecToBcd(const uint8_t dec) 
1539        {
1540                const uint8_t tens = dec / 10;
1541                const uint8_t ones = dec % 10;
1542                return (tens << 4) | ones;
1543        }
1544//---------------------------------------------------------------------------
1545        inline float ConvertCtoF(float c) 
1546        {
1547                return c * 1.8 + 32;
1548        }
1549//---------------------------------------------------------------------------
1550        inline float ConvertFtoC(float f)
1551        {
1552                return (f - 32) * 0.55555;
1553        }
1554//---------------------------------------------------------------------------
1555        class InterruptLock 
1556        {
1557        public:
1558                InterruptLock()
1559                {
1560                        noInterrupts();
1561                }
1562
1563                ~InterruptLock() 
1564                {
1565                        interrupts();
1566                }
1567        };
1568//---------------------------------------------------------------------------
1569} // Mitov
1570
1571#endif
1572