/********************************************************************** * $Id$ lpc43xx_lcd.c 2011-06-02 *//** * @file lpc43xx_lcd.c * @brief Contains all function support for LCD Driver * @version 1.0 * @date 02. June. 2011 * @author NXP MCU SW Application Team * * Copyright(C) 2011, NXP Semiconductor * All rights reserved. * *********************************************************************** * Software that is described herein is for illustrative purposes only * which provides customers with programming information regarding the * products. This software is supplied "AS IS" without any warranties. * NXP Semiconductors assumes no responsibility or liability for the * use of the software, conveys no license or title under any patent, * copyright, or mask work right to the product. NXP Semiconductors * reserves the right to make changes in the software without * notification. NXP Semiconductors also make no representation or * warranty that such application will be suitable for the specified * use without further testing or modification. * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted, under NXP Semiconductors� * relevant copyright in the software, without fee, provided that it * is used in conjunction with NXP Semiconductors microcontrollers. This * copyright, permission, and disclaimer notice must appear in all copies of * this code. **********************************************************************/ /* Peripheral group ----------------------------------------------------------- */ /** @addtogroup LCD * @{ */ /* Includes ------------------------------------------------------------------- */ #include "LPC43xx.h" #include "lpc43xx_lcd.h" /* If this source file built with example, the lpc43xx FW library configuration * file in each example directory ("lpc43xx_libcfg.h") must be included, * otherwise the default FW library configuration file must be included instead */ #ifdef __BUILD_WITH_EXAMPLE__ #include "lpc43xx_libcfg.h" #else #include "lpc43xx_libcfg_default.h" #endif /* __BUILD_WITH_EXAMPLE__ */ #ifdef _LCD LCD_CURSOR_SIZE_OPT LCD_Cursor_Size = LCD_CURSOR_64x64; /* Private Functions ---------------------------------------------------------- */ /*********************************************************************//** * @brief Init the lpc43xx LCD Controller * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] LCD_ConfigStruct point to LCD_CFG_Type that describe the LCD Panel * @return None **********************************************************************/ void LCD_Init(LPC_LCD_Type *LCDx, LCD_CFG_Type *LCD_ConfigStruct){ uint32_t i, regValue, *pPal; uint32_t pcd; /* disable the display */ LCDx->CTRL &= ~CLCDC_LCDCTRL_ENABLE; /* Setting LCD_TIMH register */ regValue= ( ((((LCD_ConfigStruct->screen_width/16)-1)&0x3F) << 2) | (( (LCD_ConfigStruct->HSync_pulse_width-1) &0xFF) << 8) | (( (LCD_ConfigStruct->horizontal_porch.front-1) &0xFF) << 16) | (( (LCD_ConfigStruct->horizontal_porch.back-1) &0xFF) << 24) ); LCDx->TIMH = regValue; /* Setting LCD_TIMV register */ regValue =((((LCD_ConfigStruct->screen_height-1) &0x3FF) << 0) | (((LCD_ConfigStruct->VSync_pulse_width-1) &0x03F) << 10) | (((LCD_ConfigStruct->vertical_porch.front-1) &0x0FF) << 16) | (((LCD_ConfigStruct->vertical_porch.back-1) &0x0FF) << 24) ); LCDx->TIMV = regValue; /* Generate the clock and signal polarity control word */ regValue = 0; regValue = (((LCD_ConfigStruct->ac_bias_frequency-1) & 0x1F) << 6); regValue |= (LCD_ConfigStruct->OE_pol & 1)<< 14; regValue |= (LCD_ConfigStruct->panel_clk_edge & 1)<< 13; regValue |= (LCD_ConfigStruct->HSync_pol & 1)<< 12; regValue |= (LCD_ConfigStruct->VSync_pol & 1)<< 11; /* Compute clocks per line based on panel type */ switch(LCD_ConfigStruct->lcd_panel_type) { case LCD_MONO_4: regValue |= ((((LCD_ConfigStruct->screen_width / 4)-1) & 0x3FF) << 16); break; case LCD_MONO_8: regValue |= ((((LCD_ConfigStruct->screen_width / 8)-1) & 0x3FF) << 16); break; case LCD_CSTN: regValue |= (((((LCD_ConfigStruct->screen_width * 3)/8)-1) & 0x3FF) << 16); break; case LCD_TFT: default: regValue |= /* 1<<26 |*/ (((LCD_ConfigStruct->screen_width-1) & 0x3FF) << 16); } /* panel clock divisor */ pcd = 6; // TODO: should be calculated from LCDDCLK pcd &= 0x3FF; regValue |= ((pcd>>5)<<27) | ((pcd)&0x1F); LCDx->POL = regValue; /* configure line end control */ CHECK_PARAM(LCD_ConfigStruct->line_end_delay<=(1<<7)); if(LCD_ConfigStruct->line_end_delay) LCDx->LE = (LCD_ConfigStruct->line_end_delay-1) | 1<<16; else LCDx->LE = 0; /* disable interrupts */ LCDx->INTMSK = 0; /* set bits per pixel */ regValue = LCD_ConfigStruct->bits_per_pixel << 1; /* set color format BGR or RGB */ regValue |= LCD_ConfigStruct->corlor_format << 8; regValue |= LCD_ConfigStruct->lcd_panel_type << 4; if(LCD_ConfigStruct->dual_panel == 1) { regValue |= 1 << 7; } LCDx->CTRL = regValue; /* clear palette */ pPal = (uint32_t*) (&(LCDx->PAL)); for(i = 0; i < 128; i++) { *pPal = 0; pPal++; } } /*********************************************************************//** * @brief Deinit LCD controller * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @return None **********************************************************************/ void LCD_DeInit(LPC_LCD_Type *LCDx); /*********************************************************************//** * @brief Power the LCD Panel * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] OnOff Turn on/off LCD * - TRUE :Turn on * - FALSE :Turn off * @return None **********************************************************************/ void LCD_Power(LPC_LCD_Type *LCDx, FunctionalState OnOff){ int i; if(OnOff){ LPC_LCD->CTRL |= CLCDC_LCDCTRL_PWR; for(i=0;i<100000;i++); LPC_LCD->CTRL |= CLCDC_LCDCTRL_ENABLE; }else{ LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_PWR; for(i=0;i<100000;i++); LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_ENABLE; } } /*********************************************************************//** * @brief Enable/Disable the LCD Controller * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] EnDis Enable/disable status * - TRUE :Enable * - FALSE :Disable * @return None **********************************************************************/ void LCD_Enable(LPC_LCD_Type *LCDx, FunctionalState EnDis){ if (EnDis) { LCDx->CTRL |= CLCDC_LCDCTRL_ENABLE; } else { LCDx->CTRL &= ~CLCDC_LCDCTRL_ENABLE; } } /*********************************************************************//** * @brief Set LCD Frame Buffer for Single Panel or Upper Panel Frame * Buffer for Dual Panel * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] buffer address of buffer * @return None **********************************************************************/ void LCD_SetFrameBuffer(LPC_LCD_Type *LCDx, void* buffer){ LCDx->UPBASE = (uint32_t)buffer; } /*********************************************************************//** * @brief Set LCD Lower Panel Frame Buffer for Dual Panel * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] buffer address of buffer * @return None **********************************************************************/ void LCD_SetLPFrameBuffer(LPC_LCD_Type *LCDx, void* buffer){ LCDx->LPBASE = (uint32_t)buffer; } /*********************************************************************//** * @brief Configure Cursor * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] cursor_size specify size of cursor * - LCD_CURSOR_32x32 :cursor size is 32x32 pixels * - LCD_CURSOR_64x64 :cursor size is 64x64 pixels * @param[in] sync cursor sync mode * - TRUE :cursor sync to the frame sync pulse * - FALSE :cursor async mode * @return None **********************************************************************/ void LCD_Cursor_Config(LPC_LCD_Type *LCDx, LCD_CURSOR_SIZE_OPT cursor_size, Bool sync){ LCD_Cursor_Size = cursor_size; LCDx->CRSR_CFG = ((sync?1:0)<<1) | cursor_size; } /*********************************************************************//** * @brief Write Cursor Image into Internal Cursor Image Buffer * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] cursor_num specify number of cursor is going to be written * this param must < 4 * @param[in] Image point to Cursor Image Buffer * @return None **********************************************************************/ void LCD_Cursor_WriteImage(LPC_LCD_Type *LCDx, uint8_t cursor_num, void* Image){ int i,j; uint8_t *fifoptr, *crsr_ptr = (uint8_t *)Image; CHECK_PARAM(cursor_num<4); /* Check if Cursor Size was configured as 32x32 or 64x64*/ if(LCD_Cursor_Size == LCD_CURSOR_32x32){ i = cursor_num * 256; j = i + 256; }else{ i = 0; j = 1024; } fifoptr = (uint8_t*)&(LCDx->CRSR_IMG[0]); /* Copy Cursor Image content to FIFO */ for(; i < j; i++) { fifoptr[i] = *(uint8_t *)crsr_ptr; crsr_ptr++; } } /*********************************************************************//** * @brief Get Internal Cursor Image Buffer Address * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] cursor_num specify number of cursor is going to be written * this param must < 4 * @return Cursor Image Buffer Address **********************************************************************/ void* LCD_Cursor_GetImageBufferAddress(LPC_LCD_Type *LCDx, uint8_t cursor_num){ CHECK_PARAM(cursor_num<4); return (void*)&(LCDx->CRSR_IMG[cursor_num*64]); } /*********************************************************************//** * @brief Enable Cursor * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] cursor_num specify number of cursor is going to be written * this param must < 4 * @param[in] OnOff Turn on/off LCD * - TRUE :Enable * - FALSE :Disable * @return None **********************************************************************/ void LCD_Cursor_Enable(LPC_LCD_Type *LCDx, uint8_t cursor_num, FunctionalState OnOff){ CHECK_PARAM(cursor_num<4); if (OnOff) { LCDx->CRSR_CTRL = (cursor_num<<4) | 1; } else { LCDx->CRSR_CTRL = (cursor_num<<4); } } /*********************************************************************//** * @brief Load LCD Palette * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] palette point to palette address * @return None **********************************************************************/ void LCD_LoadPalette(LPC_LCD_Type *LCDx, void* palette){ LCD_PALETTE_ENTRY_Type pal_entry, *ptr_pal_entry; uint8_t i, *pal_ptr; /* This function supports loading of the color palette from the C file generated by the bmp2c utility. It expects the palette to be passed as an array of 32-bit BGR entries having the following format: 2:0 - Not used 7:3 - Blue 10:8 - Not used 15:11 - Green 18:16 - Not used 23:19 - Red 31:24 - Not used arg = pointer to input palette table address */ ptr_pal_entry = &pal_entry; pal_ptr = (uint8_t *) palette; /* 256 entry in the palette table */ for(i = 0; i < 256/2; i++) { pal_entry.Bl = (*pal_ptr++) >> 3; /* blue first */ pal_entry.Gl = (*pal_ptr++) >> 3; /* get green */ pal_entry.Rl = (*pal_ptr++) >> 3; /* get red */ pal_ptr++; /* skip over the unused byte */ /* do the most significant halfword of the palette */ pal_entry.Bu = (*pal_ptr++) >> 3; /* blue first */ pal_entry.Gu = (*pal_ptr++) >> 3; /* get green */ pal_entry.Ru = (*pal_ptr++) >> 3; /* get red */ pal_ptr++; /* skip over the unused byte */ LCDx->PAL[i] = *(uint32_t *)ptr_pal_entry; } } /*********************************************************************//** * @brief Load Cursor Palette * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] palette_color cursor palette 0 value * @return None **********************************************************************/ void LCD_Cursor_LoadPalette0(LPC_LCD_Type *LCDx, uint32_t palette_color){ /* 7:0 - Red 15:8 - Green 23:16 - Blue 31:24 - Not used*/ LCDx->CRSR_PAL0 = (uint32_t)palette_color; } /*********************************************************************//** * @brief Load Cursor Palette * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] palette_color cursor palette 1 value * @return None **********************************************************************/ void LCD_Cursor_LoadPalette1(LPC_LCD_Type *LCDx, uint32_t palette_color){ /* 7:0 - Red 15:8 - Green 23:16 - Blue 31:24 - Not used*/ LCDx->CRSR_PAL1 = (uint32_t)palette_color; } /*********************************************************************//** * @brief Set Interrupt * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] Int LCD Interrupt Source, should be: * - LCD_INT_FUF :FIFO underflow * - LCD_INT_LNBU :LCD next base address update bit * - LCD_INT_VCOMP :Vertical compare bit * - LCD_INT_BER :AHB master error interrupt bit * @return None **********************************************************************/ void LCD_SetInterrupt(LPC_LCD_Type *LCDx, LCD_INT_SRC Int){ LCDx->INTMSK |= Int; } /*********************************************************************//** * @brief Clear Interrupt * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] Int LCD Interrupt Source, should be: * - LCD_INT_FUF :FIFO underflow * - LCD_INT_LNBU :LCD next base address update bit * - LCD_INT_VCOMP :Vertical compare bit * - LCD_INT_BER :AHB master error interrupt bit * @return None **********************************************************************/ void LCD_ClrInterrupt(LPC_LCD_Type *LCDx, LCD_INT_SRC Int){ LCDx->INTCLR |= Int; } /*********************************************************************//** * @brief Get LCD Interrupt Status * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @return None **********************************************************************/ LCD_INT_SRC LCD_GetInterrupt(LPC_LCD_Type *LCDx){ return (LCD_INT_SRC)LCDx->INTRAW; } /*********************************************************************//** * @brief Enable Cursor Interrupt * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @return None **********************************************************************/ void LCD_Cursor_SetInterrupt(LPC_LCD_Type *LCDx){ LCDx->CRSR_INTMSK |= 1; } /*********************************************************************//** * @brief Clear Cursor Interrupt * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @return None **********************************************************************/ void LCD_Cursor_ClrInterrupt(LPC_LCD_Type *LCDx){ LCDx->CRSR_INTCLR |= 1; } /*********************************************************************//** * @brief Set Cursor Position * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] x horizontal position * @param[in] y vertical position * @return None **********************************************************************/ void LCD_Cursor_SetPos(LPC_LCD_Type *LCDx, uint16_t x, uint16_t y){ LCDx->CRSR_XY = (x & 0x3FF) | ((y & 0x3FF) << 16); } /*********************************************************************//** * @brief Set Cursor Clipping Position * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD * @param[in] x horizontal position, should be in range: 0..63 * @param[in] y vertical position, should be in range: 0..63 * @return None **********************************************************************/ void LCD_Cursor_SetClip(LPC_LCD_Type *LCDx, uint16_t x, uint16_t y){ LCDx->CRSR_CLIP = (x & 0x3F) | ((y & 0x3F) << 8); } #endif /* _LCD */ /** * @} */