This is a driver for the segment LCD found on the Silicon Labs EF32 Giant, Leopard and Wonder Gecko platforms. NOTE: This driver will not work with other platforms, because it contains EFM32-specific code.

Dependents:   EFM32 RDA5807M RDS Radio EMF32-Segment-Touch-Demo EMF32_ShowKey blinky_EFM32_Giant ... more

Information

All examples in this repo are considered EXPERIMENTAL QUALITY, meaning this code has been created as one-off proof-of-concept and is suitable as a demonstration for experimental purposes only. This code will not be regularly maintained by Silicon Labs and there is no guarantee that these projects will work across all environments, SDK versions and hardware.

/media/uploads/stevew817/screenshot_2015-03-17_11.17.52.png

segmentlcd.c

Committer:
stevew817
Date:
2015-05-04
Revision:
6:114aa75da77b
Parent:
0:559902e88130

File content as of revision 6:114aa75da77b:

/**************************************************************************//**
 * @file
 * @brief EFM32 Segment LCD Display driver
 * @version 3.20.9
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensensed under the Silabs License Agreement. See the file
 * "Silabs_License_Agreement.txt" for details. Before using this software for
 * any purpose, you must agree to the terms of that agreement.
 *
 ******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "em_device.h"
#include "em_cmu.h"
#include "em_gpio.h"

#include "device_peripherals.h"

#include "segmentlcd.h"

/**************************************************************************//**
 * @brief
 * Defines each text symbol's segment in terms of COM and BIT numbers,
 * in a way that we can enumerate each bit for each text segment in the
 * following bit pattern:
 * @verbatim
 *  -------0------
 *
 * |   \7  |8  /9 |
 * |5   \  |  /   |1
 *
 *  --6---  ---10--
 *
 * |    /  |  \11 |
 * |4  /13 |12 \  |2
 *
 *  -------3------
 * @endverbatim
 * E.g.: First text character bit pattern #3 (above) is
 *  Segment 1D for Display
 *  Location COM 3, BIT 0
 *****************************************************************************/
typedef struct
{
  uint8_t com[14]; /**< LCD COM line (for multiplexing) */
  uint8_t bit[14]; /**< LCD bit number */
} CHAR_TypeDef;


/**************************************************************************//**
 * @brief Defines segment COM and BIT fields numeric display
 *****************************************************************************/
typedef struct
{
  uint8_t com[7]; /**< LCD COM line (for multiplexing) */
  uint8_t bit[7]; /**< LCD bit number */
} NUMBER_TypeDef;

/**************************************************************************//**
 * @brief Defines segment COM and BIT fields for Energy Modes on display
 *****************************************************************************/
typedef struct
{
  uint8_t com[5]; /**< LCD COM line (for multiplexing) */
  uint8_t bit[5]; /**< LCD bit number */
} EM_TypeDef;

/**************************************************************************//**
 * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)
 *****************************************************************************/
typedef struct
{
  uint8_t com[8]; /**< LCD COM line (for multiplexing) */
  uint8_t bit[8]; /**< LCD bit number */
} ARING_TypeDef;

/**************************************************************************//**
 * @brief Defines segment COM and BIT fields for A-wheel (suited for Anim)
 *****************************************************************************/
typedef struct
{
  uint8_t com[4]; /**< LCD COM line (for multiplexing) */
  uint8_t bit[4]; /**< LCD bit number */
} BATTERY_TypeDef;

/**************************************************************************//**
 * @brief Defines prototype for all segments in display
 *****************************************************************************/
typedef struct
{
  CHAR_TypeDef    Text[7];      /**< Text on display */
  NUMBER_TypeDef  Number[4];    /**< Numbers on display */
  EM_TypeDef      EMode;        /**< Display energy mode */
  ARING_TypeDef   ARing;        /**< Display ring */
  BATTERY_TypeDef Battery;      /**< Display battery */
} MCU_DISPLAY;

/**************************************************************************//**
 * @brief Working instance of LCD display
 *****************************************************************************/
static const MCU_DISPLAY EFM_Display = EFM_DISPLAY_DEF;


