A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.
Dependents: LPC4088test LPC4088test_ledonly LPC4088test_deleteall LPC4088_RAMtest ... more
LcdController.cpp
00001 /* 00002 * Copyright 2013 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /****************************************************************************** 00018 * Includes 00019 *****************************************************************************/ 00020 00021 #include "mbed.h" 00022 #include "LcdController.h" 00023 00024 /****************************************************************************** 00025 * Defines and typedefs 00026 *****************************************************************************/ 00027 00028 #undef _SBF 00029 #define _SBF(p,v) (((uint32_t)(v)) << (p)) 00030 00031 #undef _BITMASK 00032 #define _BITMASK(field_width) (_BIT(field_width) - 1) 00033 00034 #undef _BIT 00035 #define _BIT(p) (((uint32_t)(1)) << (p)) 00036 00037 /*********************************************************************** 00038 * Color LCD controller horizontal axis plane control register definitions 00039 **********************************************************************/ 00040 00041 /* LCD controller horizontal axis plane control register pixels per line */ 00042 #define CLCDC_LCDTIMING0_PPL_WIDTH 6 00043 #define CLCDC_LCDTIMING0_PPL(n) _SBF(2, (((n) / 16) - 1) & _BITMASK(CLCDC_LCDTIMING0_PPL_WIDTH)) 00044 /* LCD controller horizontal axis plane control register HSYNC pulse width */ 00045 #define CLCDC_LCDTIMING0_HSW_WIDTH 8 00046 #define CLCDC_LCDTIMING0_HSW(n) _SBF(8, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING0_HSW_WIDTH)) 00047 /* LCD controller horizontal axis plane control register horizontal front porch */ 00048 #define CLCDC_LCDTIMING0_HFP_WIDTH 8 00049 #define CLCDC_LCDTIMING0_HFP(n) _SBF(16, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING0_HFP_WIDTH)) 00050 /* LCD controller horizontal axis plane control register horizontal back porch */ 00051 #define CLCDC_LCDTIMING0_HBP_WIDTH 8 00052 #define CLCDC_LCDTIMING0_HBP(n) _SBF(24, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING0_HBP_WIDTH)) 00053 00054 /*********************************************************************** 00055 * Color LCD controller vertical axis plane control register definitions 00056 **********************************************************************/ 00057 00058 /* LCD controller vertical axis plane control register lines per panel */ 00059 #define CLCDC_LCDTIMING1_LPP_WIDTH 10 00060 #define CLCDC_LCDTIMING1_LPP(n) _SBF(0, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING1_LPP_WIDTH)) 00061 /* LCD controller vertical axis plane control register VSYNC pulse width */ 00062 #define CLCDC_LCDTIMING1_VSW_WIDTH 6 00063 #define CLCDC_LCDTIMING1_VSW(n) _SBF(10, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING1_VSW_WIDTH)) 00064 /* LCD controller vertical axis plane control register vertical front porch */ 00065 #define CLCDC_LCDTIMING1_VFP_WIDTH 8 00066 #define CLCDC_LCDTIMING1_VFP(n) _SBF(16, (n) & _BITMASK(CLCDC_LCDTIMING1_VFP_WIDTH)) 00067 /* LCD controller vertical axis plane control register vertical back porch */ 00068 #define CLCDC_LCDTIMING1_VBP_WIDTH 8 00069 #define CLCDC_LCDTIMING1_VBP(n) _SBF(24, (n) & _BITMASK(CLCDC_LCDTIMING1_VBP_WIDTH)) 00070 00071 /*********************************************************************** 00072 * Color LCD controller clock and signal polarity control register definitions 00073 **********************************************************************/ 00074 00075 /* LCD controller clock and signal polarity control register panel clock divisor low*/ 00076 #define CLCDC_LCDTIMING2_PCD_LO_WIDTH 5 00077 #define CLCDC_LCDTIMING2_PCD_LO(n) _SBF(0, ((n) - 2) & _BITMASK(CLCDC_LCDTIMING2_PCD_LO_WIDTH)) 00078 /* LCD controller clock and signal polarity control register clock select */ 00079 #define CLCDC_LCDTIMING2_CLKSEL _BIT(5) 00080 /* LCD controller clock and signal polarity control register AC bias pin frequency */ 00081 #define CLCDC_LCDTIMING2_ACB_WIDTH 5 00082 #define CLCDC_LCDTIMING2_ACB(n) _SBF(6, ((n) - 1) & _BITMASK(CLCDC_LCDTIMING2_ACB_WIDTH)) 00083 /* LCD controller clock and signal polarity control register invert VSYNC */ 00084 #define CLCDC_LCDTIMING2_IVS _BIT(11) 00085 /* LCD controller clock and signal polarity control register invert HSYNC */ 00086 #define CLCDC_LCDTIMING2_IHS _BIT(12) 00087 /* LCD controller clock and signal polarity control register invert plane clock */ 00088 #define CLCDC_LCDTIMING2_IPC _BIT(13) 00089 /* LCD controller clock and signal polarity control register invert output enable */ 00090 #define CLCDC_LCDTIMING2_IOE _BIT(14) 00091 /* LCD controller clock and signal polarity control register clocks per line */ 00092 #define CLCDC_LCDTIMING2_CPL_WIDTH 10 00093 #define CLCDC_LCDTIMING2_CPL(n) _SBF(16, (n) & _BITMASK(CLCDC_LCDTIMING2_CPL_WIDTH)) 00094 /* LCD controller clock and signal polarity control register bypass pixel clock divider */ 00095 #define CLCDC_LCDTIMING2_BCD _BIT(26) 00096 /* LCD controller clock and signal polarity control register panel clock divisor high*/ 00097 #define CLCDC_LCDTIMING2_PCD_HI_WIDTH 5 00098 #define CLCDC_LCDTIMING2_PCD_HI(n) _SBF((27 - CLCDC_LCDTIMING2_PCD_LO_WIDTH), ((n) - 2) & _SBF(CLCDC_LCDTIMING2_PCD_LO_WIDTH, _BITMASK(CLCDC_LCDTIMING2_PCD_HI_WIDTH))) 00099 00100 00101 /*********************************************************************** 00102 * Color LCD controller control register definitions 00103 **********************************************************************/ 00104 00105 /* LCD control enable bit */ 00106 #define CLCDC_LCDCTRL_ENABLE (1<<0) 00107 /* LCD control 1 bit per pixel bit field */ 00108 #define CLCDC_LCDCTRL_BPP1 (0 << 1) 00109 /* LCD control 2 bits per pixel bit field */ 00110 #define CLCDC_LCDCTRL_BPP2 (1 << 1) 00111 /* LCD control 4 bits per pixel bit field */ 00112 #define CLCDC_LCDCTRL_BPP4 (2 << 1) 00113 /* LCD control 8 bits per pixel bit field */ 00114 #define CLCDC_LCDCTRL_BPP8 (3 << 1) 00115 /* LCD control 16 bits per pixel bit field */ 00116 #define CLCDC_LCDCTRL_BPP16 (4 << 1) 00117 /* LCD control 24 bits per pixel bit field */ 00118 #define CLCDC_LCDCTRL_BPP24 (5 << 1) 00119 /* LCD control 16 bits (5:6:5 mode) per pixel bit field */ 00120 #define CLCDC_LCDCTRL_BPP16_565_MODE (6 << 1) 00121 /* LCD control 12 bits (4:4:4 mode) per pixel bit field */ 00122 #define CLCDC_LCDCTRL_BPP12_444_MODE (7 << 1) 00123 /* LCD control mono select bit */ 00124 #define CLCDC_LCDCTRL_BW_COLOR (0 << 4) 00125 #define CLCDC_LCDCTRL_BW_MONO (1 << 4) 00126 /* LCD controler TFT select bit */ 00127 #define CLCDC_LCDCTRL_TFT (1 << 5) 00128 /* LCD control monochrome LCD has 4-bit/8-bit select bit */ 00129 #define CLCDC_LCDCTRL_MON8 (1 << 6) 00130 /* LCD control dual panel select bit */ 00131 #define CLCDC_LCDCTRL_DUAL (1 << 7) 00132 /* LCD control RGB or BGR format select bit */ 00133 #define CLCDC_LCDCTRL_RGB (0 << 8) 00134 #define CLCDC_LCDCTRL_BGR (1 << 8) 00135 /* LCD control big-endian byte order select bit */ 00136 #define CLCDC_LCDCTRL_BEBO (1 << 9) 00137 /* LCD control big-endian pixel order within a byte select bit */ 00138 #define CLCDC_LCDCTRL_BEPO (1 << 10) 00139 /* LCD control power enable bit */ 00140 #define CLCDC_LCDCTRL_PWR (1 << 11) 00141 /* LCD control VCOMP interrupt is start of VSYNC */ 00142 #define CLCDC_LCDCTRL_VCOMP_VS (0 << 12) 00143 /* LCD control VCOMP interrupt is start of back porch */ 00144 #define CLCDC_LCDCTRL_VCOMP_BP (1 << 12) 00145 /* LCD control VCOMP interrupt is start of active video */ 00146 #define CLCDC_LCDCTRL_VCOMP_AV (2 << 12) 00147 /* LCD control VCOMP interrupt is start of front porch */ 00148 #define CLCDC_LCDCTRL_VCOMP_FP (3 << 12) 00149 /* LCD control watermark level is 8 or more words free bit */ 00150 #define CLCDC_LCDCTRL_WATERMARK (1 << 16) 00151 00152 00153 00154 bool LcdController::_lcdControllerUsed = false; 00155 00156 LcdController::LcdController() { 00157 _opened = false; 00158 } 00159 00160 int LcdController::open(LcdController::Config* cfg) { 00161 if (_lcdControllerUsed) return 1; 00162 if (cfg == NULL) return 1; 00163 00164 // enable power for LCD controller 00165 LPC_SC->PCONP |= 0x00000001; 00166 00167 pinConfig(); 00168 init(cfg); 00169 00170 // only one instance at a time is allowed to be used 00171 _lcdControllerUsed = true; 00172 _opened = true; 00173 00174 return 0; 00175 } 00176 00177 int LcdController::close() { 00178 00179 if (!_opened) return 1; 00180 00181 if (_lcdControllerUsed) { 00182 00183 // disable power for LCD controller 00184 LPC_SC->PCONP &= ~(0x00000001); 00185 00186 _lcdControllerUsed = false; 00187 _opened = false; 00188 } 00189 00190 00191 return 0; 00192 } 00193 00194 int LcdController::setFrameBuffer(uint32_t address) { 00195 if (!_opened) return 1; 00196 00197 LPC_LCD->UPBASE = address; 00198 00199 return 0; 00200 } 00201 00202 int LcdController::setPower(bool on) { 00203 if (!_opened) return 1; 00204 00205 if (on) { 00206 LPC_LCD->CTRL |= CLCDC_LCDCTRL_ENABLE; 00207 LPC_LCD->CTRL |= CLCDC_LCDCTRL_PWR; 00208 } 00209 else { 00210 LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_PWR; 00211 LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_ENABLE; 00212 } 00213 00214 return 0; 00215 } 00216 00217 void LcdController::init(LcdController::Config* cfg) { 00218 uint32_t tmp, i; 00219 00220 // Disable the display in case it is on 00221 LPC_LCD->CTRL &= ~CLCDC_LCDCTRL_ENABLE; 00222 00223 // Generate the horizontal axis plane control word 00224 tmp = (CLCDC_LCDTIMING0_PPL(cfg->width) | 00225 CLCDC_LCDTIMING0_HSW(cfg->hsync) | 00226 CLCDC_LCDTIMING0_HFP(cfg->horizontalFrontPorch) | 00227 CLCDC_LCDTIMING0_HBP(cfg->horizontalBackPorch)); 00228 LPC_LCD->TIMH = tmp; 00229 00230 // Generate the vertical axis plane control word 00231 tmp = (CLCDC_LCDTIMING1_LPP(cfg->height) | 00232 CLCDC_LCDTIMING1_VSW(cfg->vsync) | 00233 CLCDC_LCDTIMING1_VFP(cfg->verticalFrontPorch) | 00234 CLCDC_LCDTIMING1_VBP(cfg->verticalBackPorch)); 00235 LPC_LCD->TIMV = tmp; 00236 00237 // Generate the clock and signal polarity control word 00238 if(cfg->acBias != 0) 00239 { 00240 /* STN panel has AC bias value */ 00241 tmp = CLCDC_LCDTIMING2_ACB(cfg->acBias); 00242 } 00243 else 00244 { 00245 tmp = 0; 00246 } 00247 00248 if (cfg->invertOutputEnable) 00249 { 00250 tmp |= CLCDC_LCDTIMING2_IOE; 00251 } 00252 00253 if (cfg->invertPanelClock) 00254 { 00255 tmp |= CLCDC_LCDTIMING2_IPC; 00256 } 00257 00258 if (cfg->invertHsync) 00259 { 00260 tmp |= CLCDC_LCDTIMING2_IHS; 00261 } 00262 00263 if (cfg->invertVsync) 00264 { 00265 tmp |= CLCDC_LCDTIMING2_IVS; 00266 } 00267 00268 // Compute clocks per line based on panel type 00269 switch (cfg->panelType) 00270 { 00271 case Mono_4Bit: 00272 // Clocks per line is a quarter of pixels per line 00273 tmp = tmp | CLCDC_LCDTIMING2_CPL((cfg->width / 4) - 1); 00274 break; 00275 00276 case Mono_8Bit: 00277 // Clocks per line is an eighth of pixels per line 00278 tmp = tmp | CLCDC_LCDTIMING2_CPL((cfg->width / 8) - 1); 00279 break; 00280 00281 case ColorStn: 00282 // CSTN Clocks per line (* 3 / 8) 00283 tmp = tmp | CLCDC_LCDTIMING2_CPL(((cfg->width * 3) / 8) - 1); 00284 break; 00285 00286 case Tft: 00287 case AdTft: 00288 case HrTft: 00289 default: 00290 // Clocks per line and pixels per line are the same 00291 tmp = tmp | CLCDC_LCDTIMING2_CPL(cfg->width - 1); 00292 break; 00293 } 00294 00295 // clock 00296 tmp = tmp | getClockDivisor(cfg->optimalClock); 00297 00298 LPC_LCD->POL = tmp; 00299 00300 // Skip line end control word - just set to 0x0 00301 LPC_LCD->LE = 0x00000000; 00302 00303 // Default with all interrupts of 00304 LPC_LCD->INTMSK = 0x00000000; 00305 00306 00307 switch(cfg->bpp) { 00308 case Bpp_1: 00309 tmp = CLCDC_LCDCTRL_BPP1; 00310 break; 00311 case Bpp_2: 00312 tmp = CLCDC_LCDCTRL_BPP2; 00313 break; 00314 case Bpp_4: 00315 tmp = CLCDC_LCDCTRL_BPP4; 00316 break; 00317 case Bpp_8: 00318 tmp = CLCDC_LCDCTRL_BPP8; 00319 break; 00320 case Bpp_16: 00321 tmp = CLCDC_LCDCTRL_BPP16; 00322 break; 00323 case Bpp_24: 00324 tmp = CLCDC_LCDCTRL_BPP24; 00325 break; 00326 case Bpp_16_565: 00327 tmp = CLCDC_LCDCTRL_BPP16_565_MODE; 00328 break; 00329 case Bpp_12_444: 00330 tmp = CLCDC_LCDCTRL_BPP12_444_MODE; 00331 break; 00332 default: 00333 tmp = CLCDC_LCDCTRL_BPP16_565_MODE; 00334 break; 00335 } 00336 00337 // red and blue swapped 00338 tmp |= CLCDC_LCDCTRL_BGR; 00339 00340 switch (cfg->panelType) 00341 { 00342 case AdTft: 00343 case HrTft: 00344 case Tft: 00345 tmp |= CLCDC_LCDCTRL_TFT; 00346 break; 00347 00348 case Mono_4Bit: 00349 tmp |= CLCDC_LCDCTRL_BW_MONO; 00350 break; 00351 00352 case Mono_8Bit: 00353 tmp |= (CLCDC_LCDCTRL_MON8 | CLCDC_LCDCTRL_BW_MONO); 00354 break; 00355 00356 case ColorStn: 00357 ; 00358 break; 00359 00360 default: 00361 // Unsupported panel type 00362 break; 00363 } 00364 00365 // Dual panel operation 00366 if (cfg->dualPanel) 00367 { 00368 tmp |= CLCDC_LCDCTRL_DUAL; 00369 } 00370 00371 LPC_LCD->CTRL = tmp; 00372 00373 // clear the palette (color is black ) 00374 for (i = 0; i < sizeof(LPC_LCD->PAL)/sizeof(LPC_LCD->PAL[0]); i++) 00375 { 00376 LPC_LCD->PAL[i] = 0; 00377 } 00378 00379 LPC_SC->LCD_CFG = 0x0; 00380 00381 } 00382 00383 void LcdController::pinConfig() { 00384 00385 LPC_IOCON->P0_4 |= 7; /* LCD_VD_0 @ P0.4 */ 00386 LPC_IOCON->P0_5 |= 7; /* LCD_VD_1 @ P0.5 */ 00387 LPC_IOCON->P0_6 |= 7; /* LCD_VD_8 @ P0.6 */ 00388 LPC_IOCON->P0_7 |= 7; /* LCD_VD_9 @ P0.7 */ 00389 LPC_IOCON->P0_8 |= 7; /* LCD_VD_16 @ P0.8 */ 00390 LPC_IOCON->P0_9 |= 7; /* LCD_VD_17 @ P0.9 */ 00391 LPC_IOCON->P0_10 |= 7; /* LCD_VD_5 @ P0.10 */ /* LPC4088 */ 00392 00393 #ifdef LPC4088_OEM 00394 LPC_IOCON->P1_20 |= 7; /* LCD_VD_10 @ P1.20 */ 00395 LPC_IOCON->P1_23 |= 7; /* LCD_VD_13 @ P1.23 */ 00396 LPC_IOCON->P1_24 |= 7; /* LCD_VD_14 @ P1.24 */ 00397 #else 00398 LPC_IOCON->P0_11 |= 7; /* LCD_VD_10 @ P0.11 */ 00399 LPC_IOCON->P0_19 |= 7; /* LCD_VD_13 @ P0.19 */ 00400 LPC_IOCON->P0_20 |= 7; /* LCD_VD_14 @ P0.20 */ 00401 #endif 00402 00403 LPC_IOCON->P1_21 |= 7; /* LCD_VD_11 @ P1.21 */ 00404 LPC_IOCON->P1_22 |= 7; /* LCD_VD_12 @ P1.22 */ 00405 00406 LPC_IOCON->P1_25 |= 7; /* LCD_VD_15 @ P1.25 */ 00407 LPC_IOCON->P1_26 |= 7; /* LCD_VD_20 @ P1.26 */ 00408 LPC_IOCON->P1_27 |= 7; /* LCD_VD_21 @ P1.27 */ 00409 LPC_IOCON->P1_28 |= 7; /* LCD_VD_22 @ P1.28 */ 00410 LPC_IOCON->P1_29 |= 7; /* LCD_VD_23 @ P1.29 */ 00411 00412 // pwr always controlled by gpio 00413 // LPC_IOCON->P2_0 |= 7; /* LCD_PWR @ P2.0 */ 00414 // LPC_IOCON->P2_1 |= 7; /* LCD_LE @ P2.1 */ /* Never Used */ 00415 LPC_IOCON->P2_2 |= 7; /* LCD_DCLK @ P2.2 */ 00416 LPC_IOCON->P2_3 |= 7; /* LCD_FP @ P2.3 */ 00417 LPC_IOCON->P2_4 |= 7; /* LCD_ENAB_M @ P2.4 */ 00418 LPC_IOCON->P2_5 |= 7; /* LCD_LP @ P2.5 */ 00419 LPC_IOCON->P2_6 |= 7; /* LCD_VD_4 @ P2.6 */ 00420 //LPC_IOCON->P2_7 |= 7; /* LCD_VD_5 @ P2.7 */ /* LPC4088 */ 00421 LPC_IOCON->P2_8 |= 7; /* LCD_VD_6 @ P2.8 */ 00422 LPC_IOCON->P2_9 |= 7; /* LCD_VD_7 @ P2.9 */ 00423 00424 LPC_IOCON->P2_11 |= 7; /* LCD_CLKIN @ P2.11 */ 00425 LPC_IOCON->P2_12 |= 5; /* LCD_VD_3 @ P2.12 Signal marked as LCD_VD_18 on base board, but shall carry the LCD_VD_3 signal */ 00426 LPC_IOCON->P2_13 |= 7; /* LCD_VD_19 @ P2.13 */ 00427 } 00428 00429 uint32_t LcdController::getClockDivisor(int clock) { 00430 uint32_t pixel_div, tmp = 0; 00431 uint32_t clk; 00432 00433 clk = SystemCoreClock; 00434 00435 // Find closest clock divider to get clock rate 00436 pixel_div = 1; 00437 while (((clk / pixel_div) > clock) && (pixel_div <= 0x3F)) 00438 { 00439 pixel_div++; 00440 } 00441 00442 if (pixel_div <= 1) 00443 { 00444 // Pixel clock divider is 1, skip divider logic 00445 tmp = CLCDC_LCDTIMING2_BCD; 00446 } 00447 else 00448 { 00449 // Add in new divider 00450 pixel_div -= 2; 00451 00452 tmp |= (((pixel_div >> 0) & 0x1F) 00453 | (((pixel_div >> 5) & 0x1F) << 27)); 00454 } 00455 00456 return tmp; 00457 } 00458 00459
Generated on Fri Jul 15 2022 02:16:08 by 1.7.2