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_MAXIM_LED_CONTROL_h
11#define _MITOV_MAXIM_LED_CONTROL_h
12
13#include <Mitov.h>
14#include <Mitov_Basic_SPI.h>
15//#include <Mitov_7Segment_Common.h>
16
17namespace Mitov
18{
19 const byte C_MaximSegments[16] =
20 {
21 0b1111110, // = 0
22 0b0110000, // = 1
23 0b1101101, // = 2
24 0b1111001, // = 3
25 0b0110011, // = 4
26 0b1011011, // = 5
27 0b1011111, // = 6
28 0b1110000, // = 7
29 0b1111111, // = 8
30 0b1111011, // = 9
31 0b1110111, // = A
32 0b0011111, // = B
33 0b0001101, // = C
34 0b0111101, // = D
35 0b1001111, // = E
36 0b1000111 // = F
37 };
38//---------------------------------------------------------------------------
39 const byte C_MaximDecimalPoint[2] =
40 {
41 0b00000000,
42 0b10000000
43 };
44//---------------------------------------------------------------------------
45 class MaximLedCommonGroup;
46//---------------------------------------------------------------------------
47 class MaximLedGroupOwner
48 {
49 public:
50 Mitov::SimpleObjectList<MaximLedCommonGroup*> FPixelGroups;
51
52 public:
53 virtual void SetPixelValue( int AIndex, bool AValue ) = 0;
54 virtual bool GetPixelValue( int AIndex ) = 0;
55
56 };
57//---------------------------------------------------------------------------
58 class MaximLedCommonGroup : public OpenWire::Component
59 {
60 protected:
61 MaximLedGroupOwner &FOwner;
62
63 bool Enabled = true;
64
65 public:
66 void SetEnabled( bool AValue )
67 {
68 if( Enabled == AValue )
69 return;
70
71 Enabled = AValue;
72 UpdateDisplay();
73 }
74
75 public:
76 virtual void StartPixels( int &AStartPixel ) = 0;
77 virtual void PixelsClock( unsigned long currentMicros )
78 {
79 }
80
81 protected:
82 virtual void UpdateDisplay() {}
83
84 public:
85 MaximLedCommonGroup( MaximLedGroupOwner &AOwner ) :
86 FOwner( AOwner )
87 {
88 FOwner.FPixelGroups.push_back( this );
89 }
90 };
91//---------------------------------------------------------------------------
92 template<int COUNT_CONTROLLERS> class MaximLedController : public Mitov::Basic_SPI, public Mitov::ClockingSupport, public Mitov::MaximLedGroupOwner
93 {
94 typedef Mitov::Basic_SPI inherited;
95
96 protected:
97 static const byte OP_DIGIT0 = 1;
98 static const byte OP_DECODEMODE = 9;
99 static const byte OP_INTENSITY = 10;
100 static const byte OP_SCANLIMIT = 11;
101 static const byte OP_SHUTDOWN = 12;
102 static const byte OP_DISPLAYTEST = 15;
103
104 protected:
105// int FNumDevices;
106
107 byte FRegistersCurrent[ COUNT_CONTROLLERS * 8 ];
108 byte FRegisters[ COUNT_CONTROLLERS * 8 ];
109
110 bool FModified = false;
111
112 public:
113 float Intensity = 1.0f;
114
115 protected:
116 void SetIntensity( float AValue )
117 {
118 if( Intensity == AValue )
119 return;
120
121 Intensity = AValue;
122 UpdateIntensity();
123 }
124
125 void SetEnabled( bool AValue )
126 {
127 if( Enabled == AValue )
128 return;
129
130 Enabled = AValue;
131 UpdateShutDown();
132 }
133
134 public:
135 virtual void SetPixelValue( int AIndex, bool AValue )
136 {
137 if( AValue )
138 FRegisters[ AIndex / 8 ] |= 1 << ( AIndex & 7 );
139
140 else
141 FRegisters[ AIndex / 8 ] &= ~( 1 << ( AIndex & 7 ));
142
143 FModified = true;
144 }
145
146 virtual bool GetPixelValue( int AIndex )
147 {
148 return FRegisters[ AIndex / 8 ] & ( 1 << ( AIndex & 7 ));
149 }
150
151 protected:
152 void spiTransferAll( byte opcode, byte data )
153 {
154 //enable the line
155 ChipSelectOutputPin.SendValue( false );
156 //Now shift out the data
157
158 for(int i = 0; i < COUNT_CONTROLLERS; ++i )
159 {
160 FSPI.transfer( opcode );
161 FSPI.transfer( data );
162 }
163
164 //latch the data onto the display
165 ChipSelectOutputPin.SendValue( true );
166 }
167
168/*
169 void spiTransfer( int addr, byte opcode, byte data )
170 {
171 //enable the line
172 ChipSelectOutputPin.SendValue( false );
173 //Now shift out the data
174
175 for(int i = 1; i < COUNT_CONTROLLERS; ++i )
176 FSPI.transfer16( 0 ); // Skip one chip
177
178 FSPI.transfer( opcode );
179 FSPI.transfer( data );
180
181 //latch the data onto the display
182 ChipSelectOutputPin.SendValue( true );
183 }
184*/
185 protected:
186 inline void UpdateIntensity()
187 {
188 spiTransferAll( OP_INTENSITY, Intensity * 15 + 0.5 );
189 }
190
191 inline void UpdateShutDown()
192 {
193 spiTransferAll( OP_SHUTDOWN, Enabled );
194 }
195
196 void UpdatePixels()
197 {
198 uint16_t ABuffer[ COUNT_CONTROLLERS ];
199 FModified = false;
200
201 for(;;)
202 {
203 bool HasChange = false;
204 for( int AControllerIndex = 0; AControllerIndex < COUNT_CONTROLLERS; ++AControllerIndex )
205 {
206 ABuffer[ AControllerIndex ] = 0;
207 for( int j = 0; j < 8; ++j )
208 {
209 int ARegIndex = AControllerIndex * 8 + j;
210 uint16_t ANewRegValue = FRegisters[ ARegIndex ];
211 if( FRegistersCurrent[ ARegIndex ] != ANewRegValue )
212 {
213 FRegistersCurrent[ ARegIndex ] = ANewRegValue;
214 ABuffer[ AControllerIndex ] = ( ANewRegValue << 8 ) | ( OP_DIGIT0 + j );
215 HasChange = true;
216 break;
217 }
218 }
219 }
220
221 if( !HasChange )
222 break;
223
224 //enable the line
225 ChipSelectOutputPin.SendValue( false );
226 FSPI.transfer( ABuffer, COUNT_CONTROLLERS * 2 );
227
228 //latch the data onto the display
229 ChipSelectOutputPin.SendValue( true );
230 }
231 }
232
233 protected:
234 virtual void SystemInit()
235 {
236 int AStartPixel = 0;
237 for( int i = 0; i < FPixelGroups.size(); ++i )
238 FPixelGroups[ i ]->StartPixels( AStartPixel );
239
240// FNumDevices = ( AStartPixel + 63 ) / 64;
241
242// FRegisters.SetCount( FNumDevices * 8, 0 );
243// FRegistersCurrent.SetCount( FNumDevices * 8, 0 );
244
245 spiTransferAll( OP_DISPLAYTEST, 0 );
246 spiTransferAll( OP_SCANLIMIT, 7 );
247 spiTransferAll( OP_DECODEMODE, 0 );
248
249 UpdateShutDown();
250 UpdateIntensity();
251
252// if( FModified )
253
254
255 for( int i = 0; i < COUNT_CONTROLLERS * 8; ++i )
256 FRegistersCurrent[ i ] = FRegisters[ i ] + 1;
257
258 UpdatePixels();
259
260// spiTransferAll( OP_DIGIT0, 255 );
261 inherited::SystemInit();
262 }
263
264 virtual void SystemLoopBegin( unsigned long currentMicros )
265 {
266 for( int i = 0; i < FPixelGroups.size(); ++i )
267 FPixelGroups[ i ]->PixelsClock( currentMicros );
268
269 inherited::SystemLoopBegin( currentMicros );
270 }
271
272 virtual void SystemLoopEnd()
273 {
274 if( FModified )
275 if( ! ClockInputPin.IsConnected())
276 UpdatePixels();
277
278 inherited::SystemLoopEnd();
279 }
280
281 protected:
282 virtual void DoClockReceive( void * )
283 {
284 if( FModified )
285 UpdatePixels();
286 }
287
288 public:
289 MaximLedController( BasicSPI &ASPI ) :
290 inherited( ASPI )
291 {
292 for( int i = 0; i < COUNT_CONTROLLERS * 8; ++i )
293 FRegisters[ i ] = 0;
294 }
295 };
296//---------------------------------------------------------------------------
297 class MaximLedBasicGroup : public MaximLedCommonGroup
298 {
299 typedef Mitov::MaximLedCommonGroup inherited;
300
301 public:
302 int CountPixels = 64;
303
304 public:
305 virtual void StartPixels( int &AStartPixel )
306 {
307// inherited::StartPixels( AStartPixel );
308 AStartPixel += CountPixels;
309 }
310
311 public:
312 using inherited::inherited;
313
314 };
315//---------------------------------------------------------------------------
316 class MaximLedBasicInitialValueGroup : public MaximLedBasicGroup
317 {
318 typedef Mitov::MaximLedBasicGroup inherited;
319
320 public:
321 bool InitialValue = false;
322
323 public:
324 using inherited::inherited;
325
326 };
327//---------------------------------------------------------------------------
328 class MaximLedGroupBasicBooleanPixels : public MaximLedBasicInitialValueGroup
329 {
330 typedef Mitov::MaximLedBasicInitialValueGroup inherited;
331
332 protected:
333 class PixelVlaueSinkPin : public OpenWire::VlaueSinkPin<bool>
334 {
335 typedef OpenWire::VlaueSinkPin<bool> inherited;
336
337 public:
338 MaximLedGroupBasicBooleanPixels *FOwner;
339 int FIndex;
340
341 public:
342 virtual void Receive( void *_Data )
343 {
344 bool AValue = *(bool *)_Data;
345 if( AValue != Value )
346 if( FOwner->Enabled )
347 FOwner->FOwner.SetPixelValue( FIndex, AValue );
348
349 inherited::Receive( _Data );
350 }
351 };
352
353 protected:
354 virtual void UpdateDisplay()
355 {
356 for( int i = 0; i < InputPins.size(); ++i )
357 {
358 if( Enabled )
359 FOwner.SetPixelValue( InputPins[ i ].FIndex, InputPins[ i ].Value );
360
361 else
362 FOwner.SetPixelValue( InputPins[ i ].FIndex, false );
363 }
364 }
365
366 public:
367 Mitov::SimpleList<PixelVlaueSinkPin> InputPins;
368
369 public:
370 using inherited::inherited;
371
372 };
373//---------------------------------------------------------------------------
374 class MaximLedGroup : public MaximLedGroupBasicBooleanPixels
375 {
376 typedef Mitov::MaximLedGroupBasicBooleanPixels inherited;
377
378 public:
379 virtual void StartPixels( int &AStartPixel )
380 {
381 for( int i = 0; i < InputPins.size(); ++i )
382 {
383 InputPins[ i ].FOwner = this;
384 InputPins[ i ].FIndex = AStartPixel + i;
385 InputPins[ i ].Value = InitialValue;
386 FOwner.SetPixelValue( AStartPixel + i, InitialValue );
387 }
388
389 inherited::StartPixels( AStartPixel );
390 }
391
392 public:
393 using inherited::inherited;
394
395 };
396//---------------------------------------------------------------------------
397 class MaximLedGroupSection7Segments : public MaximLedGroupBasicBooleanPixels
398 {
399 typedef Mitov::MaximLedGroupBasicBooleanPixels inherited;
400
401 public:
402 virtual void StartPixels( int &AStartPixel )
403 {
404 for( int i = 0; i < 7; ++i )
405 {
406 InputPins[ i ].FOwner = this;
407 InputPins[ i ].FIndex = AStartPixel + 6 - i;
408 InputPins[ i ].Value = InitialValue;
409 FOwner.SetPixelValue( AStartPixel + 6 - i, InitialValue );
410 }
411
412 InputPins[ 7 ].FOwner = this;
413 InputPins[ 7 ].FIndex = AStartPixel + 7;
414 InputPins[ 7 ].Value = InitialValue;
415 FOwner.SetPixelValue( AStartPixel + 7, InitialValue );
416
417 inherited::StartPixels( AStartPixel );
418 }
419
420 public:
421 MaximLedGroupSection7Segments( MaximLedGroupOwner &AOwner ) :
422 inherited( AOwner )
423 {
424 InputPins.SetCount( 8 );
425 CountPixels = 8;
426 }
427 };
428//---------------------------------------------------------------------------
429 class MaximLedGroupValueSection7Segments : public MaximLedCommonGroup
430 {
431 typedef Mitov::MaximLedCommonGroup inherited;
432
433 public:
434 OpenWire::SinkPin InputPin;
435 OpenWire::SinkPin DecmalPointInputPin;
436
437 public:
438 int InitialValue = 0;
439 bool InitialDecmalPointValue = false;
440
441 protected:
442 int FValue;
443 bool FDecmalPointValue;
444
445 int FStartPixel;
446
447 public:
448 virtual void StartPixels( int &AStartPixel )
449 {
450// inherited::StartPixels( AStartPixel );
451 FStartPixel = AStartPixel;
452 AStartPixel += 8;
453 }
454
455 protected:
456 virtual void UpdateDisplay()
457 {
458 int AValue = (Enabled) ? C_MaximSegments[ FValue & 0xF ] | C_MaximDecimalPoint[ FDecmalPointValue & 1 ] : 0;
459
460 for( int i = 0; i < 8; ++i )
461 FOwner.SetPixelValue( FStartPixel + i, ( AValue >> i ) & 1 );
462 }
463
464 protected:
465 void DoReceive( void *_Data )
466 {
467 int AValue = *(int *)_Data;
468 if( FValue == AValue )
469 return;
470
471 FValue = AValue;
472 UpdateDisplay();
473 }
474
475 void DoReceiveDecmalPoint( void *_Data )
476 {
477 bool AValue = *(bool *)_Data;
478 if( FDecmalPointValue == AValue )
479 return;
480
481 FDecmalPointValue = AValue;
482 UpdateDisplay();
483 }
484
485 virtual void SystemStart()
486 {
487 FValue = InitialValue;
488 FDecmalPointValue = InitialDecmalPointValue;
489 inherited::SystemStart();
490 UpdateDisplay();
491 }
492
493 public:
494 MaximLedGroupValueSection7Segments( MaximLedGroupOwner &AOwner ) :
495 inherited( AOwner )
496 {
497 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupValueSection7Segments::DoReceive );
498 DecmalPointInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupValueSection7Segments::DoReceiveDecmalPoint );
499 }
500 };
501//---------------------------------------------------------------------------
502 class MaximLedGroupBasicMultiDigitDisplay7Segments : public MaximLedCommonGroup
503 {
504 typedef Mitov::MaximLedCommonGroup inherited;
505
506 public:
507 uint32_t CountDigits = 8;
508 bool ReversedOrder = false;
509
510 protected:
511 int FStartPixel;
512
513 public:
514 virtual void StartPixels( int &AStartPixel )
515 {
516// inherited::StartPixels( AStartPixel );
517 FStartPixel = AStartPixel;
518 AStartPixel += CountDigits * 8;
519 }
520
521 public:
522 using inherited::inherited;
523
524 };
525//---------------------------------------------------------------------------
526 template<typename T_DATA> class MaximLedGroupTypedValueDisplay7Segments : public MaximLedGroupBasicMultiDigitDisplay7Segments
527 {
528 typedef Mitov::MaximLedGroupBasicMultiDigitDisplay7Segments inherited;
529
530 public:
531 OpenWire::SinkPin InputPin;
532
533 public:
534 T_DATA InitialValue;
535
536 protected:
537 T_DATA FValue;
538
539 protected:
540 virtual byte GetSegmentsValue( int &ADigit ) = 0;
541
542 virtual void UpdateDisplay() override
543 {
544 for( int ADigit = 0; ADigit < CountDigits; ++ ADigit )
545 {
546 byte AValue;
547 if( inherited::Enabled )
548 AValue = GetSegmentsValue( ADigit );
549
550 else
551 AValue = 0;
552
553 if( ReversedOrder )
554 {
555 for( int i = 0; i < 8; ++i )
556 FOwner.SetPixelValue( FStartPixel + ( CountDigits - ADigit - 1 ) * 8 + i, ( AValue >> i ) & 1 );
557 }
558
559 else
560 {
561 for( int i = 0; i < 8; ++i )
562 FOwner.SetPixelValue( FStartPixel + ADigit * 8 + i, ( AValue >> i ) & 1 );
563 }
564 }
565 }
566
567 protected:
568 void DoReceive( void *_Data )
569 {
570 T_DATA AValue = *(T_DATA *)_Data;
571 if( FValue == AValue )
572 return;
573
574 FValue = AValue;
575 UpdateDisplay();
576 }
577
578 virtual void SystemStart() override
579 {
580 FValue = InitialValue;
581 inherited::SystemStart();
582 UpdateDisplay();
583 }
584
585 public:
586 MaximLedGroupTypedValueDisplay7Segments( MaximLedGroupOwner &AOwner ) :
587 inherited( AOwner ),
588 InitialValue( 0 ) // Needed for specialization
589 {
590 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupTypedValueDisplay7Segments::DoReceive );
591 }
592 };
593//---------------------------------------------------------------------------
594 template<> MaximLedGroupTypedValueDisplay7Segments<String>::MaximLedGroupTypedValueDisplay7Segments( MaximLedGroupOwner &AOwner ) :
595 inherited( AOwner )
596 {
597 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupTypedValueDisplay7Segments::DoReceive );
598 }
599//---------------------------------------------------------------------------
600 class MaximLedGroupIntegerDisplay7Segments : public MaximLedGroupTypedValueDisplay7Segments<int32_t>
601 {
602 typedef Mitov::MaximLedGroupTypedValueDisplay7Segments<int32_t> inherited;
603
604 public:
605 bool LeadingZeroes = false;
606
607 protected:
608 Mitov::SimpleList<unsigned int> FPowers;
609 long FMaxValue; // The biggest possible to display value
610 long FMinValue; // The smallest possible to display value
611
612 protected:
613 virtual byte GetSegmentsValue( int &ADigit )
614 {
615 int AValue;
616 if( FValue > FMaxValue )
617 AValue = 0b1000000;
618
619 else if( FValue < FMinValue )
620 AValue = 0b0001000;
621
622 else
623 {
624 AValue = ( (int)abs( FValue ) ) / FPowers[ ADigit ];
625 if( ( FValue < 0 ) && ( ADigit > 0 ))
626 {
627 if( ( !LeadingZeroes ) && ( AValue == 0 ) )
628 {
629 int APreviousValue = ( -FValue ) / FPowers[ ADigit - 1 ];
630 if( APreviousValue > 0 )
631 AValue = 0b0000001;
632
633 else
634 AValue = 0;
635
636 }
637
638 else
639 {
640 if( ADigit == CountDigits - 1 )
641 AValue = 0b1000000;
642
643 else
644 {
645 int ADigitValue = AValue % 10;
646 AValue = C_MaximSegments[ ADigitValue ];
647 }
648 }
649 }
650
651 else
652 {
653 if( ( !LeadingZeroes ) && ( AValue == 0 ) )
654 AValue = 0;
655
656 else
657 {
658 int ADigitValue = AValue % 10;
659 AValue = C_MaximSegments[ ADigitValue ];
660 }
661 }
662 }
663
664 return AValue;
665 }
666
667 public:
668 virtual void SystemStart()
669 {
670 FPowers.SetCount( CountDigits );
671 for( int i = 0; i < CountDigits; ++i )
672 FPowers[ i ] = pow( 10, i ) + 0.5;
673
674 FMaxValue = pow( 10, CountDigits ) + 0.5 - 1;
675 FMinValue = -( pow( 10, CountDigits - 1 ) + 0.5 - 1 );
676
677 inherited::SystemStart();
678 }
679
680 public:
681 using inherited::inherited;
682
683 };
684//---------------------------------------------------------------------------
685 class MaximLedGroupUnsignedBitPixelsSection : public MaximLedBasicGroup
686 {
687 typedef Mitov::MaximLedBasicGroup inherited;
688
689 public:
690 OpenWire::SinkPin InputPin;
691
692 public:
693 uint32_t InitialValue = 0;
694
695 protected:
696 uint32_t FValue = 0;
697 int FStartPixel;
698
699 protected:
700 virtual void StartPixels( int &AStartPixel )
701 {
702 FValue = InitialValue;
703 FStartPixel = AStartPixel;
704 inherited::StartPixels( AStartPixel );
705 }
706
707 virtual void UpdateDisplay()
708 {
709 for( int i = 0; i < CountPixels; ++i )
710 FOwner.SetPixelValue( FStartPixel + i, Enabled && ( FValue >> i ) & 1 );
711
712 }
713
714 void DoReceive( uint32_t *_Data )
715 {
716 uint32_t AValue = *(uint32_t *)_Data;
717 if( FValue == AValue )
718 return;
719
720 FValue = AValue;
721 UpdateDisplay();
722 }
723
724 public:
725 MaximLedGroupUnsignedBitPixelsSection( MaximLedGroupOwner &AOwner ) :
726 inherited( AOwner )
727 {
728 CountPixels = 32;
729
730 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedGroupUnsignedBitPixelsSection::DoReceive );
731 }
732 };
733//---------------------------------------------------------------------------
734 class MaximLedGroupAnalogDisplay7Segments : public MaximLedGroupTypedValueDisplay7Segments<float>
735 {
736 typedef Mitov::MaximLedGroupTypedValueDisplay7Segments<float> inherited;
737
738 public:
739 int Precision = 2;
740
741 protected:
742 char *FBuffer;
743 char *FStartChar;
744 byte FTextLength;
745 byte FFirstPos;
746
747 char FDecimalPointPos;
748
749 public:
750 virtual byte GetSegmentsValue( int &ADigit )
751 {
752 int AValue;
753 int ANumDigits = CountDigits;
754 if( ! FStartChar )
755 {
756 FStartChar = dtostrf( FValue, 1, Precision, FBuffer );
757// Serial.println( FStartChar );
758 String AText( FStartChar );
759 FTextLength = AText.length(); // strlen( FStartChar );
760// FTextLength = strlen( FStartChar );
761// Serial.println( FTextLength );
762 FDecimalPointPos = AText.indexOf( '.' );
763 if( Precision == 0 )
764 {
765 if( FTextLength <= ANumDigits )
766 FFirstPos = FTextLength - 1;
767
768 else
769 FFirstPos = ANumDigits - 1;
770
771
772// Serial.println( FStartChar );
773// Serial.println( FTextLength );
774// Serial.println( FFirstPos );
775// Serial.println( FDecimalPointPos );
776 }
777
778 else
779 {
780 if( FTextLength <= ANumDigits + 1 )
781 FFirstPos = FTextLength - 1;
782
783 else
784 FFirstPos = ANumDigits + 1 - 1;
785 }
786
787// Serial.println( FFirstPos );
788 }
789
790 int ACorrectedTextLength = FTextLength;
791 if( Precision > 0 )
792 --ACorrectedTextLength;
793
794 if( ( ACorrectedTextLength - Precision ) > ANumDigits )
795 {
796 if( FValue > 0 )
797 AValue = 0b1000000; // Overflow +
798
799 else
800 AValue = 0b0001000; // Overflow -
801 }
802
803 else
804 {
805 int ATextPos = FFirstPos - ADigit;
806 if( ATextPos < 0 )
807 AValue = 0;
808
809 else
810 {
811 if( ATextPos < 0 )
812 return( 0 );
813
814 bool ADecimalPoint = ( FStartChar[ ATextPos ] == '.' );
815 if( ATextPos <= FDecimalPointPos )
816 --ATextPos;
817
818// if( ADecimalPoint )
819// --ATextPos;
820
821 if( ATextPos < 0 )
822 return( 0 );
823
824/*
825 if( FDigit == 0 )
826 {
827 Serial.println( FStartChar );
828 Serial.println( ATextPos );
829 }
830*/
831 if( FStartChar[ ATextPos ] == '-' )
832 AValue = 0b0000001;
833
834 else
835 {
836 AValue = FStartChar[ ATextPos ] - '0';
837 AValue = C_MaximSegments[ AValue ];
838 }
839
840 if( ADecimalPoint )
841 AValue |= 0x80;
842
843 }
844 }
845
846 return AValue;
847 }
848
849 virtual void UpdateDisplay()
850 {
851 FStartChar = NULL;
852 inherited::UpdateDisplay();
853 }
854
855 protected:
856 virtual void SystemStart()
857 {
858 FBuffer = new char[ 15 + Precision ];
859 inherited::SystemStart();
860 }
861
862 public:
863 using inherited::inherited;
864
865 };
866//---------------------------------------------------------------------------
867 class MaximLedBasicValueGroup : public MaximLedBasicInitialValueGroup
868 {
869 typedef MaximLedBasicInitialValueGroup inherited;
870
871 public:
872 OpenWire::SinkPin InputPin;
873
874 protected:
875 bool FValue;
876
877 protected:
878 int FStartPixel;
879
880 public:
881 virtual void StartPixels( int &AStartPixel )
882 {
883 FStartPixel = AStartPixel;
884 inherited::StartPixels( AStartPixel );
885 }
886
887 protected:
888 void DoReceive( void *_Data )
889 {
890 bool AValue = *(bool *)_Data;
891 if( FValue == AValue )
892 return;
893
894 FValue = AValue;
895 UpdateDisplay();
896 }
897
898 virtual void SystemStart()
899 {
900 FValue = InitialValue;
901 inherited::SystemStart();
902 UpdateDisplay();
903 }
904
905 public:
906 MaximLedBasicValueGroup( MaximLedGroupOwner &AOwner ) :
907 inherited( AOwner )
908 {
909 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedBasicValueGroup::DoReceive );
910 }
911 };
912//---------------------------------------------------------------------------
913 class MaximLedSingleValueGroup : public MaximLedBasicValueGroup
914 {
915 typedef MaximLedBasicValueGroup inherited;
916
917 protected:
918 virtual void UpdateDisplay() override
919 {
920 for( int i = 0; i < CountPixels; ++i )
921 {
922 if( Enabled )
923 FOwner.SetPixelValue( FStartPixel + i, FValue );
924
925 else
926 FOwner.SetPixelValue( FStartPixel + i, false );
927 }
928 }
929
930 public:
931 using inherited::inherited;
932
933 };
934//---------------------------------------------------------------------------
935 class MaximLedIndexedPixelGroup : public MaximLedBasicValueGroup
936 {
937 typedef MaximLedBasicValueGroup inherited;
938
939 public:
940 OpenWire::SinkPin IndexInputPin;
941
942 public:
943 uint32_t InitialIndex = 0;
944
945 protected:
946 unsigned long FIndex;
947
948 protected:
949 void DoReceiveIndex( void *_Data )
950 {
951 unsigned long AIndex = *(unsigned long *)_Data;
952 if( AIndex > CountPixels )
953 AIndex = CountPixels;
954
955 if( FIndex == AIndex )
956 return;
957
958 FIndex = AIndex;
959 UpdateDisplay();
960 }
961
962 virtual void UpdateDisplay() override
963 {
964 if( Enabled )
965 FOwner.SetPixelValue( FStartPixel + FIndex, FValue );
966
967 else
968 FOwner.SetPixelValue( FStartPixel + FIndex, false );
969 }
970
971 public:
972 MaximLedIndexedPixelGroup( MaximLedGroupOwner &AOwner ) :
973 inherited( AOwner )
974 {
975 IndexInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexedPixelGroup::DoReceiveIndex );
976 }
977 };
978//---------------------------------------------------------------------------
979 class MaximLedIndexed2DPixelGroup : public MaximLedBasicValueGroup
980 {
981 typedef MaximLedBasicValueGroup inherited;
982
983 public:
984 OpenWire::SinkPin IndexInputPins[ 2 ];
985
986 public:
987 unsigned long Width = 8;
988 unsigned long InitialIndexX = 0;
989 unsigned long InitialIndexY = 0;
990
991 protected:
992 unsigned long FIndexX;
993 unsigned long FIndexY;
994
995 protected:
996 void DoReceiveIndexX( void *_Data )
997 {
998 unsigned long AIndex = *(unsigned long *)_Data;
999 if( AIndex > Width )
1000 AIndex = Width;
1001
1002 if( FIndexX == AIndex )
1003 return;
1004
1005 FIndexX = AIndex;
1006 UpdateDisplay();
1007 }
1008
1009 void DoReceiveIndexY( void *_Data )
1010 {
1011 unsigned long AIndex = *(unsigned long *)_Data;
1012 unsigned long AHeight = ( CountPixels + Width - 1 ) / Width;
1013 if( AIndex > AHeight )
1014 AIndex = AHeight;
1015
1016 if( FIndexY == AIndex )
1017 return;
1018
1019 FIndexY = AIndex;
1020 UpdateDisplay();
1021 }
1022
1023 virtual void UpdateDisplay()
1024 {
1025 unsigned long AIndex = FStartPixel + FIndexY * Width + FIndexX;
1026 if( Enabled )
1027 FOwner.SetPixelValue( AIndex, FValue );
1028
1029 else
1030 FOwner.SetPixelValue( AIndex, false );
1031 }
1032
1033 public:
1034 MaximLedIndexed2DPixelGroup( MaximLedGroupOwner &AOwner ) :
1035 inherited( AOwner )
1036 {
1037 IndexInputPins[ 0 ].SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexed2DPixelGroup::DoReceiveIndexX );
1038 IndexInputPins[ 1 ].SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedIndexed2DPixelGroup::DoReceiveIndexY );
1039 }
1040 };
1041//---------------------------------------------------------------------------
1042 class MaximLedRunningPixelGroup;
1043//---------------------------------------------------------------------------
1044 class MaximLedPixelsReversedProperty
1045 {
1046 protected:
1047 MaximLedRunningPixelGroup &FOwner;
1048
1049 public:
1050 bool Reversed : 1;
1051 bool AllPixels : 1;
1052
1053 public:
1054 void SetReversed( bool AValue );
1055
1056 public:
1057 MaximLedPixelsReversedProperty( MaximLedRunningPixelGroup &AOwner ) :
1058 FOwner( AOwner ),
1059 Reversed( false ),
1060 AllPixels( false )
1061 {
1062 }
1063 };
1064//---------------------------------------------------------------------------
1065 class MaximLedRunningPixelGroup : public MaximLedBasicValueGroup
1066 {
1067 typedef MaximLedBasicValueGroup inherited;
1068
1069 public:
1070 OpenWire::ConnectSinkPin StepInputPin;
1071 OpenWire::SourcePin OutputPin;
1072
1073 public:
1074 MaximLedPixelsReversedProperty Reversed;
1075
1076 public:
1077 void ReversePixels()
1078 {
1079 for( int i = 0; i < CountPixels / 2; ++i )
1080 {
1081 bool AOldValue1 = FOwner.GetPixelValue( FStartPixel + ( CountPixels - i - 1 ));
1082 bool AOldValue2 = FOwner.GetPixelValue( FStartPixel + i );
1083
1084 FOwner.SetPixelValue( FStartPixel + i, AOldValue1 );
1085 FOwner.SetPixelValue( FStartPixel + ( CountPixels - i - 1 ), AOldValue2 );
1086 }
1087 }
1088
1089 protected:
1090 void AnimatePixels()
1091 {
1092 if( Reversed.Reversed )
1093 {
1094 bool AOldValue = FOwner.GetPixelValue( FStartPixel );
1095 OutputPin.Notify( &AOldValue );
1096 for( int i = 0; i < CountPixels - 1; ++i )
1097 {
1098 AOldValue = FOwner.GetPixelValue( FStartPixel + i + 1 );
1099 FOwner.SetPixelValue( FStartPixel + i, AOldValue );
1100 }
1101
1102 FOwner.SetPixelValue( FStartPixel + CountPixels - 1, FValue );
1103 }
1104
1105 else
1106 {
1107 bool AOldValue = FOwner.GetPixelValue( FStartPixel + CountPixels - 1 );
1108 OutputPin.Notify( &AOldValue );
1109 for( int i = CountPixels - 1; i--; )
1110 {
1111 AOldValue = FOwner.GetPixelValue( FStartPixel + i );
1112 FOwner.SetPixelValue( FStartPixel + i + 1, AOldValue );
1113 }
1114
1115 FOwner.SetPixelValue( FStartPixel, FValue );
1116 }
1117// FOwner->FModified = true;
1118 }
1119
1120 void DoReceiveStep( void *_Data )
1121 {
1122 AnimatePixels();
1123 }
1124
1125 public:
1126 virtual void PixelsClock( unsigned long currentMicros )
1127 {
1128 if( StepInputPin.IsConnected())
1129 return;
1130
1131 AnimatePixels();
1132 }
1133
1134 public:
1135 MaximLedRunningPixelGroup( MaximLedGroupOwner &AOwner ) :
1136 inherited( AOwner ),
1137 Reversed( *this )
1138 {
1139 StepInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&MaximLedRunningPixelGroup::DoReceiveStep );
1140 }
1141 };
1142//---------------------------------------------------------------------------
1143 inline void MaximLedPixelsReversedProperty::SetReversed( bool AValue )
1144 {
1145 if( Reversed == AValue )
1146 return;
1147
1148 Reversed = AValue;
1149 if( AllPixels )
1150 FOwner.ReversePixels();
1151
1152 }
1153//---------------------------------------------------------------------------
1154 class MaximLedRepeatGroup : public MaximLedBasicInitialValueGroup, public MaximLedGroupOwner
1155 {
1156 typedef MaximLedBasicInitialValueGroup inherited;
1157
1158 protected:
1159 int FSubPixelCount;
1160 int FRepeatCount;
1161 int FStartPixel;
1162
1163 public:
1164 virtual void SetPixelValue( int AIndex, bool AValue )
1165 {
1166 for( int i = 0; i < FRepeatCount; ++i )
1167 FOwner.SetPixelValue( FStartPixel + AIndex + i * FSubPixelCount, AValue );
1168 }
1169
1170 virtual bool GetPixelValue( int AIndex )
1171 {
1172 return FOwner.GetPixelValue( FStartPixel + AIndex );
1173 }
1174
1175 public:
1176 virtual void StartPixels( int &AStartPixel )
1177 {
1178 FStartPixel = AStartPixel;
1179 inherited::StartPixels( AStartPixel );
1180
1181 FSubPixelCount = 0;
1182 for( int i = 0; i < FPixelGroups.size(); ++i )
1183 FPixelGroups[ i ]->StartPixels( FSubPixelCount );
1184
1185 if( FSubPixelCount == 0 )
1186 FRepeatCount = 0;
1187
1188 else
1189 FRepeatCount = ( CountPixels + FSubPixelCount - 1 ) / FSubPixelCount;
1190
1191 }
1192
1193 virtual void PixelsClock( unsigned long currentMicros )
1194 {
1195 inherited::PixelsClock( currentMicros );
1196
1197 for( int i = 0; i < FPixelGroups.size(); ++i )
1198 FPixelGroups[ i ]->PixelsClock( currentMicros );
1199 }
1200
1201 public:
1202 using inherited::inherited;
1203
1204 };
1205//---------------------------------------------------------------------------
1206}
1207
1208#endif