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_IQUID_CRYSTAL_DISPLAY_h
11#define _MITOV_IQUID_CRYSTAL_DISPLAY_h
12
13#include <Mitov.h>
14
15namespace Mitov
16{
17//---------------------------------------------------------------------------
18 class LiquidCrystalDisplay;
19//---------------------------------------------------------------------------
20 class LiquidCrystalElementBasic : public OpenWire::Component
21 {
22 typedef OpenWire::Component inherited;
23
24 public: // Public for the print access
25 LCD *FLcd;
26
27 public:
28 virtual void DisplayInit() {}
29 virtual void DisplayStart() {}
30
31 public:
32 LiquidCrystalElementBasic( Mitov::LiquidCrystalDisplay &AOwner );
33
34 };
35//---------------------------------------------------------------------------
36 class LiquidCrystalElementBasicPositionedField : public LiquidCrystalElementBasic
37 {
38 typedef Mitov::LiquidCrystalElementBasic inherited;
39
40 public:
41 unsigned long Column = 0;
42 unsigned long Row = 0;
43
44 public:
45 using inherited::inherited;
46
47 };
48//---------------------------------------------------------------------------
49 class LiquidCrystalElementBasicPositionedWidthField : public LiquidCrystalElementBasicPositionedField
50 {
51 typedef Mitov::LiquidCrystalElementBasicPositionedField inherited;
52
53 public:
54 unsigned long Width = 16;
55
56 public:
57 void ClearLine()
58 {
59 FLcd->setCursor( Column, Row );
60 }
61
62 void NewLine( int AClearSize )
63 {
64 for( int i = 0; i < Width - AClearSize; ++ i )
65 FLcd->print( ' ' );
66 }
67
68 public:
69 using inherited::inherited;
70
71 };
72//---------------------------------------------------------------------------
73 class LiquidCrystalElementTextField : public LiquidCrystalElementBasicPositionedWidthField
74 {
75 typedef Mitov::LiquidCrystalElementBasicPositionedWidthField inherited;
76
77 public:
78 String InitialValue;
79
80 protected:
81 virtual void SystemStart() override
82 {
83 inherited::SystemStart();
84 ClearLine();
85 int AClearSize = FLcd->print( InitialValue );
86 NewLine( AClearSize );
87 }
88
89 public:
90 using inherited::inherited;
91
92 };
93//---------------------------------------------------------------------------
94 template<typename T> class LiquidCrystalElementBasicPositionedWidthTypedField : public LiquidCrystalElementBasicPositionedWidthField
95 {
96 typedef Mitov::LiquidCrystalElementBasicPositionedWidthField inherited;
97
98 public:
99 T InitialValue;
100
101 public:
102 OpenWire::SinkPin InputPin;
103
104 protected:
105 virtual int PrintValue( T AValue ) = 0;
106
107 void ClearPrintValue( T AValue )
108 {
109 InitialValue = AValue;
110// Serial.println( AValue );
111 ClearLine();
112 int AClearSize = PrintValue( AValue );
113 NewLine( AClearSize );
114 }
115
116 protected:
117 virtual void SystemStart() override
118 {
119 inherited::SystemStart();
120// char AText[ 50 ];
121// itoa( InitialValue, AText, Base );
122// int AClearSize = FLcd->print( AText );
123 ClearPrintValue( InitialValue );
124 }
125
126 void DoReceiveData( void *_Data )
127 {
128 ClearPrintValue( *(T*)_Data );
129 }
130
131 public:
132 LiquidCrystalElementBasicPositionedWidthTypedField( Mitov::LiquidCrystalDisplay &AOwner, T AInitialValue ) :
133 inherited( AOwner ),
134 InitialValue( AInitialValue )
135 {
136 InputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalElementBasicPositionedWidthTypedField::DoReceiveData );
137 }
138
139 };
140//---------------------------------------------------------------------------
141 class LiquidCrystalElementIntegerField : public LiquidCrystalElementBasicPositionedWidthTypedField<long>
142 {
143 typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField<long> inherited;
144
145 public:
146 int Base = 10;
147
148 protected:
149 virtual int PrintValue( long AValue ) override
150 {
151 char AText[ 50 ];
152 itoa( AValue, AText, Base );
153 return FLcd->print( AText );
154 }
155
156 public:
157 LiquidCrystalElementIntegerField( Mitov::LiquidCrystalDisplay &AOwner ) :
158 inherited( AOwner, 0 )
159 {
160 }
161
162 };
163//---------------------------------------------------------------------------
164 class LiquidCrystalElementAnalogField : public LiquidCrystalElementBasicPositionedWidthTypedField<float>
165 {
166 typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField<float> inherited;
167
168 public:
169 int MinWidth = 1;
170 int Precision = 3;
171
172 protected:
173 virtual int PrintValue( float AValue ) override
174 {
175 char AText[ 50 ];
176 dtostrf( AValue, MinWidth, Precision, AText );
177 return FLcd->print( AText );
178 }
179
180 public:
181 LiquidCrystalElementAnalogField( Mitov::LiquidCrystalDisplay &AOwner ) :
182 inherited( AOwner, 0 )
183 {
184 }
185
186 };
187//---------------------------------------------------------------------------
188 class LiquidCrystalElementDigitalField : public LiquidCrystalElementBasicPositionedWidthTypedField<bool>
189 {
190 typedef Mitov::LiquidCrystalElementBasicPositionedWidthTypedField<bool> inherited;
191
192 public:
193 String TrueValue = "true";
194 String FalseValue = "false";
195
196 protected:
197 virtual int PrintValue( bool AValue ) override
198 {
199 if( AValue )
200 return FLcd->print( TrueValue );
201
202 return FLcd->print( FalseValue );
203 }
204
205 public:
206 LiquidCrystalElementDigitalField( Mitov::LiquidCrystalDisplay &AOwner ) :
207 inherited( AOwner, 0 )
208 {
209 }
210
211 };
212//---------------------------------------------------------------------------
213 // TODO: Implement setCursor() and createChar()
214 class LiquidCrystalDisplay : public OpenWire::Component
215 {
216 typedef OpenWire::Component inherited;
217
218 public:
219 OpenWire::SinkPin ScrollLeftInputPin;
220 OpenWire::SinkPin ScrollRightInputPin;
221 OpenWire::SinkPin ClearInputPin;
222 OpenWire::SinkPin HomeInputPin;
223
224 public:
225 bool Enabled : 1;
226 bool AutoScroll : 1;
227 bool RightToLeft : 1;
228 bool ShowCursor : 1;
229 bool Blink : 1;
230
231 protected:
232 uint8_t FCols;
233 uint8_t FRows;
234 uint8_t FCursorLine = 0;
235 uint8_t FCursorPos = 0;
236
237 public: // Public for the print access
238 LCD *FLcd;
239 Mitov::SimpleList<LiquidCrystalElementBasic *> FElements;
240
241 public:
242 void ClearLine()
243 {
244 FLcd->setCursor( 0, FCursorLine );
245 FCursorPos = 0;
246// for( int i = 0; i < FCols; ++ i )
247// FLcd->print( ' ' );
248
249// FLcd->setCursor( 0, FCursorLine );
250 }
251
252 void NewLine( int AClearSize )
253 {
254 for( int i = 0; i < FCols - FCursorPos - AClearSize; ++ i )
255 FLcd->print( ' ' );
256
257 ++FCursorLine;
258 FCursorPos = 0;
259 if( FCursorLine >= FRows )
260 FCursorLine = 0;
261
262// FLcd->setCursor( 0, FCursorLine );
263 }
264
265 void MoveChars( int ACount )
266 {
267 ++FCursorPos;
268 }
269
270 public:
271 void SetEnabled( bool AValue )
272 {
273 if( Enabled == AValue )
274 return;
275
276 Enabled = AValue;
277 UpdateEnabled();
278 }
279
280 void SetAutoScroll( bool AValue )
281 {
282 if( AutoScroll == AValue )
283 return;
284
285 AutoScroll = AValue;
286 UpdateAutoScroll();
287 }
288
289 void SetRightToLeft( bool AValue )
290 {
291 if( RightToLeft == AValue )
292 return;
293
294 RightToLeft = AValue;
295 UpdateRightToLeft();
296 }
297
298 void SetShowCursor( bool AValue )
299 {
300 if( ShowCursor == AValue )
301 return;
302
303 ShowCursor = AValue;
304 UpdateShowCursor();
305 }
306
307 void SetBlink( bool AValue )
308 {
309 if( Blink == AValue )
310 return;
311
312 Blink = AValue;
313 UpdateBlink();
314 }
315
316 protected:
317 void UpdateEnabled()
318 {
319 if( Enabled )
320 FLcd->display();
321
322 else
323 FLcd->noDisplay();
324
325 }
326
327 void UpdateAutoScroll()
328 {
329 if( AutoScroll )
330 FLcd->autoscroll();
331
332 else
333 FLcd->noAutoscroll();
334
335 }
336
337 void UpdateRightToLeft()
338 {
339 if( RightToLeft )
340 FLcd->rightToLeft();
341
342 else
343 FLcd->leftToRight();
344
345 }
346
347 void UpdateShowCursor()
348 {
349 if( ShowCursor )
350 FLcd->cursor();
351
352 else
353 FLcd->noCursor();
354
355 }
356
357 void UpdateBlink()
358 {
359 if( Blink )
360 FLcd->blink();
361
362 else
363 FLcd->noBlink();
364
365 }
366
367 void DoScrollLeft( void * )
368 {
369 FLcd->scrollDisplayLeft();
370 }
371
372 void DoScrollRight( void * )
373 {
374 FLcd->scrollDisplayRight();
375 }
376
377 void DoClear( void * )
378 {
379 FLcd->clear();
380 }
381
382 void DoHome( void * )
383 {
384 FLcd->home();
385 }
386
387 public:
388 virtual void SystemInit() override
389 {
390 inherited::SystemInit();
391
392 FLcd->begin( FCols, FRows );
393 UpdateEnabled();
394 UpdateAutoScroll();
395 UpdateRightToLeft();
396 UpdateShowCursor();
397 UpdateBlink();
398
399 for( Mitov::SimpleList<LiquidCrystalElementBasic *>::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter )
400 ( *Iter)->DisplayInit();
401
402// FLcd->setCursor(0,0);
403 }
404
405 virtual void SystemStart() override
406 {
407 inherited::SystemStart();
408
409 for( Mitov::SimpleList<LiquidCrystalElementBasic *>::iterator Iter = FElements.begin(); Iter != FElements.end(); ++Iter )
410 ( *Iter)->DisplayStart();
411 }
412
413 public:
414 LiquidCrystalDisplay( LCD *ALcd, unsigned int ACols, unsigned int ARows ) :
415 FLcd( ALcd ),
416 FCols( ACols ),
417 FRows( ARows ),
418 Enabled( true ),
419 AutoScroll( false ),
420 RightToLeft( false ),
421 ShowCursor( false ),
422 Blink( false )
423 {
424 ScrollLeftInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoScrollLeft );
425 ScrollRightInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoScrollRight );
426 ClearInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoClear );
427 HomeInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&LiquidCrystalDisplay::DoHome );
428 }
429
430/*
431 virtual ~LiquidCrystalDisplay()
432 {
433 delete FLcd;
434 }
435*/
436 };
437//---------------------------------------------------------------------------
438 class LiquidCrystalDisplayI2C : public LiquidCrystalDisplay
439 {
440 typedef Mitov::LiquidCrystalDisplay inherited;
441
442 public:
443 bool Backlight = true;
444
445 public:
446 void SetBacklight( bool AValue )
447 {
448 if( Backlight == AValue )
449 return;
450
451 Backlight = AValue;
452 UpdateBacklight();
453 }
454
455 public:
456 virtual void SystemInit() override
457 {
458 inherited::SystemInit();
459 UpdateBacklight();
460 }
461
462 public:
463 void UpdateBacklight()
464 {
465 if( Backlight )
466 inherited::FLcd->setBacklight( 255 );
467
468 else
469 inherited::FLcd->setBacklight( 0 );
470
471 }
472
473 public:
474 using inherited::inherited;
475
476 };
477//---------------------------------------------------------------------------
478 class LiquidCrystalElementDefineCustomCharacter : public LiquidCrystalElementBasic
479 {
480 typedef Mitov::LiquidCrystalElementBasic inherited;
481
482 protected:
483 uint8_t FCharMap[ 8 ];
484
485 uint8_t FIndex;
486
487 public:
488 virtual void DisplayInit() override
489 {
490 FLcd->createChar( FIndex, FCharMap );
491 }
492
493 public:
494 LiquidCrystalElementDefineCustomCharacter( Mitov::LiquidCrystalDisplay &AOwner, uint8_t AIndex, uint8_t Byte0, uint8_t Byte1, uint8_t Byte2, uint8_t Byte3, uint8_t Byte4, uint8_t Byte5, uint8_t Byte6, uint8_t Byte7 ) :
495 inherited( AOwner ),
496 FIndex( AIndex )
497 {
498 AOwner.FElements.push_back( this );
499
500 FCharMap[ 0 ] = Byte0;
501 FCharMap[ 1 ] = Byte1;
502 FCharMap[ 2 ] = Byte2;
503 FCharMap[ 3 ] = Byte3;
504 FCharMap[ 4 ] = Byte4;
505 FCharMap[ 5 ] = Byte5;
506 FCharMap[ 6 ] = Byte6;
507 FCharMap[ 7 ] = Byte7;
508 }
509
510 };
511//---------------------------------------------------------------------------
512 class LiquidCrystalElementCustomCharacterField : public LiquidCrystalElementBasicPositionedField
513 {
514 typedef Mitov::LiquidCrystalElementBasicPositionedField inherited;
515
516 public:
517 long Index = 0;
518
519 protected:
520 bool FModified = false;
521
522 public:
523 void SetIndex( long AValue )
524 {
525 if( AValue > 7 )
526 AValue = 7;
527
528 else if( AValue < 0 )
529 AValue = 0;
530
531 if( Index == AValue )
532 return;
533
534 Index = AValue;
535 FModified = true;
536 }
537
538 void SetColumn( unsigned long AValue )
539 {
540 if( AValue < 0 )
541 AValue = 0;
542
543 if( Column == AValue )
544 return;
545
546 Column = AValue;
547 FModified = true;
548 }
549
550 void SetRow( unsigned long AValue )
551 {
552 if( AValue < 0 )
553 AValue = 0;
554
555 if( Row == AValue )
556 return;
557
558 Row = AValue;
559 FModified = true;
560 }
561
562 public:
563 virtual void DisplayStart() override
564 {
565 DisplayCharacter();
566 }
567
568 virtual void SystemLoopBegin( unsigned long currentMicros ) override
569 {
570 inherited::SystemLoopBegin( currentMicros );
571 if( FModified )
572 {
573 DisplayCharacter();
574 FModified = false;
575 }
576 }
577
578 protected:
579 void DisplayCharacter()
580 {
581 FLcd->setCursor( Column, Row );
582 FLcd->write( (uint8_t) Index );
583 }
584
585 public:
586 LiquidCrystalElementCustomCharacterField( Mitov::LiquidCrystalDisplay &AOwner ) :
587 inherited( AOwner )
588 {
589 AOwner.FElements.push_back( this );
590 }
591
592 };
593//---------------------------------------------------------------------------
594 template<typename T_LCD, T_LCD *T_LCD_INSTANCE, typename T> class LiquidCrystalDisplayInput : public Mitov::CommonSink
595 {
596 typedef Mitov::CommonSink inherited;
597
598 protected:
599 virtual void DoReceive( void *_Data ) override
600 {
601 T_LCD_INSTANCE->ClearLine();
602 int AClearSize = T_LCD_INSTANCE->FLcd->print( *(T*)_Data );
603 T_LCD_INSTANCE->NewLine( AClearSize );
604 }
605 };
606//---------------------------------------------------------------------------
607 template<typename T_LCD, T_LCD *T_LCD_INSTANCE> class LiquidCrystalDisplayCharInput : public Mitov::CommonSink
608 {
609 typedef Mitov::CommonSink inherited;
610
611 protected:
612 virtual void DoReceive( void *_Data ) override
613 {
614// Serial.print( (char*)_Data );
615// if( *(byte*)_Data < ' ' )
616// return;
617
618 if( *(char*)_Data == '\r' )
619 T_LCD_INSTANCE->NewLine( 0 );
620
621 else if( *(char*)_Data == '\n' )
622 T_LCD_INSTANCE->ClearLine();
623
624 else if( *(char*)_Data >= ' ' )
625 {
626 int AClearSize = T_LCD_INSTANCE->FLcd->print( *(char*)_Data );
627 T_LCD_INSTANCE->MoveChars( AClearSize );
628 }
629// int AClearSize = T_LCD_INSTANCE->FLcd->print( (char*)_Data );
630// T_LCD_INSTANCE->NewLine( AClearSize );
631 }
632 };
633//---------------------------------------------------------------------------
634 template<typename T_LCD, T_LCD *T_LCD_INSTANCE> class LiquidCrystalDisplayStringInput : public Mitov::CommonSink
635 {
636 typedef Mitov::CommonSink inherited;
637
638 protected:
639 virtual void DoReceive( void *_Data )
640 {
641// Serial.print( (char*)_Data );
642// if( *(byte*)_Data < ' ' )
643// return;
644
645 T_LCD_INSTANCE->ClearLine();
646 int AClearSize = T_LCD_INSTANCE->FLcd->print( (char*)_Data );
647 T_LCD_INSTANCE->NewLine( AClearSize );
648 }
649 };
650//---------------------------------------------------------------------------
651 template<typename T_LCD, T_LCD *T_LCD_INSTANCE, typename T_OBJECT> class LiquidCrystalDisplayObjectInput : public Mitov::CommonSink
652 {
653 typedef Mitov::CommonSink inherited;
654
655 protected:
656 virtual void DoReceive( void *_Data )
657 {
658 T_LCD_INSTANCE->ClearLine();
659 int AClearSize = T_LCD_INSTANCE->FLcd->print( ((T_OBJECT *)_Data)->ToString().c_str() );
660 T_LCD_INSTANCE->NewLine( AClearSize );
661 }
662 };
663//---------------------------------------------------------------------------
664//---------------------------------------------------------------------------
665//---------------------------------------------------------------------------
666//---------------------------------------------------------------------------
667 LiquidCrystalElementBasic::LiquidCrystalElementBasic( LiquidCrystalDisplay &AOwner ) :
668 FLcd( AOwner.FLcd )
669 {
670 }
671//---------------------------------------------------------------------------
672}
673
674#endif