/**************************************************************************//**
 * @brief
 * Defines higlighted segments for the alphabet, starting from "blank" (SPACE)
 * Uses bit pattern as defined for text segments above.
 * E.g. a capital O, would have bits 0 1 2 3 4 5 => 0x003f defined
 *****************************************************************************/
static const uint16_t EFM_Alphabet[] = {
  0x0000, /* space */
  0x1100, /* ! */
  0x0280, /* " */
  0x0000, /* # */
  0x0000, /* $ */
  0x0602, /* % */
  0x0000, /* & */
  0x0020, /* ' */
  0x0039, /* ( */
  0x000f, /* ) */
  0x0000, /* * */
  0x1540, /* + */
  0x2000, /* , */
  0x0440, /* - */
  0x1000, /* . */
  0x2200, /* / */

  0x003f, /* 0 */
  0x0006, /* 1 */
  0x045b, /* 2 */
  0x044f, /* 3 */
  0x0466, /* 4 */
  0x046d, /* 5 */
  0x047d, /* 6 */
  0x0007, /* 7 */
  0x047f, /* 8 */
  0x046f, /* 9 */

  0x0000, /* : */
  0x0000, /* ; */
  0x0a00, /* < */
  0x0000, /* = */
  0x2080, /* > */
  0x0000, /* ? */
  0xffff, /* @ */

  0x0477, /* A */
  0x0a79, /* B */
  0x0039, /* C */
  0x20b0, /* D */
  0x0079, /* E */
  0x0071, /* F */
  0x047d, /* G */
  0x0476, /* H */
  0x0006, /* I */
  0x000e, /* J */
  0x0a70, /* K */
  0x0038, /* L */
  0x02b6, /* M */
  0x08b6, /* N */
  0x003f, /* O */
  0x0473, /* P */
  0x083f, /* Q */
  0x0c73, /* R */
  0x046d, /* S */
  0x1101, /* T */
  0x003e, /* U */
  0x2230, /* V */
  0x2836, /* W */
  0x2a80, /* X */
  0x046e, /* Y */
  0x2209, /* Z */

  0x0039, /* [ */
  0x0880, /* backslash */
  0x000f, /* ] */
  0x0001, /* ^ */
  0x0008, /* _ */
  0x0100, /* ` */

  0x1058, /* a */
  0x047c, /* b */
  0x0058, /* c */
  0x045e, /* d */
  0x2058, /* e */
  0x0471, /* f */
  0x0c0c, /* g */
  0x0474, /* h */
  0x0004, /* i */
  0x000e, /* j */
  0x0c70, /* k */
  0x0038, /* l */
  0x1454, /* m */
  0x0454, /* n */
  0x045c, /* o */
  0x0473, /* p */
  0x0467, /* q */
  0x0450, /* r */
  0x0c08, /* s */
  0x0078, /* t */
  0x001c, /* u */
  0x2010, /* v */
  0x2814, /* w */
  0x2a80, /* x */
  0x080c, /* y */
  0x2048, /* z */

  0x0000,
};

/**************************************************************************//**
 * @brief
 * Defines higlighted segments for the numeric display
 *****************************************************************************/

static const uint16_t EFM_Numbers[] = {
  0x003f, /* 0 */
  0x0006, /* 1 */
  0x005b, /* 2 */
  0x004f, /* 3 */
  0x0066, /* 4 */
  0x006d, /* 5 */
  0x007d, /* 6 */
  0x0007, /* 7 */
  0x007f, /* 8 */
  0x006f, /* 9 */
  0x0077, /* A */
  0x007c, /* b */
  0x0039, /* C */
  0x005e, /* d */
  0x0079, /* E */
  0x0071, /* F */
  0x0040  /* - */
};

/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/* sign is last element of the table  */
static const uint16_t signIndex = sizeof(EFM_Numbers)/sizeof(uint16_t) - 1 ;

static const LCD_Init_TypeDef lcdInit = LCD_INIT_DEF;
/** @endcond */


