Martin Sivak / EFM32_SegmentLCD

Fork of EFM32_SegmentLCD by Silicon Labs

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers segmentlcd.c Source File

segmentlcd.c

Go to the documentation of this file.
00001 /**************************************************************************//**
00002  * @file
00003  * @brief EFM32 Segment LCD Display driver
00004  * @version 3.20.9
00005  ******************************************************************************
00006  * @section License
00007  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
00008  *******************************************************************************
00009  *
00010  * This file is licensensed under the Silabs License Agreement. See the file
00011  * "Silabs_License_Agreement.txt" for details. Before using this software for
00012  * any purpose, you must agree to the terms of that agreement.
00013  *
00014  ******************************************************************************/
00015 
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include <stdlib.h>
00019 #include <stdbool.h>
00020 #include "clocking.h"
00021 #include "em_device.h"
00022 #include "em_cmu.h"
00023 #include "em_gpio.h"
00024 
00025 #include "device_peripherals.h"
00026 
00027 #include "segmentlcd.h"
00028 
00029 /**************************************************************************//**
00030  * @brief
00031  * Defines each text symbol's segment in terms of COM and BIT numbers,
00032  * in a way that we can enumerate each bit for each text segment in the
00033  * following bit pattern:
00034  * @verbatim
00035  *  -------0------
00036  *
00037  * |   \7  |8  /9 |
00038  * |5   \  |  /   |1
00039  *
00040  *  --6---  ---10--
00041  *
00042  * |    /  |  \11 |
00043  * |4  /13 |12 \  |2
00044  *
00045  *  -------3------
00046  * @endverbatim
00047  * E.g.: First text character bit pattern #3 (above) is
00048  *  Segment 1D for Display
00049  *  Location COM 3, BIT 0
00050  *****************************************************************************/
00051 typedef struct
00052 {
00053   uint8_t com[14]; /**< LCD COM line (for multiplexing) */
00054   uint8_t bit[14]; /**< LCD bit number */
00055 } CHAR_TypeDef;
00056 
00057 
00058 /**************************************************************************//**
00059  * @brief Defines segment COM and BIT fields numeric display
00060  *****************************************************************************/
00061 typedef struct
00062 {
00063   uint8_t com[7]; /**< LCD COM line (for multiplexing) */
00064   uint8_t bit[7]; /**< LCD bit number */
00065 } NUMBER_TypeDef;
00066 
00067 /**************************************************************************//**
00068  * @brief Defines segment COM and BIT fields for Energy Modes on display
00069  *****************************************************************************/
00070 typedef struct
00071 {
00072   uint8_t com[5]; /**< LCD COM line (for multiplexing) */
00073   uint8_t bit[5]; /**< LCD bit number */
00074 } EM_TypeDef;
00075 
00076 /**************************************************************************//**
00077  * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)
00078  *****************************************************************************/
00079 typedef struct
00080 {
00081   uint8_t com[8]; /**< LCD COM line (for multiplexing) */
00082   uint8_t bit[8]; /**< LCD bit number */
00083 } ARING_TypeDef;
00084 
00085 /**************************************************************************//**
00086  * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)
00087  *****************************************************************************/
00088 typedef struct
00089 {
00090   uint8_t com[4]; /**< LCD COM line (for multiplexing) */
00091   uint8_t bit[4]; /**< LCD bit number */
00092 } BATTERY_TypeDef;
00093 
00094 /**************************************************************************//**
00095  * @brief Defines prototype for all segments in display
00096  *****************************************************************************/
00097 typedef struct
00098 {
00099   CHAR_TypeDef    Text[7];      /**< Text on display */
00100   NUMBER_TypeDef  Number[4];    /**< Numbers on display */
00101   EM_TypeDef      EMode;        /**< Display energy mode */
00102   ARING_TypeDef   ARing;        /**< Display ring */
00103   BATTERY_TypeDef Battery;      /**< Display battery */
00104 } MCU_DISPLAY;
00105 
00106 /**************************************************************************//**
00107  * @brief Working instance of LCD display
00108  *****************************************************************************/
00109 static const MCU_DISPLAY EFM_Display = EFM_DISPLAY_DEF;
00110 
00111 
00112 /**************************************************************************//**
00113  * @brief
00114  * Defines higlighted segments for the alphabet, starting from "blank" (SPACE)
00115  * Uses bit pattern as defined for text segments above.
00116  * E.g. a capital O, would have bits 0 1 2 3 4 5 => 0x003f defined
00117  *****************************************************************************/
00118 static const uint16_t EFM_Alphabet[] = {
00119   0x0000, /* space */
00120   0x1100, /* ! */
00121   0x0280, /* " */
00122   0x0000, /* # */
00123   0x0000, /* $ */
00124   0x0602, /* % */
00125   0x0000, /* & */
00126   0x0020, /* ' */
00127   0x0039, /* ( */
00128   0x000f, /* ) */
00129   0x0000, /* * */
00130   0x1540, /* + */
00131   0x2000, /* , */
00132   0x0440, /* - */
00133   0x1000, /* . */
00134   0x2200, /* / */
00135 
00136   0x003f, /* 0 */
00137   0x0006, /* 1 */
00138   0x045b, /* 2 */
00139   0x044f, /* 3 */
00140   0x0466, /* 4 */
00141   0x046d, /* 5 */
00142   0x047d, /* 6 */
00143   0x0007, /* 7 */
00144   0x047f, /* 8 */
00145   0x046f, /* 9 */
00146 
00147   0x0000, /* : */
00148   0x0000, /* ; */
00149   0x0a00, /* < */
00150   0x0000, /* = */
00151   0x2080, /* > */
00152   0x0000, /* ? */
00153   0xffff, /* @ */
00154 
00155   0x0477, /* A */
00156   0x0a79, /* B */
00157   0x0039, /* C */
00158   0x20b0, /* D */
00159   0x0079, /* E */
00160   0x0071, /* F */
00161   0x047d, /* G */
00162   0x0476, /* H */
00163   0x0006, /* I */
00164   0x000e, /* J */
00165   0x0a70, /* K */
00166   0x0038, /* L */
00167   0x02b6, /* M */
00168   0x08b6, /* N */
00169   0x003f, /* O */
00170   0x0473, /* P */
00171   0x083f, /* Q */
00172   0x0c73, /* R */
00173   0x046d, /* S */
00174   0x1101, /* T */
00175   0x003e, /* U */
00176   0x2230, /* V */
00177   0x2836, /* W */
00178   0x2a80, /* X */
00179   0x046e, /* Y */
00180   0x2209, /* Z */
00181 
00182   0x0039, /* [ */
00183   0x0880, /* backslash */
00184   0x000f, /* ] */
00185   0x0001, /* ^ */
00186   0x0008, /* _ */
00187   0x0100, /* ` */
00188 
00189   0x1058, /* a */
00190   0x047c, /* b */
00191   0x0058, /* c */
00192   0x045e, /* d */
00193   0x2058, /* e */
00194   0x0471, /* f */
00195   0x0c0c, /* g */
00196   0x0474, /* h */
00197   0x0004, /* i */
00198   0x000e, /* j */
00199   0x0c70, /* k */
00200   0x0038, /* l */
00201   0x1454, /* m */
00202   0x0454, /* n */
00203   0x045c, /* o */
00204   0x0473, /* p */
00205   0x0467, /* q */
00206   0x0450, /* r */
00207   0x0c08, /* s */
00208   0x0078, /* t */
00209   0x001c, /* u */
00210   0x2010, /* v */
00211   0x2814, /* w */
00212   0x2a80, /* x */
00213   0x080c, /* y */
00214   0x2048, /* z */
00215 
00216   0x0000,
00217 };
00218 
00219 /**************************************************************************//**
00220  * @brief
00221  * Defines higlighted segments for the numeric display
00222  *****************************************************************************/
00223 
00224 static const uint16_t EFM_Numbers[] = {
00225   0x003f, /* 0 */
00226   0x0006, /* 1 */
00227   0x005b, /* 2 */
00228   0x004f, /* 3 */
00229   0x0066, /* 4 */
00230   0x006d, /* 5 */
00231   0x007d, /* 6 */
00232   0x0007, /* 7 */
00233   0x007f, /* 8 */
00234   0x006f, /* 9 */
00235   0x0077, /* A */
00236   0x007c, /* b */
00237   0x0039, /* C */
00238   0x005e, /* d */
00239   0x0079, /* E */
00240   0x0071, /* F */
00241   0x0040  /* - */
00242 };
00243 
00244 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
00245 /* sign is last element of the table  */
00246 static const uint16_t signIndex = sizeof(EFM_Numbers)/sizeof(uint16_t) - 1 ;
00247 
00248 static const LCD_Init_TypeDef lcdInit = LCD_INIT_DEF;
00249 /** @endcond */
00250 
00251 
00252 /**************************************************************************//**
00253  * @brief Disable all segments
00254  *****************************************************************************/
00255 void SegmentLCD_AllOff(void)
00256 {
00257   /* Turn on low segments */
00258   LCD_ALL_SEGMENTS_OFF();
00259 }
00260 
00261 
00262 /**************************************************************************//**
00263  * @brief Enable all segments
00264  *****************************************************************************/
00265 void SegmentLCD_AllOn(void)
00266 {
00267   LCD_ALL_SEGMENTS_ON();
00268 }
00269 
00270 
00271 /**************************************************************************//**
00272  * @brief Turn all segments on alpha characters in display off
00273  *****************************************************************************/
00274 void SegmentLCD_AlphaNumberOff(void)
00275 {
00276   LCD_ALPHA_NUMBER_OFF();
00277   return;
00278 }
00279 
00280 
00281 /**************************************************************************//**
00282  * @brief Light up or shut off Ring of Indicators
00283  * @param anum "Segment number" on "Ring", range 0 - 7
00284  * @param on Zero is off, non-zero is on
00285  *****************************************************************************/
00286 void SegmentLCD_ARing(int anum, int on)
00287 {
00288   uint32_t com, bit;
00289 
00290   com = EFM_Display.ARing.com[anum];
00291   bit = EFM_Display.ARing.bit[anum];
00292 
00293   if (on)
00294   {
00295     LCD_SegmentSet(com, bit, true);
00296   }
00297   else
00298   {
00299     LCD_SegmentSet(com, bit, false);
00300   }
00301 }
00302 
00303 
00304 /**************************************************************************//**
00305  * @brief Light up or shut off Battery Indicator
00306  * @param batteryLevel Battery Level, 0 to 4 (0 turns all off)
00307  *****************************************************************************/
00308 void SegmentLCD_Battery(int batteryLevel)
00309 {
00310   uint32_t com, bit;
00311   int      i, on;
00312 
00313   for (i = 0; i < 4; i++)
00314   {
00315     if (i < batteryLevel)
00316     {
00317       on = 1;
00318     }
00319     else
00320     {
00321       on = 0;
00322     }
00323     com = EFM_Display.Battery.com[i];
00324     bit = EFM_Display.Battery.bit[i];
00325 
00326     if (on)
00327     {
00328       LCD_SegmentSet(com, bit, true);
00329     }
00330     else
00331     {
00332       LCD_SegmentSet(com, bit, false);
00333     }
00334   }
00335 }
00336 
00337 
00338 /**************************************************************************//**
00339  * @brief Disables LCD controller
00340  *****************************************************************************/
00341 void SegmentLCD_Disable(void)
00342 {
00343   /* Disable LCD */
00344   LCD_Enable(false);
00345 
00346   /* Make sure CTRL register has been updated */
00347   LCD_SyncBusyDelay(LCD_SYNCBUSY_CTRL);
00348 
00349   /* Turn off LCD clock */
00350   CMU_ClockEnable(cmuClock_LCD, false);
00351 
00352   /* Turn off voltage boost if enabled */
00353   CMU->LCDCTRL = 0;
00354 }
00355 
00356 
00357 /**************************************************************************//**
00358  * @brief Light up or shut off Energy Mode indicator
00359  * @param em Energy Mode numer 0 to 4
00360  * @param on Zero is off, non-zero is on
00361  *****************************************************************************/
00362 void SegmentLCD_EnergyMode(int em, int on)
00363 {
00364   uint32_t com, bit;
00365 
00366   com = EFM_Display.EMode.com[em];
00367   bit = EFM_Display.EMode.bit[em];
00368 
00369   if (on)
00370   {
00371     LCD_SegmentSet(com, bit, true);
00372   }
00373   else
00374   {
00375     LCD_SegmentSet(com, bit, false);
00376   }
00377 }
00378 
00379 /**************************************************************************//**
00380  * @brief Get frame rate division value corresponding to mux selection
00381  * @param mux enum
00382  *****************************************************************************/
00383 uint8_t SegmentLCD_GetFrameRateDiv(LCD_Mux_TypeDef muxSetting) {
00384     switch(muxSetting) {
00385       /** Static (segments can be multiplexed with LCD_COM[0]) */
00386     case lcdMuxStatic: return 2;
00387       /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */
00388     case lcdMuxDuplex: return 4;
00389       /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */
00390     case lcdMuxTriplex: return 6;
00391       /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */
00392     case lcdMuxQuadruplex: return 8;
00393     #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00394       /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
00395     case lcdMuxSextaplex: return 12;
00396       /** Octaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
00397     case lcdMuxOctaplex: return 16;
00398     #endif
00399     default: return 1;
00400     }
00401 }
00402 
00403 /**************************************************************************//**
00404  * @brief Segment LCD Initialization routine for EFM32 STK display
00405  * @param useBoost Set to use voltage boost
00406  *****************************************************************************/
00407 void SegmentLCD_Init(bool useBoost)
00408 {
00409 
00410   /* Ensure LE modules are accessible */
00411   CMU_ClockEnable(cmuClock_CORELE, true);
00412 
00413   /* Enable LFRCO as LFACLK in CMU (will also enable oscillator if not enabled) */
00414   CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
00415 
00416   /* LCD Controller Prescaler  */
00417 
00418   /* Calculate value. Approach 50Hz for framerate. */
00419   uint32_t prescaler = (LOW_ENERGY_CLOCK_FREQUENCY / 32) / SegmentLCD_GetFrameRateDiv(lcdInit.mux);
00420 
00421   CMU_ClockDivSet(cmuClock_LCDpre, prescaler);
00422 
00423   /* Frame Rate */
00424   CMU_LCDClkFDIVSet(0);
00425 
00426   /* Enable clock to LCD module */
00427   CMU_ClockEnable(cmuClock_LCD, true);
00428 
00429   LCD_DISPLAY_ENABLE();
00430 
00431   /* Disable interrupts */
00432   LCD_IntDisable(0xFFFFFFFF);
00433 
00434   /* Initialize and enable LCD controller */
00435   LCD_Init(&lcdInit);
00436 
00437   /* Enable all display segments */
00438   LCD_SEGMENTS_ENABLE();
00439 
00440   /* Enable boost if necessary */
00441   if (useBoost)
00442   {
00443     LCD_VBoostSet(LCD_BOOST_LEVEL);
00444     LCD_VLCDSelect(lcdVLCDSelVExtBoost);
00445     CMU->LCDCTRL |= CMU_LCDCTRL_VBOOSTEN;
00446   }
00447 
00448   /* Turn all segments off */
00449   SegmentLCD_AllOff();
00450 
00451   LCD_SyncBusyDelay(0xFFFFFFFF);
00452 }
00453 
00454 
00455 /**************************************************************************//**
00456  * @brief Write a hexadecimal number on lower alphanumeric part of
00457  *        Segment LCD display
00458  * @param num Hexadecimal number value to put on display, in range 0
00459  *        to 0x0FFFFFFF
00460  *****************************************************************************/
00461 void SegmentLCD_LowerHex( uint32_t num )
00462 {
00463   int       i;
00464   char      str[7];
00465   uint32_t  nibble;
00466 
00467   SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);
00468 
00469   for ( i=6; i>=0; i-- )
00470   {
00471     nibble = num & 0xF;
00472 
00473     if ( nibble < 10 )
00474       str[i] = nibble + '0';
00475     else if ( nibble == 11 )
00476       str[i] = 'b';
00477     else if ( nibble == 13 )
00478       str[i] = 'd';
00479     else
00480       str[i] = (nibble - 10) + 'A';
00481 
00482     num >>= 4;
00483   }
00484 
00485   SegmentLCD_Write(str);
00486 }
00487 
00488 /**************************************************************************//**
00489  * @brief Write number on lower alphanumeric part of Segment LCD display
00490  * @param num Numeric value to put on display, in range -9999999 to +9999999
00491  *****************************************************************************/
00492 void SegmentLCD_LowerNumber( int num )
00493 {
00494   int i;
00495   char str[7];
00496 
00497   SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);
00498 
00499   if ( ( num > 9999999 ) || ( num < -9999999 ) )
00500   {
00501     SegmentLCD_Write("Ovrflow");
00502     return;
00503   }
00504 
00505   if ( num < 0 )
00506   {
00507     SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 1);
00508     num = -num;
00509   }
00510 
00511   for ( i=6; i>=0; i-- )
00512   {
00513     if ( ( i < 6 ) && ( num == 0 ) )
00514     {
00515       str[i] = ' ';
00516     }
00517     else
00518     {
00519       str[i] = (num % 10) + '0';
00520       num /= 10;
00521     }
00522   }
00523 
00524   SegmentLCD_Write(str);
00525 }
00526 
00527 
00528 /**************************************************************************//**
00529  * @brief Write number on numeric part on Segment LCD display
00530  * @param value Numeric value to put on display, in range -999 to +9999
00531  *****************************************************************************/
00532 void SegmentLCD_Number(int value)
00533 {
00534   int      i, com, bit, digit, div, neg;
00535   uint16_t bitpattern;
00536   uint16_t num;
00537 
00538   /* Parameter consistancy check */
00539   if (value >= 9999)
00540   {
00541     value = 9999;
00542   }
00543   if (value <= -1000)
00544   {
00545     value = -999;
00546   }
00547   if (value < 0)
00548   {
00549     value = abs(value);
00550     neg   = 1;
00551   }
00552   else
00553   {
00554     neg = 0;
00555   }
00556 
00557   /* If an update is in progress we must block, or there might be tearing */
00558   LCD_SyncBusyDelay(0xFFFFFFFF);
00559 
00560   /* Freeze updates to avoid partial refresh of display */
00561   LCD_FreezeEnable(true);
00562 
00563   /* Turn off all number LCD segments */
00564   SegmentLCD_NumberOff();
00565 
00566   /* Extract useful digits */
00567   div = 1;
00568   for (digit = 0; digit < 4; digit++)
00569   {
00570     num = (value / div) % 10;
00571     if ((neg == 1) && (digit == 3)) num = signIndex;
00572     /* Get number layout of display */
00573     bitpattern = EFM_Numbers[num];
00574     for (i = 0; i < 7; i++)
00575     {
00576       bit = EFM_Display.Number[digit].bit[i];
00577       com = EFM_Display.Number[digit].com[i];
00578       if (bitpattern & (1 << i))
00579       {
00580         LCD_SegmentSet(com, bit, true);
00581       }
00582     }
00583     div = div * 10;
00584   }
00585   /* Sync LCD registers to LE domain */
00586   LCD_FreezeEnable(false);
00587 }
00588 
00589 
00590 /**************************************************************************//**
00591  * @brief Turn all segments on numeric digits in display off
00592  *****************************************************************************/
00593 void SegmentLCD_NumberOff(void)
00594 {
00595   /* Turn off all number segments */
00596   LCD_NUMBER_OFF();
00597   return;
00598 }
00599 
00600 
00601 /**************************************************************************//**
00602  * @brief Light up or shut off various symbols on Segment LCD
00603  * @param s Which symbol to turn on or off
00604  * @param on Zero is off, non-zero is on
00605  *****************************************************************************/
00606 void SegmentLCD_Symbol(lcdSymbol s, int on)
00607 {
00608   int com = 0;
00609   int bit = 0;
00610 
00611   switch (s)
00612   {
00613   case LCD_SYMBOL_GECKO:
00614     com = LCD_SYMBOL_GECKO_COM;
00615     bit = LCD_SYMBOL_GECKO_SEG;
00616     break;
00617   case LCD_SYMBOL_ANT:
00618     com = LCD_SYMBOL_ANT_COM;
00619     bit = LCD_SYMBOL_ANT_SEG;
00620     break;
00621   case LCD_SYMBOL_PAD0:
00622     com = LCD_SYMBOL_PAD0_COM;
00623     bit = LCD_SYMBOL_PAD0_SEG;
00624     break;
00625   case LCD_SYMBOL_PAD1:
00626     com = LCD_SYMBOL_PAD1_COM;
00627     bit = LCD_SYMBOL_PAD1_SEG;
00628     break;
00629   case LCD_SYMBOL_EFM32:
00630     com = LCD_SYMBOL_EFM32_COM;
00631     bit = LCD_SYMBOL_EFM32_SEG;
00632     break;
00633   case LCD_SYMBOL_MINUS:
00634     com = LCD_SYMBOL_MINUS_COM;
00635     bit = LCD_SYMBOL_MINUS_SEG;
00636     break;
00637   case LCD_SYMBOL_COL3:
00638     com = LCD_SYMBOL_COL3_COM;
00639     bit = LCD_SYMBOL_COL3_SEG;
00640     break;
00641   case LCD_SYMBOL_COL5:
00642     com = LCD_SYMBOL_COL5_COM;
00643     bit = LCD_SYMBOL_COL5_SEG;
00644     break;
00645   case LCD_SYMBOL_COL10:
00646     com = LCD_SYMBOL_COL10_COM;
00647     bit = LCD_SYMBOL_COL10_SEG;
00648     break;
00649 #ifdef LCD_SYMBOL_DEGC_SEG
00650   case LCD_SYMBOL_DEGC:
00651     com = LCD_SYMBOL_DEGC_COM;
00652     bit = LCD_SYMBOL_DEGC_SEG;
00653     break;
00654 #endif
00655 #ifdef LCD_SYMBOL_DEGF_SEG
00656   case LCD_SYMBOL_DEGF:
00657     com = LCD_SYMBOL_DEGF_COM;
00658     bit = LCD_SYMBOL_DEGF_SEG;
00659     break;
00660 #endif
00661 #ifdef LCD_SYMBOL_DP2_SEG
00662   case LCD_SYMBOL_DP2:
00663     com = LCD_SYMBOL_DP2_COM;
00664     bit = LCD_SYMBOL_DP2_SEG;
00665     break;
00666 #endif
00667 #ifdef LCD_SYMBOL_DP3_SEG
00668   case LCD_SYMBOL_DP3:
00669     com = LCD_SYMBOL_DP3_COM;
00670     bit = LCD_SYMBOL_DP3_SEG;
00671     break;
00672 #endif
00673 #ifdef LCD_SYMBOL_DP4_SEG
00674   case LCD_SYMBOL_DP4:
00675     com = LCD_SYMBOL_DP4_COM;
00676     bit = LCD_SYMBOL_DP4_SEG;
00677     break;
00678 #endif
00679 #ifdef LCD_SYMBOL_DP5_SEG
00680   case LCD_SYMBOL_DP5:
00681     com = LCD_SYMBOL_DP5_COM;
00682     bit = LCD_SYMBOL_DP5_SEG;
00683     break;
00684 #endif
00685   case LCD_SYMBOL_DP6:
00686     com = LCD_SYMBOL_DP6_COM;
00687     bit = LCD_SYMBOL_DP6_SEG;
00688     break;
00689   case LCD_SYMBOL_DP10:
00690     com = LCD_SYMBOL_DP10_COM;
00691     bit = LCD_SYMBOL_DP10_SEG;
00692     break;
00693 #ifdef LCD_SYMBOL_AM_SEG
00694   case LCD_SYMBOL_AM:
00695     com = LCD_SYMBOL_AM_COM;
00696     bit = LCD_SYMBOL_AM_SEG;
00697     break;
00698 #endif
00699 #ifdef LCD_SYMBOL_PM_SEG
00700   case LCD_SYMBOL_PM:
00701     com = LCD_SYMBOL_PM_COM;
00702     bit = LCD_SYMBOL_PM_SEG;
00703     break;
00704 #endif
00705 #ifdef LCD_SYMBOL_MICROAMP_SEG
00706   case LCD_SYMBOL_MICROAMP:
00707     com = LCD_SYMBOL_MICROAMP_COM;
00708     bit = LCD_SYMBOL_MICROAMP_SEG;
00709     break;
00710 #endif
00711 #ifdef LCD_SYMBOL_MILLIAMP_SEG
00712   case LCD_SYMBOL_MILLIAMP:
00713     com = LCD_SYMBOL_MILLIAMP_COM;
00714     bit = LCD_SYMBOL_MILLIAMP_SEG;
00715     break;
00716 #endif
00717 
00718   }
00719   if (on)
00720   {
00721     LCD_SegmentSet(com, bit, true);
00722   }
00723   else
00724   {
00725     LCD_SegmentSet(com, bit, false);
00726   }
00727 }
00728 
00729 
00730 /**************************************************************************//**
00731  * @brief Write hexadecimal number on numeric part on Segment LCD display
00732  * @param value Numeric value to put on display, in range 0x0000-0xFFFF
00733  *****************************************************************************/
00734 void SegmentLCD_UnsignedHex(uint16_t value)
00735 {
00736   int      num, i, com, bit, digit;
00737   uint16_t bitpattern;
00738 
00739   /* Parameter consistancy check */
00740   if (value >= 0xffff)
00741   {
00742     value = 0xffff;
00743   }
00744 
00745   /* If an update is in progress we must block, or there might be tearing */
00746   LCD_SyncBusyDelay(0xFFFFFFFF);
00747 
00748   /* Freeze updates to avoid partial refresh of display */
00749   LCD_FreezeEnable(true);
00750 
00751   /* Turn off all number LCD segments */
00752   SegmentLCD_NumberOff();
00753 
00754   for (digit = 0; digit < 4; digit++)
00755   {
00756     num        = (value >> (4 * digit)) & 0x0f;
00757     bitpattern = EFM_Numbers[num];
00758     for (i = 0; i < 7; i++)
00759     {
00760       bit = EFM_Display.Number[digit].bit[i];
00761       com = EFM_Display.Number[digit].com[i];
00762       if (bitpattern & (1 << i))
00763       {
00764         LCD_SegmentSet(com, bit, true);
00765       }
00766     }
00767   }
00768 
00769   /* Sync LCD registers to LE domain */
00770   LCD_FreezeEnable(false);
00771 }
00772 
00773 
00774 /**************************************************************************//**
00775  * @brief Write text on LCD display
00776  * @param string Text string to show on display
00777  *****************************************************************************/
00778 void SegmentLCD_Write(char *string)
00779 {
00780   int      data, length, index;
00781   uint16_t bitfield;
00782   uint32_t com, bit;
00783   int      i;
00784 
00785   length = strlen(string);
00786   index  = 0;
00787 
00788   /* If an update is in progress we must block, or there might be tearing */
00789   LCD_SyncBusyDelay(0xFFFFFFFF);
00790 
00791   /* Freeze LCD to avoid partial updates */
00792   LCD_FreezeEnable(true);
00793 
00794   /* Turn all segments off */
00795   SegmentLCD_AlphaNumberOff();
00796 
00797   /* Fill out all characters on display */
00798   for (index = 0; index < 7; index++)
00799   {
00800     if (index < length)
00801     {
00802       data = (int) *string;
00803     }
00804     else           /* Padding with space */
00805     {
00806       data = 0x20; /* SPACE */
00807     }
00808     /* Defined letters currently starts at "SPACE" - ASCII 0x20; */
00809     data = data - 0x20;
00810     /* Get font for this letter */
00811     bitfield = EFM_Alphabet[data];
00812 
00813     for (i = 0; i < 14; i++)
00814     {
00815       bit = EFM_Display.Text[index].bit[i];
00816       com = EFM_Display.Text[index].com[i];
00817 
00818       if (bitfield & (1 << i))
00819       {
00820         /* Turn on segment */
00821         LCD_SegmentSet(com, bit, true);
00822       }
00823     }
00824     string++;
00825   }
00826   /* Enable update */
00827   LCD_FreezeEnable(false);
00828 }