]> git.sur5r.net Git - freertos/blob
c4200c584a01fef077457a395e77153cbca2bb10
[freertos] /
1 /**************************************************************************//**\r
2  * @file\r
3  * @brief EFM32 Segment LCD Display driver\r
4  * @version 4.2.1\r
5  ******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * This file is licensed under the Silabs License Agreement. See the file\r
11  * "Silabs_License_Agreement.txt" for details. Before using this software for\r
12  * any purpose, you must agree to the terms of that agreement.\r
13  *\r
14  ******************************************************************************/\r
15 \r
16 \r
17 #include <stdio.h>\r
18 #include <string.h>\r
19 #include <stdlib.h>\r
20 #include <stdbool.h>\r
21 #include "em_device.h"\r
22 #include "em_cmu.h"\r
23 #include "em_gpio.h"\r
24 \r
25 #include "segmentlcd.h"\r
26 \r
27 /**************************************************************************//**\r
28  * @brief\r
29  * Defines each text symbol's segment in terms of COM and BIT numbers,\r
30  * in a way that we can enumerate each bit for each text segment in the\r
31  * following bit pattern:\r
32  * @verbatim\r
33  *  -------0------\r
34  *\r
35  * |   \7  |8  /9 |\r
36  * |5   \  |  /   |1\r
37  *\r
38  *  --6---  ---10--\r
39  *\r
40  * |    /  |  \11 |\r
41  * |4  /13 |12 \  |2\r
42  *\r
43  *  -------3------\r
44  * @endverbatim\r
45  * E.g.: First text character bit pattern #3 (above) is\r
46  *  Segment 1D for Display\r
47  *  Location COM 3, BIT 0\r
48  *****************************************************************************/\r
49 typedef struct\r
50 {\r
51   uint8_t com[14]; /**< LCD COM line (for multiplexing) */\r
52   uint8_t bit[14]; /**< LCD bit number */\r
53 } CHAR_TypeDef;\r
54 \r
55 \r
56 /**************************************************************************//**\r
57  * @brief Defines segment COM and BIT fields numeric display\r
58  *****************************************************************************/\r
59 typedef struct\r
60 {\r
61   uint8_t com[7]; /**< LCD COM line (for multiplexing) */\r
62   uint8_t bit[7]; /**< LCD bit number */\r
63 } NUMBER_TypeDef;\r
64 \r
65 /**************************************************************************//**\r
66  * @brief Defines segment COM and BIT fields for Energy Modes on display\r
67  *****************************************************************************/\r
68 typedef struct\r
69 {\r
70   uint8_t com[5]; /**< LCD COM line (for multiplexing) */\r
71   uint8_t bit[5]; /**< LCD bit number */\r
72 } EM_TypeDef;\r
73 \r
74 /**************************************************************************//**\r
75  * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)\r
76  *****************************************************************************/\r
77 typedef struct\r
78 {\r
79   uint8_t com[8]; /**< LCD COM line (for multiplexing) */\r
80   uint8_t bit[8]; /**< LCD bit number */\r
81 } ARING_TypeDef;\r
82 \r
83 /**************************************************************************//**\r
84  * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)\r
85  *****************************************************************************/\r
86 typedef struct\r
87 {\r
88   uint8_t com[4]; /**< LCD COM line (for multiplexing) */\r
89   uint8_t bit[4]; /**< LCD bit number */\r
90 } BATTERY_TypeDef;\r
91 \r
92 /**************************************************************************//**\r
93  * @brief Defines prototype for all segments in display\r
94  *****************************************************************************/\r
95 typedef struct\r
96 {\r
97   CHAR_TypeDef    Text[7];      /**< Text on display */\r
98   NUMBER_TypeDef  Number[4];    /**< Numbers on display */\r
99   EM_TypeDef      EMode;        /**< Display energy mode */\r
100   ARING_TypeDef   ARing;        /**< Display ring */\r
101   BATTERY_TypeDef Battery;      /**< Display battery */\r
102 } MCU_DISPLAY;\r
103 \r
104 /**************************************************************************//**\r
105  * @brief Working instance of LCD display\r
106  *****************************************************************************/\r
107 static const MCU_DISPLAY EFM_Display = EFM_DISPLAY_DEF;\r
108 \r
109 \r
110 /**************************************************************************//**\r
111  * @brief\r
112  * Defines higlighted segments for the alphabet, starting from "blank" (SPACE)\r
113  * Uses bit pattern as defined for text segments above.\r
114  * E.g. a capital O, would have bits 0 1 2 3 4 5 => 0x003f defined\r
115  *****************************************************************************/\r
116 static const uint16_t EFM_Alphabet[] = {\r
117   0x0000, /* space */\r
118   0x1100, /* ! */\r
119   0x0280, /* " */\r
120   0x0000, /* # */\r
121   0x0000, /* $ */\r
122   0x0602, /* % */\r
123   0x0000, /* & */\r
124   0x0020, /* ' */\r
125   0x0039, /* ( */\r
126   0x000f, /* ) */\r
127   0x0000, /* * */\r
128   0x1540, /* + */\r
129   0x2000, /* , */\r
130   0x0440, /* - */\r
131   0x1000, /* . */\r
132   0x2200, /* / */\r
133 \r
134   0x003f, /* 0 */\r
135   0x0006, /* 1 */\r
136   0x045b, /* 2 */\r
137   0x044f, /* 3 */\r
138   0x0466, /* 4 */\r
139   0x046d, /* 5 */\r
140   0x047d, /* 6 */\r
141   0x0007, /* 7 */\r
142   0x047f, /* 8 */\r
143   0x046f, /* 9 */\r
144 \r
145   0x0000, /* : */\r
146   0x0000, /* ; */\r
147   0x0a00, /* < */\r
148   0x0000, /* = */\r
149   0x2080, /* > */\r
150   0x0000, /* ? */\r
151   0xffff, /* @ */\r
152 \r
153   0x0477, /* A */\r
154   0x0a79, /* B */\r
155   0x0039, /* C */\r
156   0x20b0, /* D */\r
157   0x0079, /* E */\r
158   0x0071, /* F */\r
159   0x047d, /* G */\r
160   0x0476, /* H */\r
161   0x0006, /* I */\r
162   0x000e, /* J */\r
163   0x0a70, /* K */\r
164   0x0038, /* L */\r
165   0x02b6, /* M */\r
166   0x08b6, /* N */\r
167   0x003f, /* O */\r
168   0x0473, /* P */\r
169   0x083f, /* Q */\r
170   0x0c73, /* R */\r
171   0x046d, /* S */\r
172   0x1101, /* T */\r
173   0x003e, /* U */\r
174   0x2230, /* V */\r
175   0x2836, /* W */\r
176   0x2a80, /* X */\r
177   0x046e, /* Y */\r
178   0x2209, /* Z */\r
179 \r
180   0x0039, /* [ */\r
181   0x0880, /* backslash */\r
182   0x000f, /* ] */\r
183   0x0001, /* ^ */\r
184   0x0008, /* _ */\r
185   0x0100, /* ` */\r
186 \r
187   0x1058, /* a */\r
188   0x047c, /* b */\r
189   0x0058, /* c */\r
190   0x045e, /* d */\r
191   0x2058, /* e */\r
192   0x0471, /* f */\r
193   0x0c0c, /* g */\r
194   0x0474, /* h */\r
195   0x0004, /* i */\r
196   0x000e, /* j */\r
197   0x0c70, /* k */\r
198   0x0038, /* l */\r
199   0x1454, /* m */\r
200   0x0454, /* n */\r
201   0x045c, /* o */\r
202   0x0473, /* p */\r
203   0x0467, /* q */\r
204   0x0450, /* r */\r
205   0x0c08, /* s */\r
206   0x0078, /* t */\r
207   0x001c, /* u */\r
208   0x2010, /* v */\r
209   0x2814, /* w */\r
210   0x2a80, /* x */\r
211   0x080c, /* y */\r
212   0x2048, /* z */\r
213 \r
214   0x0000,\r
215 };\r
216 \r
217 /**************************************************************************//**\r
218  * @brief\r
219  * Defines higlighted segments for the numeric display\r
220  *****************************************************************************/\r
221 \r
222 static const uint16_t EFM_Numbers[] = {\r
223   0x003f, /* 0 */\r
224   0x0006, /* 1 */\r
225   0x005b, /* 2 */\r
226   0x004f, /* 3 */\r
227   0x0066, /* 4 */\r
228   0x006d, /* 5 */\r
229   0x007d, /* 6 */\r
230   0x0007, /* 7 */\r
231   0x007f, /* 8 */\r
232   0x006f, /* 9 */\r
233   0x0077, /* A */\r
234   0x007c, /* b */\r
235   0x0039, /* C */\r
236   0x005e, /* d */\r
237   0x0079, /* E */\r
238   0x0071, /* F */\r
239   0x0040  /* - */\r
240 };\r
241 \r
242 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
243 /* sign is last element of the table  */\r
244 static const uint16_t signIndex = sizeof(EFM_Numbers)/sizeof(uint16_t) - 1 ;\r
245 \r
246 static const LCD_Init_TypeDef lcdInit = LCD_INIT_DEF;\r
247 /** @endcond */\r
248 \r
249 \r
250 /**************************************************************************//**\r
251  * @brief Disable all segments\r
252  *****************************************************************************/\r
253 void SegmentLCD_AllOff(void)\r
254 {\r
255   /* Turn on low segments */\r
256   LCD_ALL_SEGMENTS_OFF();\r
257 }\r
258 \r
259 \r
260 /**************************************************************************//**\r
261  * @brief Enable all segments\r
262  *****************************************************************************/\r
263 void SegmentLCD_AllOn(void)\r
264 {\r
265   LCD_ALL_SEGMENTS_ON();\r
266 }\r
267 \r
268 \r
269 /**************************************************************************//**\r
270  * @brief Turn all segments on alpha characters in display off\r
271  *****************************************************************************/\r
272 void SegmentLCD_AlphaNumberOff(void)\r
273 {\r
274   LCD_ALPHA_NUMBER_OFF();\r
275   return;\r
276 }\r
277 \r
278 \r
279 /**************************************************************************//**\r
280  * @brief Light up or shut off Ring of Indicators\r
281  * @param anum "Segment number" on "Ring", range 0 - 7\r
282  * @param on Zero is off, non-zero is on\r
283  *****************************************************************************/\r
284 void SegmentLCD_ARing(int anum, int on)\r
285 {\r
286   uint32_t com, bit;\r
287 \r
288   com = EFM_Display.ARing.com[anum];\r
289   bit = EFM_Display.ARing.bit[anum];\r
290 \r
291   if (on)\r
292   {\r
293     LCD_SegmentSet(com, bit, true);\r
294   }\r
295   else\r
296   {\r
297     LCD_SegmentSet(com, bit, false);\r
298   }\r
299 }\r
300 \r
301 \r
302 /**************************************************************************//**\r
303  * @brief Light up or shut off Battery Indicator\r
304  * @param batteryLevel Battery Level, 0 to 4 (0 turns all off)\r
305  *****************************************************************************/\r
306 void SegmentLCD_Battery(int batteryLevel)\r
307 {\r
308   uint32_t com, bit;\r
309   int      i, on;\r
310 \r
311   for (i = 0; i < 4; i++)\r
312   {\r
313     if (i < batteryLevel)\r
314     {\r
315       on = 1;\r
316     }\r
317     else\r
318     {\r
319       on = 0;\r
320     }\r
321     com = EFM_Display.Battery.com[i];\r
322     bit = EFM_Display.Battery.bit[i];\r
323 \r
324     if (on)\r
325     {\r
326       LCD_SegmentSet(com, bit, true);\r
327     }\r
328     else\r
329     {\r
330       LCD_SegmentSet(com, bit, false);\r
331     }\r
332   }\r
333 }\r
334 \r
335 \r
336 /**************************************************************************//**\r
337  * @brief Disables LCD controller\r
338  *****************************************************************************/\r
339 void SegmentLCD_Disable(void)\r
340 {\r
341   /* Disable LCD */\r
342   LCD_Enable(false);\r
343 \r
344   /* Make sure CTRL register has been updated */\r
345   LCD_SyncBusyDelay(LCD_SYNCBUSY_CTRL);\r
346 \r
347   /* Turn off LCD clock */\r
348   CMU_ClockEnable(cmuClock_LCD, false);\r
349 \r
350   /* Turn off voltage boost if enabled */\r
351   CMU->LCDCTRL = 0;\r
352 }\r
353 \r
354 \r
355 /**************************************************************************//**\r
356  * @brief Light up or shut off Energy Mode indicator\r
357  * @param em Energy Mode numer 0 to 4\r
358  * @param on Zero is off, non-zero is on\r
359  *****************************************************************************/\r
360 void SegmentLCD_EnergyMode(int em, int on)\r
361 {\r
362   uint32_t com, bit;\r
363 \r
364   com = EFM_Display.EMode.com[em];\r
365   bit = EFM_Display.EMode.bit[em];\r
366 \r
367   if (on)\r
368   {\r
369     LCD_SegmentSet(com, bit, true);\r
370   }\r
371   else\r
372   {\r
373     LCD_SegmentSet(com, bit, false);\r
374   }\r
375 }\r
376 \r
377 \r
378 /**************************************************************************//**\r
379  * @brief Segment LCD Initialization routine for EFM32 STK display\r
380  * @param useBoost Set to use voltage boost\r
381  *****************************************************************************/\r
382 void SegmentLCD_Init(bool useBoost)\r
383 {\r
384 \r
385   /* Ensure LE modules are accessible */\r
386   CMU_ClockEnable(cmuClock_CORELE, true);\r
387 \r
388   /* Enable LFRCO as LFACLK in CMU (will also enable oscillator if not enabled) */\r
389   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);\r
390 \r
391   /* LCD Controller Prescaler  */\r
392   CMU_ClockDivSet(cmuClock_LCDpre, LCD_CMU_CLK_PRE);\r
393 \r
394   /* Frame Rate */\r
395   CMU_LCDClkFDIVSet(LCD_CMU_CLK_DIV);\r
396 \r
397   /* Enable clock to LCD module */\r
398   CMU_ClockEnable(cmuClock_LCD, true);\r
399 \r
400   LCD_DISPLAY_ENABLE();\r
401 \r
402   /* Disable interrupts */\r
403   LCD_IntDisable(0xFFFFFFFF);\r
404 \r
405   /* Initialize and enable LCD controller */\r
406   LCD_Init(&lcdInit);\r
407 \r
408   /* Enable all display segments */\r
409   LCD_SEGMENTS_ENABLE();\r
410 \r
411   /* Enable boost if necessary */\r
412   if (useBoost)\r
413   {\r
414     LCD_VBoostSet(LCD_BOOST_LEVEL);\r
415     LCD_VLCDSelect(lcdVLCDSelVExtBoost);\r
416     CMU->LCDCTRL |= CMU_LCDCTRL_VBOOSTEN;\r
417   }\r
418 \r
419   /* Turn all segments off */\r
420   SegmentLCD_AllOff();\r
421 \r
422   LCD_SyncBusyDelay(0xFFFFFFFF);\r
423 }\r
424 \r
425 \r
426 /**************************************************************************//**\r
427  * @brief Write a hexadecimal number on lower alphanumeric part of\r
428  *        Segment LCD display\r
429  * @param num Hexadecimal number value to put on display, in range 0\r
430  *        to 0x0FFFFFFF\r
431  *****************************************************************************/\r
432 void SegmentLCD_LowerHex( uint32_t num )\r
433 {\r
434   int       i;\r
435   char      str[7];\r
436   uint32_t  nibble;\r
437 \r
438   SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);\r
439 \r
440   for ( i=6; i>=0; i-- )\r
441   {\r
442     nibble = num & 0xF;\r
443 \r
444     if ( nibble < 10 )\r
445       str[i] = nibble + '0';\r
446     else if ( nibble == 11 )\r
447       str[i] = 'b';\r
448     else if ( nibble == 13 )\r
449       str[i] = 'd';\r
450     else\r
451       str[i] = (nibble - 10) + 'A';\r
452 \r
453     num >>= 4;\r
454   }\r
455 \r
456   SegmentLCD_Write(str);\r
457 }\r
458 \r
459 /**************************************************************************//**\r
460  * @brief Write number on lower alphanumeric part of Segment LCD display\r
461  * @param num Numeric value to put on display, in range -9999999 to +9999999\r
462  *****************************************************************************/\r
463 void SegmentLCD_LowerNumber( int num )\r
464 {\r
465   int i;\r
466   char str[7];\r
467 \r
468   SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);\r
469 \r
470   if ( ( num > 9999999 ) || ( num < -9999999 ) )\r
471   {\r
472     SegmentLCD_Write("Ovrflow");\r
473     return;\r
474   }\r
475 \r
476   if ( num < 0 )\r
477   {\r
478     SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 1);\r
479     num = -num;\r
480   }\r
481 \r
482   for ( i=6; i>=0; i-- )\r
483   {\r
484     if ( ( i < 6 ) && ( num == 0 ) )\r
485     {\r
486       str[i] = ' ';\r
487     }\r
488     else\r
489     {\r
490       str[i] = (num % 10) + '0';\r
491       num /= 10;\r
492     }\r
493   }\r
494 \r
495   SegmentLCD_Write(str);\r
496 }\r
497 \r
498 \r
499 /**************************************************************************//**\r
500  * @brief Write number on numeric part on Segment LCD display\r
501  * @param value Numeric value to put on display, in range -999 to +9999\r
502  *****************************************************************************/\r
503 void SegmentLCD_Number(int value)\r
504 {\r
505   int      i, com, bit, digit, div, neg;\r
506   uint16_t bitpattern;\r
507   uint16_t num;\r
508 \r
509   /* Parameter consistancy check */\r
510   if (value >= 9999)\r
511   {\r
512     value = 9999;\r
513   }\r
514   if (value <= -1000)\r
515   {\r
516     value = -999;\r
517   }\r
518   if (value < 0)\r
519   {\r
520     value = abs(value);\r
521     neg   = 1;\r
522   }\r
523   else\r
524   {\r
525     neg = 0;\r
526   }\r
527 \r
528   /* If an update is in progress we must block, or there might be tearing */\r
529   LCD_SyncBusyDelay(0xFFFFFFFF);\r
530 \r
531   /* Freeze updates to avoid partial refresh of display */\r
532   LCD_FreezeEnable(true);\r
533 \r
534   /* Turn off all number LCD segments */\r
535   SegmentLCD_NumberOff();\r
536 \r
537   /* Extract useful digits */\r
538   div = 1;\r
539   for (digit = 0; digit < 4; digit++)\r
540   {\r
541     num = (value / div) % 10;\r
542     if ((neg == 1) && (digit == 3)) num = signIndex;\r
543     /* Get number layout of display */\r
544     bitpattern = EFM_Numbers[num];\r
545     for (i = 0; i < 7; i++)\r
546     {\r
547       bit = EFM_Display.Number[digit].bit[i];\r
548       com = EFM_Display.Number[digit].com[i];\r
549       if (bitpattern & (1 << i))\r
550       {\r
551         LCD_SegmentSet(com, bit, true);\r
552       }\r
553     }\r
554     div = div * 10;\r
555   }\r
556   /* Sync LCD registers to LE domain */\r
557   LCD_FreezeEnable(false);\r
558 }\r
559 \r
560 \r
561 /**************************************************************************//**\r
562  * @brief Turn all segments on numeric digits in display off\r
563  *****************************************************************************/\r
564 void SegmentLCD_NumberOff(void)\r
565 {\r
566   /* Turn off all number segments */\r
567   LCD_NUMBER_OFF();\r
568   return;\r
569 }\r
570 \r
571 \r
572 /**************************************************************************//**\r
573  * @brief Light up or shut off various symbols on Segment LCD\r
574  * @param s Which symbol to turn on or off\r
575  * @param on Zero is off, non-zero is on\r
576  *****************************************************************************/\r
577 void SegmentLCD_Symbol(lcdSymbol s, int on)\r
578 {\r
579   int com = 0;\r
580   int bit = 0;\r
581 \r
582   switch (s)\r
583   {\r
584   case LCD_SYMBOL_GECKO:\r
585     com = LCD_SYMBOL_GECKO_COM;\r
586     bit = LCD_SYMBOL_GECKO_SEG;\r
587     break;\r
588   case LCD_SYMBOL_ANT:\r
589     com = LCD_SYMBOL_ANT_COM;\r
590     bit = LCD_SYMBOL_ANT_SEG;\r
591     break;\r
592   case LCD_SYMBOL_PAD0:\r
593     com = LCD_SYMBOL_PAD0_COM;\r
594     bit = LCD_SYMBOL_PAD0_SEG;\r
595     break;\r
596   case LCD_SYMBOL_PAD1:\r
597     com = LCD_SYMBOL_PAD1_COM;\r
598     bit = LCD_SYMBOL_PAD1_SEG;\r
599     break;\r
600   case LCD_SYMBOL_EFM32:\r
601     com = LCD_SYMBOL_EFM32_COM;\r
602     bit = LCD_SYMBOL_EFM32_SEG;\r
603     break;\r
604   case LCD_SYMBOL_MINUS:\r
605     com = LCD_SYMBOL_MINUS_COM;\r
606     bit = LCD_SYMBOL_MINUS_SEG;\r
607     break;\r
608   case LCD_SYMBOL_COL3:\r
609     com = LCD_SYMBOL_COL3_COM;\r
610     bit = LCD_SYMBOL_COL3_SEG;\r
611     break;\r
612   case LCD_SYMBOL_COL5:\r
613     com = LCD_SYMBOL_COL5_COM;\r
614     bit = LCD_SYMBOL_COL5_SEG;\r
615     break;\r
616   case LCD_SYMBOL_COL10:\r
617     com = LCD_SYMBOL_COL10_COM;\r
618     bit = LCD_SYMBOL_COL10_SEG;\r
619     break;\r
620 #ifdef LCD_SYMBOL_DEGC_SEG\r
621   case LCD_SYMBOL_DEGC:\r
622     com = LCD_SYMBOL_DEGC_COM;\r
623     bit = LCD_SYMBOL_DEGC_SEG;\r
624     break;\r
625 #endif\r
626 #ifdef LCD_SYMBOL_DEGF_SEG\r
627   case LCD_SYMBOL_DEGF:\r
628     com = LCD_SYMBOL_DEGF_COM;\r
629     bit = LCD_SYMBOL_DEGF_SEG;\r
630     break;\r
631 #endif\r
632 #ifdef LCD_SYMBOL_DP2_SEG\r
633   case LCD_SYMBOL_DP2:\r
634     com = LCD_SYMBOL_DP2_COM;\r
635     bit = LCD_SYMBOL_DP2_SEG;\r
636     break;\r
637 #endif\r
638 #ifdef LCD_SYMBOL_DP3_SEG\r
639   case LCD_SYMBOL_DP3:\r
640     com = LCD_SYMBOL_DP3_COM;\r
641     bit = LCD_SYMBOL_DP3_SEG;\r
642     break;\r
643 #endif\r
644 #ifdef LCD_SYMBOL_DP4_SEG\r
645   case LCD_SYMBOL_DP4:\r
646     com = LCD_SYMBOL_DP4_COM;\r
647     bit = LCD_SYMBOL_DP4_SEG;\r
648     break;\r
649 #endif\r
650 #ifdef LCD_SYMBOL_DP5_SEG\r
651   case LCD_SYMBOL_DP5:\r
652     com = LCD_SYMBOL_DP5_COM;\r
653     bit = LCD_SYMBOL_DP5_SEG;\r
654     break;\r
655 #endif\r
656   case LCD_SYMBOL_DP6:\r
657     com = LCD_SYMBOL_DP6_COM;\r
658     bit = LCD_SYMBOL_DP6_SEG;\r
659     break;\r
660   case LCD_SYMBOL_DP10:\r
661     com = LCD_SYMBOL_DP10_COM;\r
662     bit = LCD_SYMBOL_DP10_SEG;\r
663     break;\r
664 #ifdef LCD_SYMBOL_AM_SEG\r
665   case LCD_SYMBOL_AM:\r
666     com = LCD_SYMBOL_AM_COM;\r
667     bit = LCD_SYMBOL_AM_SEG;\r
668     break;\r
669 #endif\r
670 #ifdef LCD_SYMBOL_PM_SEG\r
671   case LCD_SYMBOL_PM:\r
672     com = LCD_SYMBOL_PM_COM;\r
673     bit = LCD_SYMBOL_PM_SEG;\r
674     break;\r
675 #endif\r
676 #ifdef LCD_SYMBOL_MICROAMP_SEG\r
677   case LCD_SYMBOL_MICROAMP:\r
678     com = LCD_SYMBOL_MICROAMP_COM;\r
679     bit = LCD_SYMBOL_MICROAMP_SEG;\r
680     break;\r
681 #endif\r
682 #ifdef LCD_SYMBOL_MILLIAMP_SEG\r
683   case LCD_SYMBOL_MILLIAMP:\r
684     com = LCD_SYMBOL_MILLIAMP_COM;\r
685     bit = LCD_SYMBOL_MILLIAMP_SEG;\r
686     break;\r
687 #endif\r
688 \r
689   }\r
690   if (on)\r
691   {\r
692     LCD_SegmentSet(com, bit, true);\r
693   }\r
694   else\r
695   {\r
696     LCD_SegmentSet(com, bit, false);\r
697   }\r
698 }\r
699 \r
700 \r
701 /**************************************************************************//**\r
702  * @brief Write hexadecimal number on numeric part on Segment LCD display\r
703  * @param value Numeric value to put on display, in range 0x0000-0xFFFF\r
704  *****************************************************************************/\r
705 void SegmentLCD_UnsignedHex(uint16_t value)\r
706 {\r
707   int      num, i, com, bit, digit;\r
708   uint16_t bitpattern;\r
709 \r
710   /* Parameter consistancy check */\r
711   if (value >= 0xffff)\r
712   {\r
713     value = 0xffff;\r
714   }\r
715 \r
716   /* If an update is in progress we must block, or there might be tearing */\r
717   LCD_SyncBusyDelay(0xFFFFFFFF);\r
718 \r
719   /* Freeze updates to avoid partial refresh of display */\r
720   LCD_FreezeEnable(true);\r
721 \r
722   /* Turn off all number LCD segments */\r
723   SegmentLCD_NumberOff();\r
724 \r
725   for (digit = 0; digit < 4; digit++)\r
726   {\r
727     num        = (value >> (4 * digit)) & 0x0f;\r
728     bitpattern = EFM_Numbers[num];\r
729     for (i = 0; i < 7; i++)\r
730     {\r
731       bit = EFM_Display.Number[digit].bit[i];\r
732       com = EFM_Display.Number[digit].com[i];\r
733       if (bitpattern & (1 << i))\r
734       {\r
735         LCD_SegmentSet(com, bit, true);\r
736       }\r
737     }\r
738   }\r
739 \r
740   /* Sync LCD registers to LE domain */\r
741   LCD_FreezeEnable(false);\r
742 }\r
743 \r
744 \r
745 /**************************************************************************//**\r
746  * @brief Write text on LCD display\r
747  * @param string Text string to show on display\r
748  *****************************************************************************/\r
749 void SegmentLCD_Write(char *string)\r
750 {\r
751   int      data, length, index;\r
752   uint16_t bitfield;\r
753   uint32_t com, bit;\r
754   int      i;\r
755 \r
756   length = strlen(string);\r
757   index  = 0;\r
758 \r
759   /* If an update is in progress we must block, or there might be tearing */\r
760   LCD_SyncBusyDelay(0xFFFFFFFF);\r
761 \r
762   /* Freeze LCD to avoid partial updates */\r
763   LCD_FreezeEnable(true);\r
764 \r
765   /* Turn all segments off */\r
766   SegmentLCD_AlphaNumberOff();\r
767 \r
768   /* Fill out all characters on display */\r
769   for (index = 0; index < 7; index++)\r
770   {\r
771     if (index < length)\r
772     {\r
773       data = (int) *string;\r
774     }\r
775     else           /* Padding with space */\r
776     {\r
777       data = 0x20; /* SPACE */\r
778     }\r
779     /* Defined letters currently starts at "SPACE" - ASCII 0x20; */\r
780     data = data - 0x20;\r
781     /* Get font for this letter */\r
782     bitfield = EFM_Alphabet[data];\r
783 \r
784     for (i = 0; i < 14; i++)\r
785     {\r
786       bit = EFM_Display.Text[index].bit[i];\r
787       com = EFM_Display.Text[index].com[i];\r
788 \r
789       if (bitfield & (1 << i))\r
790       {\r
791         /* Turn on segment */\r
792         LCD_SegmentSet(com, bit, true);\r
793       }\r
794     }\r
795     string++;\r
796   }\r
797   /* Enable update */\r
798   LCD_FreezeEnable(false);\r
799 }\r