/**************************************************************************//**
 * @brief Disable all segments
 *****************************************************************************/
void SegmentLCD_AllOff(void)
{
  /* Turn on low segments */
  LCD_ALL_SEGMENTS_OFF();
}


/**************************************************************************//**
 * @brief Enable all segments
 *****************************************************************************/
void SegmentLCD_AllOn(void)
{
  LCD_ALL_SEGMENTS_ON();
}


/**************************************************************************//**
 * @brief Turn all segments on alpha characters in display off
 *****************************************************************************/
void SegmentLCD_AlphaNumberOff(void)
{
  LCD_ALPHA_NUMBER_OFF();
  return;
}


/**************************************************************************//**
 * @brief Light up or shut off Ring of Indicators
 * @param anum "Segment number" on "Ring", range 0 - 7
 * @param on Zero is off, non-zero is on
 *****************************************************************************/
void SegmentLCD_ARing(int anum, int on)
{
  uint32_t com, bit;

  com = EFM_Display.ARing.com[anum];
  bit = EFM_Display.ARing.bit[anum];

  if (on)
  {
    LCD_SegmentSet(com, bit, true);
  }
  else
  {
    LCD_SegmentSet(com, bit, false);
  }
}


/**************************************************************************//**
 * @brief Light up or shut off Battery Indicator
 * @param batteryLevel Battery Level, 0 to 4 (0 turns all off)
 *****************************************************************************/
void SegmentLCD_Battery(int batteryLevel)
{
  uint32_t com, bit;
  int      i, on;

  for (i = 0; i < 4; i++)
  {
    if (i < batteryLevel)
    {
      on = 1;
    }
    else
    {
      on = 0;
    }
    com = EFM_Display.Battery.com[i];
    bit = EFM_Display.Battery.bit[i];

    if (on)
    {
      LCD_SegmentSet(com, bit, true);
    }
    else
    {
      LCD_SegmentSet(com, bit, false);
    }
  }
}


/**************************************************************************//**
 * @brief Disables LCD controller
 *****************************************************************************/
void SegmentLCD_Disable(void)
{
  /* Disable LCD */
  LCD_Enable(false);

  /* Make sure CTRL register has been updated */
  LCD_SyncBusyDelay(LCD_SYNCBUSY_CTRL);

  /* Turn off LCD clock */
  CMU_ClockEnable(cmuClock_LCD, false);

  /* Turn off voltage boost if enabled */
  CMU->LCDCTRL = 0;
}


/**************************************************************************//**
 * @brief Light up or shut off Energy Mode indicator
 * @param em Energy Mode numer 0 to 4
 * @param on Zero is off, non-zero is on
 *****************************************************************************/
void SegmentLCD_EnergyMode(int em, int on)
{
  uint32_t com, bit;

  com = EFM_Display.EMode.com[em];
  bit = EFM_Display.EMode.bit[em];

  if (on)
  {
    LCD_SegmentSet(com, bit, true);
  }
  else
  {
    LCD_SegmentSet(com, bit, false);
  }
}

/**************************************************************************//**
 * @brief Get frame rate division value corresponding to mux selection
 * @param mux enum
 *****************************************************************************/
