libraries / Mitov / Mitov_NeoPixel.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_NEO_PIXEL_h
  11#define _MITOV_NEO_PIXEL_h
  12
  13#include <Mitov.h>
  14
  15#include <MitovEmbedded_Adafruit_NeoPixel/MitovEmbedded_Adafruit_NeoPixel.h>
  16
  17namespace Mitov
  18{
  19        class NeoPixelsRunningColorGroup;
  20//---------------------------------------------------------------------------
  21        class NeoPixelsController
  22        {
  23        public:
  24                virtual void SetPixelColor( int AIndex, TColor AColor ) = 0;
  25                virtual TColor GetPixelColor( int AIndex ) = 0;
  26
  27        };
  28//---------------------------------------------------------------------------
  29        class NeoPixelsCommonGroup : public OpenWire::Component
  30        {
  31        public:
  32                NeoPixelsController     *FOwner;
  33                int                     FStartPixel;
  34
  35        public:
  36                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel )
  37                {
  38                        FOwner = AOwner;
  39                        FStartPixel = AStartPixel;
  40                }
  41
  42                virtual void PixelsClock( unsigned long currentMicros )
  43                {
  44                }
  45
  46        };
  47//---------------------------------------------------------------------------
  48        class NeoPixelsBasicGroup : public NeoPixelsCommonGroup
  49        {
  50                typedef NeoPixelsCommonGroup inherited;
  51
  52        public:
  53                int             CountPixels = 10;
  54
  55        public:
  56                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel )
  57                {
  58                        inherited::StartPixels( AOwner, AStartPixel );
  59                        AStartPixel += CountPixels;
  60                }
  61
  62        };
  63//---------------------------------------------------------------------------
  64        class NeoPixels : public OpenWire::Component, public NeoPixelsController, public Mitov::ClockingSupport
  65        {
  66                typedef OpenWire::Component inherited;
  67
  68        public:
  69                float   Brightness = 1.0f;
  70                Mitov::SimpleObjectList<NeoPixelsCommonGroup*>  PixelGroups;
  71
  72        public:
  73                bool    FModified;
  74
  75        protected:
  76                int     FPinNumber;
  77
  78        public:
  79                void SetBrightness( float AValue )
  80                {
  81                        if( Brightness == AValue )
  82                                return;
  83
  84                        IntSetBrightness( AValue );
  85                }
  86
  87        public:
  88                void SetPixelColor( int AIndex, TColor AColor )
  89                {
  90                        FPixel.setPixelColor( AIndex, AColor.Red, AColor.Green, AColor.Blue );
  91                        FModified = true;
  92                }
  93
  94                TColor GetPixelColor( int AIndex )
  95                {
  96                        return TColor( FPixel.getPixelColor( AIndex ), true );
  97                }
  98
  99        protected:
 100                MitovEmbedded_Adafruit_NeoPixel &FPixel;
 101
 102        protected:
 103                void IntSetBrightness( float AValue )
 104                {
 105                        Brightness = AValue;
 106                        FPixel.setBrightness( AValue * 255 );
 107                        FModified = true;
 108                }
 109
 110                virtual void SystemInit()
 111                {
 112                        FPixel.setPin( FPinNumber );
 113
 114                        FPixel.begin();
 115                        IntSetBrightness( Brightness );
 116
 117                        int AStartPixel = 0;
 118                        for( int i = 0; i < PixelGroups.size(); ++i )
 119                                PixelGroups[ i ]->StartPixels( this, AStartPixel );
 120                        
 121
 122                        inherited::SystemInit();
 123                }
 124
 125                virtual void SystemLoopBegin( unsigned long currentMicros )
 126                {
 127                        for( int i = 0; i < PixelGroups.size(); ++i )
 128                                PixelGroups[ i ]->PixelsClock( currentMicros );
 129
 130                        inherited::SystemLoopBegin( currentMicros );
 131                }
 132
 133                virtual void SystemLoopEnd()
 134                {
 135                        if( FModified )
 136                                if( ! ClockInputPin.IsConnected())
 137                                {
 138                                        FPixel.show();
 139                                        FModified = false;
 140                                }
 141
 142                        inherited::SystemLoopEnd();
 143                }
 144
 145                virtual void DoClockReceive(void *) override
 146                {
 147                        if( FModified )
 148                        {
 149                                FPixel.show();
 150                                FModified = false;
 151                        }
 152                }
 153
 154        public:
 155                NeoPixels( int APinNumber, MitovEmbedded_Adafruit_NeoPixel &APixel ) :
 156                        FPinNumber( APinNumber ),
 157                    FPixel( APixel )
 158                {
 159                }
 160
 161        };
 162//---------------------------------------------------------------------------
 163        class NeoPixelsBasicInitialColorGroup : public NeoPixelsBasicGroup
 164        {
 165                typedef NeoPixelsBasicGroup inherited;
 166
 167        public:
 168                TColor  InitialColor;
 169
 170                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel )
 171                {
 172                        inherited::StartPixels( AOwner, AStartPixel );
 173
 174                        for( int i = 0; i < CountPixels; ++i )
 175                                FOwner->SetPixelColor( FStartPixel + i, InitialColor );
 176                }
 177
 178        };
 179//---------------------------------------------------------------------------
 180        class NeoPixelsBasicColorGroup : public NeoPixelsBasicInitialColorGroup
 181        {
 182                typedef NeoPixelsBasicInitialColorGroup inherited;
 183
 184        protected:
 185                TColor  FColor;
 186
 187        public:
 188                OpenWire::SinkPin       ColorInputPin;
 189
 190        public:
 191                void SetInitialColor( TColor AValue )
 192                {
 193                        if( InitialColor == AValue )
 194                                return;
 195
 196                        InitialColor = AValue;
 197                        FColor = AValue;
 198                        ApplyColorsAll(); 
 199//                      FOwner->FModified = true;
 200                }
 201
 202        protected:
 203                virtual void ApplyColorsAll()
 204                {
 205                        for( int i = 0; i < CountPixels; ++i )
 206                                FOwner->SetPixelColor( FStartPixel + i, FColor );
 207                }
 208
 209                virtual void ApplyColors() {}
 210
 211                void IntSetColor( TColor AValue )
 212                {
 213                        if( FColor == AValue )
 214                                return;
 215
 216                        FColor = AValue;
 217                        ApplyColors(); 
 218//                      FOwner->FModified = true;
 219                }
 220
 221                void DoReceiveColor( void *_Data )
 222                {
 223                        IntSetColor( *(TColor *)_Data );
 224                }
 225
 226        protected:
 227                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel )
 228                {
 229                        inherited::StartPixels( AOwner, AStartPixel );
 230//                      Serial.println( CountPixels );
 231                        IntSetColor( InitialColor );
 232//                      FOwner->FModified = true;
 233//                      Serial.println( FStartPixel );
 234                }
 235
 236        public:
 237                NeoPixelsBasicColorGroup()
 238                {
 239                        ColorInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsBasicColorGroup::DoReceiveColor );
 240                }
 241
 242        };
 243//---------------------------------------------------------------------------
 244        class NeoPixelsGroup : public NeoPixelsBasicInitialColorGroup
 245        {
 246                typedef NeoPixelsBasicInitialColorGroup inherited;
 247
 248        protected:
 249                class PixelVlaueSinkPin : public OpenWire::VlaueSinkPin<TColor>
 250                {
 251                        typedef OpenWire::VlaueSinkPin<TColor> inherited;
 252
 253                public:
 254                        NeoPixelsGroup *FOwner;
 255                        int                             FIndex;
 256
 257                public:
 258                        virtual void Receive( void *_Data )
 259                        {
 260                                TColor AValue = *(TColor *)_Data;
 261                                if( AValue != Value )
 262                                        FOwner->FOwner->SetPixelColor( FIndex, AValue );
 263
 264                                inherited::Receive( _Data );
 265                        }
 266                };
 267
 268        public:
 269                Mitov::SimpleList<PixelVlaueSinkPin> InputPins;
 270
 271        protected:
 272                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel )
 273                {
 274                        inherited::StartPixels( AOwner, AStartPixel );
 275                        for( int i = 0; i < InputPins.size(); ++i )
 276                        {
 277                                InputPins[ i ].FOwner = this;
 278                                InputPins[ i ].FIndex = FStartPixel + i;
 279                                InputPins[ i ].Value = InitialColor;
 280//                              FOwner->SetPixelColor( FStartPixel + i, InitialColor );
 281//                              Iter->SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsGroup::DoReceive );
 282//                              Iter->Value = T_VALUE;
 283                        }
 284
 285                }
 286
 287        };
 288//---------------------------------------------------------------------------
 289        class NeoPixelsRepeatGroup : public NeoPixelsBasicInitialColorGroup, public NeoPixelsController
 290        {
 291                typedef NeoPixelsBasicInitialColorGroup inherited;
 292
 293        public:
 294                Mitov::SimpleObjectList<NeoPixelsCommonGroup*>  PixelGroups;
 295
 296        protected:
 297                int FSubPixelCount;
 298                int FRepeatCount;
 299
 300        public:
 301                virtual void SetPixelColor( int AIndex, TColor AColor )
 302                {
 303                        for( int i = 0; i < FRepeatCount; ++i )
 304                                FOwner->SetPixelColor( FStartPixel + AIndex + i * FSubPixelCount, AColor );
 305                }
 306
 307                virtual TColor GetPixelColor( int AIndex )
 308                {
 309                        return FOwner->GetPixelColor( FStartPixel + AIndex );
 310                }
 311
 312        public:
 313                virtual void StartPixels( NeoPixelsController *AOwner, int &AStartPixel ) 
 314                {
 315                        inherited::StartPixels( AOwner, AStartPixel );
 316
 317                        FSubPixelCount = 0;
 318                        for( int i = 0; i < PixelGroups.size(); ++i )
 319                                PixelGroups[ i ]->StartPixels( this, FSubPixelCount );
 320
 321                        if( FSubPixelCount == 0 )
 322                                FRepeatCount = 0;
 323
 324                        else
 325                                FRepeatCount = ( CountPixels + FSubPixelCount - 1 ) / FSubPixelCount;
 326
 327                }
 328
 329                virtual void PixelsClock( unsigned long currentMicros )
 330                {
 331                        inherited::PixelsClock( currentMicros );
 332
 333                        for( int i = 0; i < PixelGroups.size(); ++i )
 334                                PixelGroups[ i ]->PixelsClock( currentMicros );
 335                }
 336        };
 337//---------------------------------------------------------------------------
 338        class NeoPixelsSingleColorGroup : public NeoPixelsBasicColorGroup
 339        {
 340                typedef NeoPixelsBasicColorGroup inherited;
 341
 342        protected:
 343                virtual void ApplyColors() override
 344                {
 345                        ApplyColorsAll();
 346                }
 347
 348        };
 349//---------------------------------------------------------------------------
 350        class NeoPixelsReversedProperty
 351        {
 352        protected:
 353                NeoPixelsRunningColorGroup &FOwner;
 354
 355        public:
 356                bool Reversed : 1;
 357                bool AllPixels : 1;
 358
 359        public:
 360                void SetReversed( bool AValue );
 361
 362        public:
 363                NeoPixelsReversedProperty( NeoPixelsRunningColorGroup &AOwner ) :
 364                        FOwner( AOwner ),
 365                        Reversed( false ),
 366                        AllPixels( false )
 367                {
 368                }
 369        };
 370//---------------------------------------------------------------------------
 371        class NeoPixelsRunningColorGroup : public NeoPixelsBasicColorGroup
 372        {
 373                typedef NeoPixelsBasicColorGroup inherited;
 374
 375        public:
 376                OpenWire::ConnectSinkPin        StepInputPin;
 377                OpenWire::SourcePin     ColorOutputPin;
 378
 379        public:
 380                NeoPixelsReversedProperty       Reversed;
 381
 382        public:
 383                void ReversePixels()
 384                {
 385                        for( int i = 0; i < CountPixels / 2; ++i )
 386                        {
 387                                TColor AOldColor1 = FOwner->GetPixelColor( FStartPixel + ( CountPixels - i - 1 ));
 388                                TColor AOldColor2 = FOwner->GetPixelColor( FStartPixel + i );
 389
 390                                FOwner->SetPixelColor( FStartPixel + i, AOldColor1 );
 391                                FOwner->SetPixelColor( FStartPixel + ( CountPixels - i - 1 ), AOldColor2 );
 392                        }
 393                }
 394
 395        protected:
 396                void AnimatePixels()
 397                {
 398                        if( Reversed.Reversed )
 399                        {
 400                                TColor AOldColor = FOwner->GetPixelColor( FStartPixel );
 401                                ColorOutputPin.Notify( &AOldColor );
 402                                for( int i = 0; i < CountPixels - 1; ++i )
 403                                {
 404                                        AOldColor = FOwner->GetPixelColor( FStartPixel + i + 1 );
 405                                        FOwner->SetPixelColor( FStartPixel + i, AOldColor );
 406                                }
 407
 408                                FOwner->SetPixelColor( FStartPixel + CountPixels - 1, FColor );
 409                        }
 410
 411                        else
 412                        {
 413                                TColor AOldColor = FOwner->GetPixelColor( FStartPixel + CountPixels - 1 );
 414                                ColorOutputPin.Notify( &AOldColor );
 415                                for( int i = CountPixels - 1; i--; )
 416                                {
 417                                        AOldColor = FOwner->GetPixelColor( FStartPixel + i );
 418                                        FOwner->SetPixelColor( FStartPixel + i + 1, AOldColor );
 419                                }
 420
 421                                FOwner->SetPixelColor( FStartPixel, FColor );
 422                        }
 423//                      FOwner->FModified = true;
 424                }
 425
 426                void DoReceiveStep( void *_Data )
 427                {
 428                        AnimatePixels();
 429                }
 430
 431        protected:
 432                virtual void PixelsClock( unsigned long currentMicros ) override
 433                {
 434                        if( StepInputPin.IsConnected())
 435                                return;
 436
 437                        AnimatePixels();
 438                }
 439
 440        public:
 441                NeoPixelsRunningColorGroup() :
 442                  Reversed( *this )
 443                {
 444                        StepInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsRunningColorGroup::DoReceiveStep );
 445                }
 446        };
 447//---------------------------------------------------------------------------
 448        inline void NeoPixelsReversedProperty::SetReversed( bool AValue )
 449        {
 450                if( Reversed == AValue )
 451                        return;
 452
 453                Reversed = AValue;
 454                if( AllPixels )
 455                        FOwner.ReversePixels();
 456
 457        }
 458//---------------------------------------------------------------------------
 459        class NeoPixelsColorPixelGroup : public NeoPixelsBasicColorGroup
 460        {
 461        public:
 462                OpenWire::SinkPin       IndexInputPin;
 463
 464        public:
 465                uint32_t InitialIndex = 0;
 466
 467        protected:
 468                unsigned long   FIndex;
 469                bool                    FModified;
 470
 471        protected:
 472                void DoReceiveIndex( void *_Data )
 473                {
 474                        unsigned long AIndex = *(unsigned long *)_Data;
 475                        if( AIndex > CountPixels )
 476                                AIndex = CountPixels;
 477
 478                        if( FIndex == AIndex )
 479                                return;
 480
 481                        FIndex = AIndex;
 482                        FModified = true;
 483                }
 484
 485                virtual void PixelsClock( unsigned long currentMicros )
 486                {
 487                        if( FModified )
 488                        {
 489                                FOwner->SetPixelColor( FStartPixel + FIndex, FColor );
 490//                              FOwner->FModified = true;
 491                                FModified = false;
 492                        }
 493                }
 494
 495                virtual void ApplyColors() 
 496                {
 497                        FModified = true;
 498                }
 499
 500        public:
 501                NeoPixelsColorPixelGroup()
 502                {
 503                        IndexInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&NeoPixelsColorPixelGroup::DoReceiveIndex );
 504                }
 505        };
 506//---------------------------------------------------------------------------
 507}
 508
 509#endif