URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_EFMG890F128_IAR/] [lcd/] [lcdcontroller.c] - Rev 669
Go to most recent revision | Compare with Previous | Blame | View Log
/**************************************************************************//** * @file * @brief LCD Controller driver * @author Energy Micro AS * @version 1.0.1 ****************************************************************************** * @section License * <b>(C) Copyright 2009 Energy Micro AS, http://www.energymicro.com</b> ****************************************************************************** * * This source code is the property of Energy Micro AS. The source and compiled * code may only be used on Energy Micro "EFM32" microcontrollers. * * This copyright notice may not be removed from the source code nor changed. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no * obligation to support this Software. Energy Micro AS is providing the * Software "AS IS", with no express or implied warranties of any kind, * including, but not limited to, any implied warranties of merchantability * or fitness for any particular purpose or warranties against infringement * of any proprietary rights of a third party. * * Energy Micro AS will not be liable for any consequential, incidental, or * special damages, or any other relief, or for any claim by any third party, * arising from your use of this Software. * *****************************************************************************/ #include "FreeRTOS.h" #include "task.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include "efm32.h" #include "lcdcontroller.h" #include "lcddisplay.h" /** Counts every n'th frame */ int frameCounter = 0; /**************************************************************************//** * @brief LCD Interrupt Handler, triggers on frame counter, every n'th frame *****************************************************************************/ void LCD_IRQHandler(void) { LCD_TypeDef *lcd = LCD; /* clear interrupt */ lcd->IFC = 0xFFFFFFFF; frameCounter++; } /**************************************************************************//** * @brief Enables a segment on the LCD display * @param lcd Pointer to LCD register block * @param com COM segment number * @param bitvalue Bit value for segment *****************************************************************************/ static void LCD_enableSegment(LCD_TypeDef * lcd, int com, int bitvalue) { switch (com) { case 0: lcd->SEGD0L |= bitvalue; break; case 1: lcd->SEGD1L |= bitvalue; break; case 2: lcd->SEGD2L |= bitvalue; break; case 3: lcd->SEGD3L |= bitvalue; break; case 4: lcd->SEGD0H |= bitvalue; break; case 5: lcd->SEGD1H |= bitvalue; break; case 6: lcd->SEGD2H |= bitvalue; break; case 7: lcd->SEGD3H |= bitvalue; break; } } /**************************************************************************//** * @brief Disables a segment on the LCD Display * @param lcd Pointer to LCD register structure * @param com COM segment number * @param bitvalue Bit value for segment *****************************************************************************/ static void LCD_disableSegment(LCD_TypeDef * lcd, int com, int bitvalue) { switch (com) { case 0: lcd->SEGD0L &= ~bitvalue; break; case 1: lcd->SEGD1L &= ~bitvalue; break; case 2: lcd->SEGD2L &= ~bitvalue; break; case 3: lcd->SEGD3L &= ~bitvalue; break; case 4: lcd->SEGD0H &= ~bitvalue; break; case 5: lcd->SEGD1H &= ~bitvalue; break; case 6: lcd->SEGD2H &= ~bitvalue; break; case 7: lcd->SEGD3H &= ~bitvalue; break; } } /**************************************************************************//** * @brief Write number on numeric part on LCD display * @param lcd Pointer to LCD control block * @param value Numeric value to put on display, in range -999 to +9999 *****************************************************************************/ void LCD_Number(LCD_TypeDef *lcd, int value) { int num, i, com, bit, digit, div, neg; uint16_t bitpattern; /* Parameter consistancy check */ if (value >= 9999) { value = 9999; } if (value <= -1000) { value = -999; } if (value < 0) { value = abs(value); neg = 1; } else { neg = 0; } /* Extract useful digits */ div = 1; for (digit = 0; digit < 4; digit++) { num = (value / div) % 10; if ((neg == 1) && (digit == 3)) num = 10; bitpattern = EM_Numbers[num]; for (i = 0; i < 7; i++) { bit = EFMDisplay.Number[digit].bit[i]; com = EFMDisplay.Number[digit].com[i]; if (bitpattern & (1 << i)) { LCD_enableSegment(lcd, com, 1 << bit); } else { LCD_disableSegment(lcd, com, 1 << bit); } } div = div * 10; } } /**************************************************************************//** * @brief Turn all segments on numeric display off * @param lcd Pointer to LCD register structure *****************************************************************************/ void LCD_NumberOff(LCD_TypeDef *lcd) { int digit, i, bit, com; /* Turn off all segments */ for (digit = 0; digit < 4; digit++) { for (i = 0; i < 7; i++) { bit = EFMDisplay.Number[digit].bit[i]; com = EFMDisplay.Number[digit].com[i]; LCD_disableSegment(lcd, com, 1 << bit); } } return; } /**************************************************************************//** * @brief Write text on LCD display * @param lcd Pointer to LCD register structure * @param string Text string to show on display *****************************************************************************/ void LCD_Write(LCD_TypeDef *lcd, char *string) { int data, length, index; uint16_t bitfield; uint32_t value; uint32_t com, bit; int i; length = strlen(string); index = 0; /* 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" - 0x20; */ data = data - 0x20; bitfield = EM_alphabet[data]; for (i = 0; i < 14; i++) { bit = EFMDisplay.Text[index].bit[i]; com = EFMDisplay.Text[index].com[i]; value = (1 << bit); if (bitfield & (1 << i)) { /* Turn on segment */ LCD_enableSegment(lcd, com, value); } else { /* Turn off segment */ LCD_disableSegment(lcd, com, value); } } string++; } while (lcd->SYNCBUSY) ; } /**************************************************************************//** * @brief LCD Disable all segments * @param lcd Pointer to LCD register block *****************************************************************************/ void LCD_AllOff(LCD_TypeDef *lcd) { lcd->SEGD0L = 0x00000000; lcd->SEGD0H = 0x00000000; lcd->SEGD1L = 0x00000000; lcd->SEGD1H = 0x00000000; lcd->SEGD2L = 0x00000000; lcd->SEGD2H = 0x00000000; lcd->SEGD3L = 0x00000000; lcd->SEGD3H = 0x00000000; while (lcd->SYNCBUSY) ; } /**************************************************************************//** * @brief LCD Enable all segments * @param lcd Pointer to LCD register block *****************************************************************************/ void LCD_AllOn(LCD_TypeDef *lcd) { lcd->SEGD0L = 0xffffffff; lcd->SEGD0H = 0xffffffff; lcd->SEGD1L = 0xffffffff; lcd->SEGD1H = 0xffffffff; lcd->SEGD2L = 0xffffffff; lcd->SEGD2H = 0xffffffff; lcd->SEGD3L = 0xffffffff; lcd->SEGD3H = 0xffffffff; while (lcd->SYNCBUSY) ; } /**************************************************************************//** * @brief LCD Light up or shut off Energy Mode indicator * @param lcd Pointer to LCD register block * @pararm em Energy Mode numer 0 to 4 * @param on Zero is off, non-zero is on *****************************************************************************/ void LCD_EnergyMode(LCD_TypeDef *lcd, int em, int on) { uint32_t com, bitvalue; com = EFMDisplay.EMode.com[em]; bitvalue = 1 << EFMDisplay.EMode.bit[em]; if (on) { LCD_enableSegment(lcd, com, bitvalue); } else { LCD_disableSegment(lcd, com, bitvalue); } } /**************************************************************************//** * @brief LCD Light up or shut off Ring of Indicators * @param lcd Pointer to LCD register block * @param anum "Segment number" on "Ring", range 0 - 7 * @param on Zero is off, non-zero is on *****************************************************************************/ void LCD_ARing(LCD_TypeDef *lcd, int anum, int on) { uint32_t com, bitvalue; com = EFMDisplay.ARing.com[anum]; bitvalue = 1 << EFMDisplay.ARing.bit[anum]; if (on) { LCD_enableSegment(lcd, com, bitvalue); } else { LCD_disableSegment(lcd, com, bitvalue); } } /**************************************************************************//** * @brief LCD Light up or shut off various symbols on LCD Display * @param lcd Pointer to LCD register block * @param s Which symbol to turn on or off * @param on Zero is off, non-zero is on *****************************************************************************/ void LCD_Symbol(LCD_TypeDef *lcd, lcdSymbol s, int on) { int com, bit; switch (s) { case LCD_SYMBOL_GECKO: com = 3; bit = 8; break; case LCD_SYMBOL_ANT: com = 3; bit = 1; break; case LCD_SYMBOL_PAD0: com = 1; bit = 8; break; case LCD_SYMBOL_PAD1: com = 2; bit = 8; break; case LCD_SYMBOL_AM: com = 4; bit = 0; break; case LCD_SYMBOL_PM: com = 4; bit = 3; break; case LCD_SYMBOL_EFM32: com = 0; bit = 8; break; case LCD_SYMBOL_MINUS: com = 0; bit = 9; break; case LCD_SYMBOL_COL3: com = 0; bit = 16; break; case LCD_SYMBOL_COL5: com = 0; bit = 24; break; case LCD_SYMBOL_COL10: com = 4; bit = 7; break; case LCD_SYMBOL_DP2: com = 4; bit = 2; break; case LCD_SYMBOL_DP3: com = 5; bit = 2; break; case LCD_SYMBOL_DP4: com = 6; bit = 2; break; case LCD_SYMBOL_DP5: com = 7; bit = 2; break; case LCD_SYMBOL_DP6: com = 0; bit = 21; break; case LCD_SYMBOL_DP10: com = 4; bit = 5; break; } if (on) { LCD_enableSegment(lcd, com, 1 << bit); } else { LCD_disableSegment(lcd, com, 1 << bit); } } /**************************************************************************//** * @brief LCD Light up or shut off Battery Indicator * @param lcd Pointer to LCD register block * @param batteryLevel Battery Level, 0 to 4 (0 turns all off) *****************************************************************************/ void LCD_Battery(LCD_TypeDef *lcd, int batteryLevel) { uint32_t com, bitvalue; int i, on; for (i = 0; i < 4; i++) { if (i < batteryLevel) { on = 1; } else { on = 0; } com = EFMDisplay.Battery.com[i]; bitvalue = 1 << EFMDisplay.Battery.bit[i]; if (on) { LCD_enableSegment(lcd, com, bitvalue); } else { LCD_disableSegment(lcd, com, bitvalue); } } } /**************************************************************************//** * @brief LCD Initialization routine for EFM32 DVK display * @param lcd Pointer to LCD register block *****************************************************************************/ void LCD_Init(LCD_TypeDef *lcd) { CMU_TypeDef *cmu = CMU; /* Enable LFXO oscillator */ cmu->OSCENCMD |= CMU_OSCENCMD_LFXOEN; while (!(cmu->STATUS & CMU_STATUS_LFXORDY)) ; /* Enable LCD clock in CMU */ cmu->LFACLKEN0 |= CMU_LFACLKEN0_LCD; /* Select LFXO for LCD */ cmu->LFCLKSEL = CMU_LFCLKSEL_LFA_LFXO | CMU_LFCLKSEL_LFB_LFXO; /* LCD Controller Prescaler (divide by 1) */ /* CLKlcd = 0.25 kHz */ cmu->LFAPRESC0 &= ~_CMU_LFAPRESC0_LCD_MASK; cmu->LFAPRESC0 |= _CMU_LFAPRESC0_LCD_DIV128 << _CMU_LFAPRESC0_LCD_SHIFT; /* Set up interrupt handler */ lcd->IEN = 0; while (lcd->SYNCBUSY) ; /* Clear pending interrupts */ lcd->IFC = ~0; /* Enable interrupt */ NVIC_EnableIRQ(LCD_IRQn); lcd->IEN = LCD_IEN_FC; /* Frame rate is 32Hz, 0.25Khz LFCLK128, QUADRUPLEX mode, FDIV=0 */ lcd->DISPCTRL = LCD_DISPCTRL_MUX_QUADRUPLEX | LCD_DISPCTRL_BIAS_ONETHIRD | LCD_DISPCTRL_WAVE_LOWPOWER | LCD_DISPCTRL_CONLEV_MAX | LCD_DISPCTRL_VLCDSEL_VDD | LCD_DISPCTRL_VBLEV_3V00; /* No voltage boost, framerate 32Hz */ cmu->LCDCTRL = 0; /* Turn all segments off */ LCD_AllOff(lcd); /* Enable all segment registers */ lcd->SEGEN = 0x000003FF; lcd->CTRL = LCD_CTRL_EN | LCD_CTRL_UDCTRL_FRAMESTART; while (lcd->SYNCBUSY) ; /* Configure LCD to give a frame counter interrupt every 8th frame. */ lcd->BACTRL = LCD_BACTRL_FCEN | (7 << _LCD_BACTRL_FCTOP_SHIFT) | (0 << _LCD_BACTRL_FCPRESC_SHIFT); while (lcd->SYNCBUSY) ; lcd->IFC = LCD_IFC_FC; lcd->IEN = LCD_IEN_FC; } /**************************************************************************//** * @brief Disables LCD controller * @param lcd Pointer to LCD register block *****************************************************************************/ void LCD_Disable(LCD_TypeDef *lcd) { CMU_TypeDef *cmu = CMU; /* Turn off interrupts */ lcd->IEN = 0x00000000; lcd->IFC = LCD_IFC_FC; NVIC_DisableIRQ(LCD_IRQn); /* Disable LCD */ lcd->CTRL = 0; /* Turn off LCD clock */ cmu->LFACLKEN0 &= ~(CMU_LFACLKEN0_LCD); /* Turn off voltage boost if enabled */ cmu->LCDCTRL = 0; } /**************************************************************************//** * @brief LCD scrolls a text over the display, sort of "polled printf" * @param lcd Pointer to LCD register block *****************************************************************************/ void LCD_ScrollText(LCD_TypeDef *lcd, char *scrolltext) { int i, len; char buffer[8]; buffer[7] = 0x00; len = strlen(scrolltext); if (len < 7) return; for (i = 0; i < (len - 7); i++) { memcpy(buffer, scrolltext + i, 7); LCD_Write(lcd, buffer); vTaskDelay(100/portTICK_RATE_MS); } }
Go to most recent revision | Compare with Previous | Blame | View Log