473 lines
16 KiB
C
473 lines
16 KiB
C
/**********************************************************************
|
||
* $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<72>
|
||
* 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 */
|
||
|
||
/**
|
||
* @}
|
||
*/
|
||
|