uint8_t SegmentLCD_GetFrameRateDiv(LCD_Mux_TypeDef muxSetting) {
	switch(muxSetting) {
	  /** Static (segments can be multiplexed with LCD_COM[0]) */
	case lcdMuxStatic: return 2;
	  /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */
	case lcdMuxDuplex: return 4;
	  /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */
	case lcdMuxTriplex: return 6;
	  /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */
	case lcdMuxQuadruplex: return 8;
	#if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
	  /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
	case lcdMuxSextaplex: return 12;
	  /** Octaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
	case lcdMuxOctaplex: return 16;
	#endif
	default: return 1;
	}
}

/**************************************************************************//**
 * @brief Segment LCD Initialization routine for EFM32 STK display
 * @param useBoost Set to use voltage boost
 *****************************************************************************/
void SegmentLCD_Init(bool useBoost)
{

  /* Ensure LE modules are accessible */
  CMU_ClockEnable(cmuClock_CORELE, true);

  /* Enable LFRCO as LFACLK in CMU (will also enable oscillator if not enabled) */
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);

  /* LCD Controller Prescaler  */

  /* Calculate value. Approach 50Hz for framerate. */
  uint32_t prescaler = (LOW_ENERGY_CLOCK_FREQUENCY / 32) / SegmentLCD_GetFrameRateDiv(lcdInit.mux);

  CMU_ClockDivSet(cmuClock_LCDpre, prescaler);

  /* Frame Rate */
  CMU_LCDClkFDIVSet(0);

  /* Enable clock to LCD module */
  CMU_ClockEnable(cmuClock_LCD, true);

  LCD_DISPLAY_ENABLE();

  /* Disable interrupts */
  LCD_IntDisable(0xFFFFFFFF);

  /* Initialize and enable LCD controller */
  LCD_Init(&lcdInit);

  /* Enable all display segments */
  LCD_SEGMENTS_ENABLE();

  /* Enable boost if necessary */
  if (useBoost)
  {
    LCD_VBoostSet(LCD_BOOST_LEVEL);
    LCD_VLCDSelect(lcdVLCDSelVExtBoost);
    CMU->LCDCTRL |= CMU_LCDCTRL_VBOOSTEN;
  }

  /* Turn all segments off */
  SegmentLCD_AllOff();

  LCD_SyncBusyDelay(0xFFFFFFFF);
}


/**************************************************************************//**
 * @brief Write a hexadecimal number on lower alphanumeric part of
 *        Segment LCD display
 * @param num Hexadecimal number value to put on display, in range 0
 *        to 0x0FFFFFFF
 *****************************************************************************/
void SegmentLCD_LowerHex( uint32_t num )
{
  int       i;
  char      str[7];
  uint32_t  nibble;

  SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);

  for ( i=6; i>=0; i-- )
  {
    nibble = num & 0xF;

    if ( nibble < 10 )
      str[i] = nibble + '0';
    else if ( nibble == 11 )
      str[i] = 'b';
    else if ( nibble == 13 )
      str[i] = 'd';
    else
      str[i] = (nibble - 10) + 'A';

    num >>= 4;
  }

  SegmentLCD_Write(str);
}

/**************************************************************************//**
 * @brief Write number on lower alphanumeric part of Segment LCD display
 * @param num Numeric value to put on display, in range -9999999 to +9999999
 *****************************************************************************/
void SegmentLCD_LowerNumber( int num )
{
  int i;
  char str[7];

  SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 0);

  if ( ( num > 9999999 ) || ( num < -9999999 ) )
  {
    SegmentLCD_Write("Ovrflow");
    return;
  }

  if ( num < 0 )
  {
    SegmentLCD_Symbol(LCD_SYMBOL_MINUS, 1);
    num = -num;
  }

  for ( i=6; i>=0; i-- )
  {
    if ( ( i < 6 ) && ( num == 0 ) )
    {
      str[i] = ' ';
    }
    else
    {
      str[i] = (num % 10) + '0';
      num /= 10;
    }
  }

  SegmentLCD_Write(str);
}


/**************************************************************************//**
 * @brief Write number on numeric part on Segment LCD display
 * @param value Numeric value to put on display, in range -999 to +9999
 *****************************************************************************/
void SegmentLCD_Number(int value)
{
  int      i, com, bit, digit, div, neg;
  uint16_t bitpattern;
  uint16_t num;

  /* Parameter consistancy check */
  if (value >= 9999)
  {
    value = 9999;
  }
  if (value <= -1000)
  {
    value = -999;
  }
  if (value < 0)
  {
    value = abs(value);
    neg   = 1;
  }
  else
  {
    neg = 0;
  }

  /* If an update is in progress we must block, or there might be tearing */
  LCD_SyncBusyDelay(0xFFFFFFFF);

  /* Freeze updates to avoid partial refresh of display */
  LCD_FreezeEnable(true);

  /* Turn off all number LCD segments */
  SegmentLCD_NumberOff();

  /* Extract useful digits */
  div = 1;
  for (digit = 0; digit < 4; digit++)
  {
    num = (value / div) % 10;
    if ((neg == 1) && (digit == 3)) num = signIndex;
    /* Get number layout of display */
    bitpattern = EFM_Numbers[num];
    for (i = 0; i < 7; i++)
    {
      bit = EFM_Display.Number[digit].bit[i];
      com = EFM_Display.Number[digit].com[i];
      if (bitpattern & (1 << i))
      {
        LCD_SegmentSet(com, bit, true);
      }
    }
    div = div * 10;
  }
  /* Sync LCD registers to LE domain */
  LCD_FreezeEnable(false);
}


