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