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