/**************************************************************************//**
 * @brief Turn all segments on numeric digits in display off
 *****************************************************************************/
void SegmentLCD_NumberOff(void)
{
  /* Turn off all number segments */
  LCD_NUMBER_OFF();
  return;
}


/**************************************************************************//**
 * @brief Light up or shut off various symbols on Segment LCD
 * @param s Which symbol to turn on or off
 * @param on Zero is off, non-zero is on
 *****************************************************************************/
void SegmentLCD_Symbol(lcdSymbol s, int on)
{
  int com = 0;
  int bit = 0;

  switch (s)
  {
  case LCD_SYMBOL_GECKO:
    com = LCD_SYMBOL_GECKO_COM;
    bit = LCD_SYMBOL_GECKO_SEG;
    break;
  case LCD_SYMBOL_ANT:
    com = LCD_SYMBOL_ANT_COM;
    bit = LCD_SYMBOL_ANT_SEG;
    break;
  case LCD_SYMBOL_PAD0:
    com = LCD_SYMBOL_PAD0_COM;
    bit = LCD_SYMBOL_PAD0_SEG;
    break;
  case LCD_SYMBOL_PAD1:
    com = LCD_SYMBOL_PAD1_COM;
    bit = LCD_SYMBOL_PAD1_SEG;
    break;
  case LCD_SYMBOL_EFM32:
    com = LCD_SYMBOL_EFM32_COM;
    bit = LCD_SYMBOL_EFM32_SEG;
    break;
  case LCD_SYMBOL_MINUS:
    com = LCD_SYMBOL_MINUS_COM;
    bit = LCD_SYMBOL_MINUS_SEG;
    break;
  case LCD_SYMBOL_COL3:
    com = LCD_SYMBOL_COL3_COM;
    bit = LCD_SYMBOL_COL3_SEG;
    break;
  case LCD_SYMBOL_COL5:
    com = LCD_SYMBOL_COL5_COM;
    bit = LCD_SYMBOL_COL5_SEG;
    break;
  case LCD_SYMBOL_COL10:
    com = LCD_SYMBOL_COL10_COM;
    bit = LCD_SYMBOL_COL10_SEG;
    break;
#ifdef LCD_SYMBOL_DEGC_SEG
  case LCD_SYMBOL_DEGC:
    com = LCD_SYMBOL_DEGC_COM;
    bit = LCD_SYMBOL_DEGC_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_DEGF_SEG
  case LCD_SYMBOL_DEGF:
    com = LCD_SYMBOL_DEGF_COM;
    bit = LCD_SYMBOL_DEGF_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_DP2_SEG
  case LCD_SYMBOL_DP2:
    com = LCD_SYMBOL_DP2_COM;
    bit = LCD_SYMBOL_DP2_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_DP3_SEG
  case LCD_SYMBOL_DP3:
    com = LCD_SYMBOL_DP3_COM;
    bit = LCD_SYMBOL_DP3_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_DP4_SEG
  case LCD_SYMBOL_DP4:
    com = LCD_SYMBOL_DP4_COM;
    bit = LCD_SYMBOL_DP4_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_DP5_SEG
  case LCD_SYMBOL_DP5:
    com = LCD_SYMBOL_DP5_COM;
    bit = LCD_SYMBOL_DP5_SEG;
    break;
#endif
  case LCD_SYMBOL_DP6:
    com = LCD_SYMBOL_DP6_COM;
    bit = LCD_SYMBOL_DP6_SEG;
    break;
  case LCD_SYMBOL_DP10:
    com = LCD_SYMBOL_DP10_COM;
    bit = LCD_SYMBOL_DP10_SEG;
    break;
#ifdef LCD_SYMBOL_AM_SEG
  case LCD_SYMBOL_AM:
    com = LCD_SYMBOL_AM_COM;
    bit = LCD_SYMBOL_AM_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_PM_SEG
  case LCD_SYMBOL_PM:
    com = LCD_SYMBOL_PM_COM;
    bit = LCD_SYMBOL_PM_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_MICROAMP_SEG
  case LCD_SYMBOL_MICROAMP:
    com = LCD_SYMBOL_MICROAMP_COM;
    bit = LCD_SYMBOL_MICROAMP_SEG;
    break;
#endif
#ifdef LCD_SYMBOL_MILLIAMP_SEG
  case LCD_SYMBOL_MILLIAMP:
    com = LCD_SYMBOL_MILLIAMP_COM;
    bit = LCD_SYMBOL_MILLIAMP_SEG;
    break;
#endif

  }
  if (on)
  {
    LCD_SegmentSet(com, bit, true);
  }
  else
  {
    LCD_SegmentSet(com, bit, false);
  }
}


