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_7SEGMENT_h
11#define _MITOV_7SEGMENT_h
12
13#include <Mitov.h>
14#include <Mitov_BasicDisplay.h>
15
16namespace Mitov
17{
18 const byte C_Segments[16] =
19 {
20 0b0111111, // = 0
21 0b0000110, // = 1
22 0b1011011, // = 2
23 0b1001111, // = 3
24 0b1100110, // = 4
25 0b1101101, // = 5
26 0b1111101, // = 6
27 0b0000111, // = 7
28 0b1111111, // = 8
29 0b1101111, // = 9
30 0b1110111, // = A
31 0b1111100, // = B
32 0b1011000, // = C
33 0b1011110, // = D
34 0b1111001, // = E
35 0b1110001 // = F
36 };
37//---------------------------------------------------------------------------
38 template<typename T> class DisplayBasic7Segment : public Mitov::BasicDisplay<T>
39 {
40 typedef Mitov::BasicDisplay<T> inherited;
41
42 public:
43 Mitov::SimpleList<OpenWire::SourcePin> SegmentPins;
44
45 public:
46 bool InvertedSegments;
47
48 public:
49 DisplayBasic7Segment() :
50 InvertedSegments( false )
51 {
52 SegmentPins.SetCount(16);
53 }
54
55 };
56//---------------------------------------------------------------------------
57 class Display7Segment : public Mitov::DisplayBasic7Segment<long>
58 {
59 typedef Mitov::DisplayBasic7Segment<long> inherited;
60
61 protected:
62 virtual void DoReceive( void *_Data )
63 {
64 inherited::DoReceive( _Data );
65 UpdateDisplay();
66 }
67
68 virtual void UpdateDisplay()
69 {
70 int AValue = (Enabled) ? C_Segments[ FValue & 0xF ] : 0;
71 for( int i = 0; i < 16; ++i )
72 {
73 bool ABitValue = AValue & 1;
74 ABitValue ^= InvertedSegments;
75 SegmentPins[ i ].Notify( &ABitValue );
76 AValue >>= 1;
77 }
78 }
79
80 };
81//---------------------------------------------------------------------------
82 template<typename T> class DisplayBasicDynamic7Segment : public Mitov::DisplayBasic7Segment<T>
83 {
84 typedef Mitov::DisplayBasic7Segment<T> inherited;
85
86 public:
87 Mitov::SimpleList<OpenWire::SourcePin> DigitPins;
88
89 public:
90 unsigned long RefreshInterval = 1000;
91 bool InvertedDigits = false;
92
93 protected:
94 unsigned long FLastTime = 0;
95 int FDigit = 0;
96
97 protected:
98 virtual int GetSegmentsValue() = 0;
99
100 virtual void UpdateDisplay()
101 {
102 int AValue;
103 if( inherited::Enabled )
104 AValue = GetSegmentsValue();
105
106 else
107 AValue = 0;
108
109 for( int i = 0; i < DigitPins.size(); ++i )
110 {
111 bool ABitValue = false;
112 ABitValue ^= InvertedDigits;
113 DigitPins[ i ].Notify( &ABitValue );
114 }
115
116 for( int i = 0; i < 16; ++i )
117 {
118 bool ABitValue = AValue & 1;
119 ABitValue ^= inherited::InvertedSegments;
120 inherited::SegmentPins[ i ].Notify( &ABitValue );
121 AValue >>= 1;
122 }
123
124 AValue = FDigit;
125 for( int i = 0; i < DigitPins.size(); ++i )
126 {
127 bool ABitValue = ( AValue-- == 0 );
128 ABitValue ^= InvertedDigits;
129 DigitPins[ i ].Notify( &ABitValue );
130 }
131 }
132
133 public:
134 virtual void SystemLoopBegin( unsigned long currentMicros )
135 {
136 if( ( currentMicros - FLastTime ) < RefreshInterval )
137 return;
138
139 ++FDigit;
140
141 if( FDigit >= DigitPins.size() )
142 FDigit = 0;
143
144 FLastTime = currentMicros;
145 UpdateDisplay();
146 }
147
148 };
149//---------------------------------------------------------------------------
150 class DisplayIntegerDynamic7Segment : public Mitov::DisplayBasicDynamic7Segment<long>
151 {
152 typedef Mitov::DisplayBasicDynamic7Segment<long> inherited;
153
154 public:
155 bool LeadingZeroes = false;
156
157 protected:
158 Mitov::SimpleList<unsigned int> FPowers;
159 long FMaxValue; // The biggest possible to display value
160 long FMinValue; // The smallest possible to display value
161
162 protected:
163 virtual int GetSegmentsValue()
164 {
165 int AValue;
166 if( FValue > FMaxValue )
167 AValue = 0b0000001;
168
169 else if( FValue < FMinValue )
170 AValue = 0b0001000;
171
172 else
173 {
174 AValue = ( (int)abs( FValue ) ) / FPowers[ FDigit ];
175 if( ( FValue < 0 ) && ( FDigit > 0 ))
176 {
177 if( ( !LeadingZeroes ) && ( AValue == 0 ) )
178 {
179 int APreviousValue = ( -FValue ) / FPowers[ FDigit - 1 ];
180 if( APreviousValue > 0 )
181 AValue = 0b1000000;
182
183 else
184 AValue = 0;
185
186 }
187 else
188 {
189 if( FDigit == DigitPins.size() - 1 )
190 AValue = 0b1000000;
191
192 else
193 {
194 int ADigitValue = AValue % 10;
195 AValue = C_Segments[ ADigitValue ];
196 }
197 }
198 }
199 else
200 {
201 if( ( !LeadingZeroes ) && ( AValue == 0 ) )
202 AValue = 0;
203
204 else
205 {
206 int ADigitValue = AValue % 10;
207 AValue = C_Segments[ ADigitValue ];
208 }
209 }
210 }
211
212 return AValue;
213 }
214
215 virtual void SystemInit()
216 {
217 FPowers.SetCount( DigitPins.size() );
218 for( int i = 0; i < DigitPins.size(); ++i )
219 FPowers[ i ] = pow( 10, i ) + 0.5;
220
221 FMaxValue = pow( 10, DigitPins.size() ) + 0.5 - 1;
222 FMinValue = -( pow( 10, DigitPins.size() - 1 ) + 0.5 - 1 );
223
224 inherited::SystemInit();
225 }
226
227 };
228//---------------------------------------------------------------------------
229 class DisplayAnalogDynamic7Segment : public Mitov::DisplayBasicDynamic7Segment<float>
230 {
231 typedef Mitov::DisplayBasicDynamic7Segment<float> inherited;
232
233 public:
234 unsigned char Precision = 2;
235
236 protected:
237 char *FBuffer;
238 char *FStartChar;
239 unsigned char FTextLength;
240 unsigned char FFirstPos;
241
242 char FDecimalPointPos;
243
244 protected:
245 virtual int GetSegmentsValue()
246 {
247 int AValue;
248 int ANumDigits = DigitPins.size();
249 if( ! FStartChar )
250 {
251 FStartChar = dtostrf( FValue, 1, Precision, FBuffer );
252// Serial.println( FStartChar );
253 String AText( FStartChar );
254 FTextLength = AText.length(); // strlen( FStartChar );
255// FTextLength = strlen( FStartChar );
256// Serial.println( FTextLength );
257 FDecimalPointPos = AText.indexOf( '.' );
258 if( Precision == 0 )
259 {
260 if( FTextLength <= ANumDigits )
261 FFirstPos = FTextLength - 1;
262
263 else
264 FFirstPos = ANumDigits - 1;
265
266
267// Serial.println( FStartChar );
268// Serial.println( FTextLength );
269// Serial.println( FFirstPos );
270// Serial.println( FDecimalPointPos );
271 }
272
273 else
274 {
275 if( FTextLength <= ANumDigits + 1 )
276 FFirstPos = FTextLength - 1;
277
278 else
279 FFirstPos = ANumDigits + 1 - 1;
280 }
281
282// Serial.println( FFirstPos );
283 }
284
285 int ACorrectedTextLength = FTextLength;
286 if( Precision > 0 )
287 --ACorrectedTextLength;
288
289 if( ( ACorrectedTextLength - Precision ) > ANumDigits )
290 {
291 if( FValue > 0 )
292 AValue = 0b0000001; // Overflow +
293
294 else
295 AValue = 0b0001000; // Overflow -
296 }
297
298 else
299 {
300 int ATextPos = FFirstPos - FDigit;
301 if( ATextPos < 0 )
302 AValue = 0;
303
304 else
305 {
306 if( ATextPos < 0 )
307 return( 0 );
308
309 bool ADecimalPoint = ( FStartChar[ ATextPos ] == '.' );
310 if( ATextPos <= FDecimalPointPos )
311 --ATextPos;
312
313// if( ADecimalPoint )
314// --ATextPos;
315
316 if( ATextPos < 0 )
317 return( 0 );
318
319/*
320 if( FDigit == 0 )
321 {
322 Serial.println( FStartChar );
323 Serial.println( ATextPos );
324 }
325*/
326 if( FStartChar[ ATextPos ] == '-' )
327 AValue = 0b1000000;
328
329 else
330 {
331 AValue = FStartChar[ ATextPos ] - '0';
332 AValue = C_Segments[ AValue ];
333 }
334
335 if( ADecimalPoint )
336 AValue |= 0x80;
337
338 }
339 }
340
341 return AValue;
342 }
343
344 virtual void DoReceive( void *_Data )
345 {
346 FStartChar = NULL;
347 inherited::DoReceive( _Data );
348 }
349
350 public:
351 virtual void SystemInit()
352 {
353 FBuffer = new char[ 15 + Precision ];
354 inherited::SystemInit();
355 }
356
357/*
358 virtual ~DisplayAnalogDynamic7Segment()
359 {
360 delete [] FBuffer;
361 }
362*/
363 };
364
365}
366
367#endif