The wait in mci_WaitForEvent will delay all card transactions.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LcdController.cpp Source File

LcdController.cpp

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