/**************************************************************************//**
 * @brief Write hexadecimal number on numeric part on Segment LCD display
 * @param value Numeric value to put on display, in range 0x0000-0xFFFF
 *****************************************************************************/
void SegmentLCD_UnsignedHex(uint16_t value)
{
  int      num, i, com, bit, digit;
  uint16_t bitpattern;

  /* Parameter consistancy check */
  if (value >= 0xffff)
  {
    value = 0xffff;
  }

  /* If an update is in progress we must block, or there might be tearing */
  LCD_SyncBusyDelay(0xFFFFFFFF);

  /* Freeze updates to avoid partial refresh of display */
  LCD_FreezeEnable(true);

  /* Turn off all number LCD segments */
  SegmentLCD_NumberOff();

  for (digit = 0; digit < 4; digit++)
  {
    num        = (value >> (4 * digit)) & 0x0f;
    bitpattern = EFM_Numbers[num];
    for (i = 0; i < 7; i++)
    {
      bit = EFM_Display.Number[digit].bit[i];
      com = EFM_Display.Number[digit].com[i];
      if (bitpattern & (1 << i))
      {
        LCD_SegmentSet(com, bit, true);
      }
    }
  }

  /* Sync LCD registers to LE domain */
  LCD_FreezeEnable(false);
}


/**************************************************************************//**
 * @brief Write text on LCD display
 * @param string Text string to show on display
 *****************************************************************************/
void SegmentLCD_Write(char *string)
{
  int      data, length, index;
  uint16_t bitfield;
  uint32_t com, bit;
  int      i;

  length = strlen(string);
  index  = 0;

  /* If an update is in progress we must block, or there might be tearing */
  LCD_SyncBusyDelay(0xFFFFFFFF);

  /* Freeze LCD to avoid partial updates */
  LCD_FreezeEnable(true);

  /* Turn all segments off */
  SegmentLCD_AlphaNumberOff();

  /* Fill out all characters on display */
  for (index = 0; index < 7; index++)
  {
    if (index < length)
    {
      data = (int) *string;
    }
    else           /* Padding with space */
    {
      data = 0x20; /* SPACE */
    }
    /* Defined letters currently starts at "SPACE" - ASCII 0x20; */
    data = data - 0x20;
    /* Get font for this letter */
    bitfield = EFM_Alphabet[data];

    for (i = 0; i < 14; i++)
    {
      bit = EFM_Display.Text[index].bit[i];
      com = EFM_Display.Text[index].com[i];

      if (bitfield & (1 << i))
      {
        /* Turn on segment */
        LCD_SegmentSet(com, bit, true);
      }
    }
    string++;
  }
  /* Enable update */
  LCD_FreezeEnable(false);
}