1 /**********************************************************************
\r
2 * $Id$ lpc18xx_lcd.c 2011-06-02
\r
4 * @file lpc18xx_lcd.c
\r
5 * @brief Contains all function support for LCD Driver
\r
7 * @date 02. June. 2011
\r
8 * @author NXP MCU SW Application Team
\r
10 * Copyright(C) 2011, NXP Semiconductor
\r
11 * All rights reserved.
\r
13 ***********************************************************************
\r
14 * Software that is described herein is for illustrative purposes only
\r
15 * which provides customers with programming information regarding the
\r
16 * products. This software is supplied "AS IS" without any warranties.
\r
17 * NXP Semiconductors assumes no responsibility or liability for the
\r
18 * use of the software, conveys no license or title under any patent,
\r
19 * copyright, or mask work right to the product. NXP Semiconductors
\r
20 * reserves the right to make changes in the software without
\r
21 * notification. NXP Semiconductors also make no representation or
\r
22 * warranty that such application will be suitable for the specified
\r
23 * use without further testing or modification.
\r
24 **********************************************************************/
\r
26 /* Peripheral group ----------------------------------------------------------- */
\r
31 /* Includes ------------------------------------------------------------------- */
\r
32 #include "LPC18xx.h"
\r
33 #include "lpc18xx_lcd.h"
\r
35 /* If this source file built with example, the LPC18xx FW library configuration
\r
36 * file in each example directory ("lpc18xx_libcfg.h") must be included,
\r
37 * otherwise the default FW library configuration file must be included instead
\r
39 #ifdef __BUILD_WITH_EXAMPLE__
\r
40 #include "lpc18xx_libcfg.h"
\r
42 #include "lpc18xx_libcfg_default.h"
\r
43 #endif /* __BUILD_WITH_EXAMPLE__ */
\r
47 LCD_CURSOR_SIZE_OPT LCD_Cursor_Size = LCD_CURSOR_64x64;
\r
49 /* Private Functions ---------------------------------------------------------- */
\r
51 /*********************************************************************//**
\r
52 * @brief Init the LPC18xx LCD Controller
\r
53 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
54 * @param[in] LCD_ConfigStruct point to LCD_CFG_Type that describe the LCD Panel
\r
56 **********************************************************************/
\r
57 void LCD_Init(LPC_LCD_Type *LCDx, LCD_CFG_Type *LCD_ConfigStruct){
\r
58 uint32_t i, regValue, *pPal;
\r
60 /* disable the display */
\r
61 LCDx->CTRL &= ~CLCDC_LCDCTRL_ENABLE;
\r
63 /* Setting LCD_TIMH register */
\r
64 regValue= ( ((((LCD_ConfigStruct->screen_width/16)-1)&0x3F) << 2)
\r
65 | (( (LCD_ConfigStruct->HSync_pulse_width-1) &0xFF) << 8)
\r
66 | (( (LCD_ConfigStruct->horizontal_porch.front-1) &0xFF) << 16)
\r
67 | (( (LCD_ConfigStruct->horizontal_porch.back-1) &0xFF) << 24) );
\r
69 LCDx->TIMH = regValue;
\r
71 /* Setting LCD_TIMV register */
\r
72 regValue =((((LCD_ConfigStruct->screen_height-1) &0x3FF) << 0)
\r
73 | (((LCD_ConfigStruct->VSync_pulse_width-1) &0x03F) << 10)
\r
74 | (((LCD_ConfigStruct->vertical_porch.front-1) &0x0FF) << 16)
\r
75 | (((LCD_ConfigStruct->vertical_porch.back-1) &0x0FF) << 24) );
\r
77 LCDx->TIMV = regValue;
\r
79 /* Generate the clock and signal polarity control word */
\r
81 regValue = (((LCD_ConfigStruct->ac_bias_frequency-1) & 0x1F) << 6);
\r
83 regValue |= (LCD_ConfigStruct->OE_pol & 1)<< 14;
\r
85 regValue |= (LCD_ConfigStruct->panel_clk_edge & 1)<< 13;
\r
87 regValue |= (LCD_ConfigStruct->HSync_pol & 1)<< 12;
\r
89 regValue |= (LCD_ConfigStruct->VSync_pol & 1)<< 11;
\r
91 /* Compute clocks per line based on panel type */
\r
93 switch(LCD_ConfigStruct->lcd_panel_type)
\r
96 regValue |= ((((LCD_ConfigStruct->screen_width / 4)-1) & 0x3FF) << 16);
\r
99 regValue |= ((((LCD_ConfigStruct->screen_width / 8)-1) & 0x3FF) << 16);
\r
102 regValue |= (((((LCD_ConfigStruct->screen_width * 3)/8)-1) & 0x3FF) << 16);
\r
106 regValue |= 1<<26 | (((LCD_ConfigStruct->screen_width-1) & 0x3FF) << 16);
\r
109 /* panel clock divisor */
\r
110 pcd = LCD_ConfigStruct->pcd; // TODO: should be calculated from LCDDCLK
\r
112 regValue |= ((pcd>>5)<<27) | ((pcd)&0x1F);
\r
114 LCDx->POL = regValue;
\r
116 /* configure line end control */
\r
117 CHECK_PARAM(LCD_ConfigStruct->line_end_delay<=(1<<7));
\r
118 if(LCD_ConfigStruct->line_end_delay)
\r
119 LCDx->LE = (LCD_ConfigStruct->line_end_delay-1) | 1<<16;
\r
123 /* disable interrupts */
\r
126 /* set bits per pixel */
\r
127 regValue = LCD_ConfigStruct->bits_per_pixel << 1;
\r
129 /* set color format BGR or RGB */
\r
130 regValue |= LCD_ConfigStruct->color_format << 8;
\r
132 regValue |= LCD_ConfigStruct->lcd_panel_type << 4;
\r
134 if(LCD_ConfigStruct->dual_panel == 1)
\r
136 regValue |= 1 << 7;
\r
138 LCDx->CTRL = regValue;
\r
139 /* clear palette */
\r
140 pPal = (uint32_t*) (&(LCDx->PAL));
\r
142 for(i = 0; i < 128; i++)
\r
150 /*********************************************************************//**
\r
151 * @brief Deinit LCD controller
\r
152 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
154 **********************************************************************/
\r
155 void LCD_DeInit(LPC_LCD_Type *LCDx);
\r
158 /*********************************************************************//**
\r
159 * @brief Power the LCD Panel
\r
160 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
161 * @param[in] OnOff Turn on/off LCD
\r
163 * - FALSE :Turn off
\r
165 **********************************************************************/
\r
166 void LCD_Power(LPC_LCD_Type *LCDx, FunctionalState OnOff){
\r
169 LPC_LCD->CTRL |= CLCDC_LCDCTRL_PWR;
\r
170 for(i=0;i<100000;i++);
\r
171 LPC_LCD->CTRL |= CLCDC_LCDCTRL_ENABLE;
\r
173 LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_PWR;
\r
174 for(i=0;i<100000;i++);
\r
175 LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_ENABLE;
\r
180 /*********************************************************************//**
\r
181 * @brief Enable/Disable the LCD Controller
\r
182 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
183 * @param[in] EnDis Enable/disable status
\r
187 **********************************************************************/
\r
188 void LCD_Enable(LPC_LCD_Type *LCDx, FunctionalState EnDis){
\r
191 LCDx->CTRL |= CLCDC_LCDCTRL_ENABLE;
\r
195 LCDx->CTRL &= ~CLCDC_LCDCTRL_ENABLE;
\r
200 /*********************************************************************//**
\r
201 * @brief Set LCD Frame Buffer for Single Panel or Upper Panel Frame
\r
202 * Buffer for Dual Panel
\r
203 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
204 * @param[in] buffer address of buffer
\r
206 **********************************************************************/
\r
207 void LCD_SetFrameBuffer(LPC_LCD_Type *LCDx, void* buffer){
\r
208 LCDx->UPBASE = (uint32_t)buffer;
\r
212 /*********************************************************************//**
\r
213 * @brief Set LCD Lower Panel Frame Buffer for Dual Panel
\r
214 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
215 * @param[in] buffer address of buffer
\r
217 **********************************************************************/
\r
218 void LCD_SetLPFrameBuffer(LPC_LCD_Type *LCDx, void* buffer){
\r
219 LCDx->LPBASE = (uint32_t)buffer;
\r
223 /*********************************************************************//**
\r
224 * @brief Configure Cursor
\r
225 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
226 * @param[in] cursor_size specify size of cursor
\r
227 * - LCD_CURSOR_32x32 :cursor size is 32x32 pixels
\r
228 * - LCD_CURSOR_64x64 :cursor size is 64x64 pixels
\r
229 * @param[in] sync cursor sync mode
\r
230 * - TRUE :cursor sync to the frame sync pulse
\r
231 * - FALSE :cursor async mode
\r
233 **********************************************************************/
\r
234 void LCD_Cursor_Config(LPC_LCD_Type *LCDx, LCD_CURSOR_SIZE_OPT cursor_size, Bool sync){
\r
235 LCD_Cursor_Size = cursor_size;
\r
236 LCDx->CRSR_CFG = ((sync?1:0)<<1) | cursor_size;
\r
240 /*********************************************************************//**
\r
241 * @brief Write Cursor Image into Internal Cursor Image Buffer
\r
242 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
243 * @param[in] cursor_num specify number of cursor is going to be written
\r
244 * this param must < 4
\r
245 * @param[in] Image point to Cursor Image Buffer
\r
247 **********************************************************************/
\r
248 void LCD_Cursor_WriteImage(LPC_LCD_Type *LCDx, uint8_t cursor_num, void* Image){
\r
250 uint8_t *fifoptr, *crsr_ptr = (uint8_t *)Image;
\r
252 CHECK_PARAM(cursor_num<4);
\r
253 /* Check if Cursor Size was configured as 32x32 or 64x64*/
\r
254 if(LCD_Cursor_Size == LCD_CURSOR_32x32){
\r
255 i = cursor_num * 256;
\r
261 fifoptr = (uint8_t*)&(LCDx->CRSR_IMG[0]);
\r
262 /* Copy Cursor Image content to FIFO */
\r
265 fifoptr[i] = *(uint8_t *)crsr_ptr;
\r
271 /*********************************************************************//**
\r
272 * @brief Get Internal Cursor Image Buffer Address
\r
273 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
274 * @param[in] cursor_num specify number of cursor is going to be written
\r
275 * this param must < 4
\r
276 * @return Cursor Image Buffer Address
\r
277 **********************************************************************/
\r
278 void* LCD_Cursor_GetImageBufferAddress(LPC_LCD_Type *LCDx, uint8_t cursor_num){
\r
279 CHECK_PARAM(cursor_num<4);
\r
280 return (void*)&(LCDx->CRSR_IMG[cursor_num*64]);
\r
284 /*********************************************************************//**
\r
285 * @brief Enable Cursor
\r
286 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
287 * @param[in] cursor_num specify number of cursor is going to be written
\r
288 * this param must < 4
\r
289 * @param[in] OnOff Turn on/off LCD
\r
293 **********************************************************************/
\r
294 void LCD_Cursor_Enable(LPC_LCD_Type *LCDx, uint8_t cursor_num, FunctionalState OnOff){
\r
295 CHECK_PARAM(cursor_num<4);
\r
298 LCDx->CRSR_CTRL = (cursor_num<<4) | 1;
\r
302 LCDx->CRSR_CTRL = (cursor_num<<4);
\r
307 /*********************************************************************//**
\r
308 * @brief Load LCD Palette
\r
309 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
310 * @param[in] palette point to palette address
\r
312 **********************************************************************/
\r
313 void LCD_LoadPalette(LPC_LCD_Type *LCDx, void* palette){
\r
314 LCD_PALETTE_ENTRY_Type pal_entry, *ptr_pal_entry;
\r
315 uint8_t i, *pal_ptr;
\r
316 /* This function supports loading of the color palette from
\r
317 the C file generated by the bmp2c utility. It expects the
\r
318 palette to be passed as an array of 32-bit BGR entries having
\r
319 the following format:
\r
327 arg = pointer to input palette table address */
\r
328 ptr_pal_entry = &pal_entry;
\r
329 pal_ptr = (uint8_t *) palette;
\r
331 /* 256 entry in the palette table */
\r
332 for(i = 0; i < 256/2; i++)
\r
334 pal_entry.Bl = (*pal_ptr++) >> 3; /* blue first */
\r
335 pal_entry.Gl = (*pal_ptr++) >> 3; /* get green */
\r
336 pal_entry.Rl = (*pal_ptr++) >> 3; /* get red */
\r
337 pal_ptr++; /* skip over the unused byte */
\r
338 /* do the most significant halfword of the palette */
\r
339 pal_entry.Bu = (*pal_ptr++) >> 3; /* blue first */
\r
340 pal_entry.Gu = (*pal_ptr++) >> 3; /* get green */
\r
341 pal_entry.Ru = (*pal_ptr++) >> 3; /* get red */
\r
342 pal_ptr++; /* skip over the unused byte */
\r
344 LCDx->PAL[i] = *(uint32_t *)ptr_pal_entry;
\r
349 /*********************************************************************//**
\r
350 * @brief Load Cursor Palette
\r
351 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
352 * @param[in] palette_color cursor palette 0 value
\r
354 **********************************************************************/
\r
355 void LCD_Cursor_LoadPalette0(LPC_LCD_Type *LCDx, uint32_t palette_color){
\r
360 LCDx->CRSR_PAL0 = (uint32_t)palette_color;
\r
364 /*********************************************************************//**
\r
365 * @brief Load Cursor Palette
\r
366 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
367 * @param[in] palette_color cursor palette 1 value
\r
369 **********************************************************************/
\r
370 void LCD_Cursor_LoadPalette1(LPC_LCD_Type *LCDx, uint32_t palette_color){
\r
375 LCDx->CRSR_PAL1 = (uint32_t)palette_color;
\r
379 /*********************************************************************//**
\r
380 * @brief Set Interrupt
\r
381 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
382 * @param[in] Int LCD Interrupt Source, should be:
\r
383 * - LCD_INT_FUF :FIFO underflow
\r
384 * - LCD_INT_LNBU :LCD next base address update bit
\r
385 * - LCD_INT_VCOMP :Vertical compare bit
\r
386 * - LCD_INT_BER :AHB master error interrupt bit
\r
388 **********************************************************************/
\r
389 void LCD_SetInterrupt(LPC_LCD_Type *LCDx, LCD_INT_SRC Int){
\r
390 LCDx->INTMSK |= Int;
\r
394 /*********************************************************************//**
\r
395 * @brief Clear Interrupt
\r
396 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
397 * @param[in] Int LCD Interrupt Source, should be:
\r
398 * - LCD_INT_FUF :FIFO underflow
\r
399 * - LCD_INT_LNBU :LCD next base address update bit
\r
400 * - LCD_INT_VCOMP :Vertical compare bit
\r
401 * - LCD_INT_BER :AHB master error interrupt bit
\r
403 **********************************************************************/
\r
404 void LCD_ClrInterrupt(LPC_LCD_Type *LCDx, LCD_INT_SRC Int){
\r
405 LCDx->INTCLR |= Int;
\r
409 /*********************************************************************//**
\r
410 * @brief Get LCD Interrupt Status
\r
411 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
413 **********************************************************************/
\r
414 LCD_INT_SRC LCD_GetInterrupt(LPC_LCD_Type *LCDx){
\r
415 return (LCD_INT_SRC)LCDx->INTRAW;
\r
419 /*********************************************************************//**
\r
420 * @brief Enable Cursor Interrupt
\r
421 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
423 **********************************************************************/
\r
424 void LCD_Cursor_SetInterrupt(LPC_LCD_Type *LCDx){
\r
425 LCDx->CRSR_INTMSK |= 1;
\r
429 /*********************************************************************//**
\r
430 * @brief Clear Cursor Interrupt
\r
431 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
433 **********************************************************************/
\r
434 void LCD_Cursor_ClrInterrupt(LPC_LCD_Type *LCDx){
\r
435 LCDx->CRSR_INTCLR |= 1;
\r
439 /*********************************************************************//**
\r
440 * @brief Set Cursor Position
\r
441 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
442 * @param[in] x horizontal position
\r
443 * @param[in] y vertical position
\r
445 **********************************************************************/
\r
446 void LCD_Cursor_SetPos(LPC_LCD_Type *LCDx, uint16_t x, uint16_t y){
\r
447 LCDx->CRSR_XY = (x & 0x3FF) | ((y & 0x3FF) << 16);
\r
451 /*********************************************************************//**
\r
452 * @brief Set Cursor Clipping Position
\r
453 * @param[in] LCDx pointer to LCD Controller Reg Struct, should be: LPC_LCD
\r
454 * @param[in] x horizontal position, should be in range: 0..63
\r
455 * @param[in] y vertical position, should be in range: 0..63
\r
457 **********************************************************************/
\r
458 void LCD_Cursor_SetClip(LPC_LCD_Type *LCDx, uint16_t x, uint16_t y){
\r
459 LCDx->CRSR_CLIP = (x & 0x3F) | ((y & 0x3F) << 8);
\r
467 /* --------------------------------- End Of File ------------------------------ */
\r