em_lcd.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_lcd.h"
00035 #if defined(LCD_COUNT) && (LCD_COUNT > 0)
00036 #include "em_assert.h"
00037 #include "em_bitband.h"
00038 
00039 /***************************************************************************/
00044 /***************************************************************************/
00050 /***************************************************************************/
00063 void LCD_Init(const LCD_Init_TypeDef *lcdInit)
00064 {
00065   uint32_t dispCtrl = LCD->DISPCTRL;
00066 
00067   EFM_ASSERT(lcdInit != (void *) 0);
00068 
00069   /* Disable controller before reconfiguration */
00070   LCD_Enable(false);
00071 
00072   /* Make sure we don't touch other bit fields (i.e. voltage boost) */
00073   dispCtrl &= ~(
00074 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00075     _LCD_DISPCTRL_MUXE_MASK |
00076 #endif
00077     _LCD_DISPCTRL_MUX_MASK |
00078     _LCD_DISPCTRL_BIAS_MASK |
00079     _LCD_DISPCTRL_WAVE_MASK |
00080     _LCD_DISPCTRL_VLCDSEL_MASK |
00081     _LCD_DISPCTRL_CONCONF_MASK);
00082 
00083   /* Configure controller according to initialization structure */
00084   dispCtrl |= lcdInit->mux; /* also configures MUXE */
00085   dispCtrl |= lcdInit->bias;
00086   dispCtrl |= lcdInit->wave;
00087   dispCtrl |= lcdInit->vlcd;
00088   dispCtrl |= lcdInit->contrast;
00089 
00090   /* Update display controller */
00091   LCD->DISPCTRL = dispCtrl;
00092 
00093   /* Enable controller if wanted */
00094   if (lcdInit->enable)
00095   {
00096     LCD_Enable(true);
00097   }
00098 }
00099 
00100 
00101 /***************************************************************************/
00108 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd)
00109 {
00110   uint32_t dispctrl = LCD->DISPCTRL;
00111 
00112   /* Select VEXT or VDD */
00113   dispctrl &= ~(_LCD_DISPCTRL_VLCDSEL_MASK);
00114   switch (vlcd)
00115   {
00116   case lcdVLCDSelVExtBoost:
00117     dispctrl |= LCD_DISPCTRL_VLCDSEL_VEXTBOOST;
00118     break;
00119   case lcdVLCDSelVDD:
00120     dispctrl |= LCD_DISPCTRL_VLCDSEL_VDD;
00121     break;
00122   default:
00123     break;
00124   }
00125 
00126   LCD->DISPCTRL = dispctrl;
00127 }
00128 
00129 
00130 /***************************************************************************/
00137 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud)
00138 {
00139   LCD->CTRL = (LCD->CTRL & ~_LCD_CTRL_UDCTRL_MASK) | ud;
00140 }
00141 
00142 
00143 /***************************************************************************/
00150 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit)
00151 {
00152   uint32_t bactrl = LCD->BACTRL;
00153 
00154   EFM_ASSERT(fcInit != (void *) 0);
00155 
00156   /* Verify FC Top Counter to be within limits */
00157   EFM_ASSERT(fcInit->top < 64);
00158 
00159   /* Reconfigure frame count configuration */
00160   bactrl &= ~(_LCD_BACTRL_FCTOP_MASK |
00161               _LCD_BACTRL_FCPRESC_MASK);
00162   bactrl |= (fcInit->top << _LCD_BACTRL_FCTOP_SHIFT);
00163   bactrl |= fcInit->prescale;
00164 
00165   /* Set Blink and Animation Control Register */
00166   LCD->BACTRL = bactrl;
00167 
00168   LCD_FrameCountEnable(fcInit->enable);
00169 }
00170 
00171 
00172 /***************************************************************************/
00179 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)
00180 {
00181   uint32_t bactrl = LCD->BACTRL;
00182 
00183   EFM_ASSERT(animInit != (void *) 0);
00184 
00185   /* Set Animation Register Values */
00186   LCD->AREGA = animInit->AReg;
00187   LCD->AREGB = animInit->BReg;
00188 
00189   /* Configure Animation Shift and Logic */
00190   bactrl &= ~(_LCD_BACTRL_AREGASC_MASK |
00191               _LCD_BACTRL_AREGBSC_MASK |
00192               _LCD_BACTRL_ALOGSEL_MASK);
00193 
00194   bactrl |= (animInit->AShift << _LCD_BACTRL_AREGASC_SHIFT);
00195   bactrl |= (animInit->BShift << _LCD_BACTRL_AREGBSC_SHIFT);
00196   bactrl |= animInit->animLogic;
00197 
00198 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00199   bactrl &= ~(_LCD_BACTRL_ALOC_MASK);
00200 
00201   if(animInit->startSeg == 0)
00202   {
00203     bactrl |= LCD_BACTRL_ALOC_SEG0TO7;
00204   }
00205   else if(animInit->startSeg == 8)
00206   {
00207     bactrl |= LCD_BACTRL_ALOC_SEG8TO15;
00208   }
00209 #endif
00210 
00211   /* Reconfigure */
00212   LCD->BACTRL = bactrl;
00213 
00214   /* Enable */
00215   LCD_AnimEnable(animInit->enable);
00216 }
00217 
00218 
00219 /***************************************************************************/
00230 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segmentRange, bool enable)
00231 {
00232   if (enable)
00233   {
00234     LCD->SEGEN |= segmentRange;
00235   }
00236   else
00237   {
00238     LCD->SEGEN &= ~((uint32_t)segmentRange);
00239   }
00240 }
00241 
00242 
00243 /***************************************************************************/
00261 void LCD_SegmentSet(int com, int bit, bool enable)
00262 {
00263 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00264   /* Tiny and Giant Family supports up to 8 COM lines */
00265   EFM_ASSERT(com < 8);
00266 #else
00267   /* Gecko Family supports up to 4 COM lines */
00268   EFM_ASSERT(com < 4);
00269 #endif
00270 
00271 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00272   EFM_ASSERT(bit < 40);
00273 #else
00274   /* Tiny Gecko Family supports only "low" segment registers */
00275   EFM_ASSERT(bit < 32);
00276 #endif
00277 
00278   /* Use bitband access for atomic bit set/clear of segment */
00279   switch (com)
00280   {
00281   case 0:
00282     if (bit < 32)
00283     {
00284       BITBAND_Peripheral(&(LCD->SEGD0L), bit, (unsigned int)enable);
00285     }
00286 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00287     else
00288     {
00289       bit -= 32;
00290       BITBAND_Peripheral(&(LCD->SEGD0H), bit, (unsigned int)enable);
00291     }
00292 #endif
00293     break;
00294   case 1:
00295     if (bit < 32)
00296     {
00297       BITBAND_Peripheral(&(LCD->SEGD1L), bit, (unsigned int)enable);
00298     }
00299 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00300     else
00301     {
00302       bit -= 32;
00303       BITBAND_Peripheral(&(LCD->SEGD1H), bit, (unsigned int)enable);
00304     }
00305 #endif
00306     break;
00307   case 2:
00308     if (bit < 32)
00309     {
00310       BITBAND_Peripheral(&(LCD->SEGD2L), bit, (unsigned int)enable);
00311     }
00312 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00313     else
00314     {
00315       bit -= 32;
00316       BITBAND_Peripheral(&(LCD->SEGD2H), bit, (unsigned int)enable);
00317     }
00318 #endif
00319     break;
00320   case 3:
00321     if (bit < 32)
00322     {
00323       BITBAND_Peripheral(&(LCD->SEGD3L), bit, (unsigned int)enable);
00324     }
00325 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00326     else
00327     {
00328       bit -= 32;
00329       BITBAND_Peripheral(&(LCD->SEGD3H), bit, (unsigned int)enable);
00330     }
00331 #endif
00332     break;
00333   case 4:
00334 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00335     if (bit < 32)
00336     {
00337       BITBAND_Peripheral(&(LCD->SEGD4L), bit, (unsigned int)enable);
00338     }
00339 #endif
00340 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00341     else
00342     {
00343       bit -= 32;
00344       BITBAND_Peripheral(&(LCD->SEGD4H), bit, (unsigned int)enable);
00345     }
00346 #endif
00347     break;
00348   case 5:
00349 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00350     if (bit < 32)
00351     {
00352       BITBAND_Peripheral(&(LCD->SEGD5L), bit, (unsigned int)enable);
00353     }
00354 #endif
00355 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00356     else
00357     {
00358       bit -= 32;
00359       BITBAND_Peripheral(&(LCD->SEGD5H), bit, (unsigned int)enable);
00360     }
00361 #endif
00362     break;
00363   case 6:
00364 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00365     if (bit < 32)
00366     {
00367       BITBAND_Peripheral(&(LCD->SEGD6L), bit, (unsigned int)enable);
00368     }
00369 #endif
00370 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00371     else
00372     {
00373       bit -= 32;
00374       BITBAND_Peripheral(&(LCD->SEGD6H), bit, (unsigned int)enable);
00375     }
00376 #endif
00377     break;
00378   case 7:
00379 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00380     if (bit < 32)
00381     {
00382       BITBAND_Peripheral(&(LCD->SEGD7L), bit, (unsigned int)enable);
00383     }
00384 #endif
00385 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00386     else
00387     {
00388       bit -= 32;
00389       BITBAND_Peripheral(&(LCD->SEGD7H), bit, (unsigned int)enable);
00390     }
00391 #endif
00392     break;
00393 
00394   default:
00395     EFM_ASSERT(0);
00396     break;
00397   }
00398 }
00399 
00400 
00401 /***************************************************************************/
00415 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)
00416 {
00417   uint32_t segData;
00418 
00419   /* Maximum number of com lines */
00420 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00421   EFM_ASSERT(com < 8);
00422 #else
00423   /* Gecko Family supports up to 4 COM lines */
00424   EFM_ASSERT(com < 4);
00425 #endif
00426 
00427   switch (com)
00428   {
00429   case 0:
00430     segData     = LCD->SEGD0L;
00431     segData    &= ~(mask);
00432     segData    |= (mask & bits);
00433     LCD->SEGD0L = segData;
00434     break;
00435   case 1:
00436     segData     = LCD->SEGD1L;
00437     segData    &= ~(mask);
00438     segData    |= (mask & bits);
00439     LCD->SEGD1L = segData;
00440     break;
00441   case 2:
00442     segData     = LCD->SEGD2L;
00443     segData    &= ~(mask);
00444     segData    |= (mask & bits);
00445     LCD->SEGD2L = segData;
00446     break;
00447   case 3:
00448     segData     = LCD->SEGD3L;
00449     segData    &= ~(mask);
00450     segData    |= (mask & bits);
00451     LCD->SEGD3L = segData;
00452     break;
00453 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00454   case 4:
00455     segData     = LCD->SEGD4L;
00456     segData    &= ~(mask);
00457     segData    |= (mask & bits);
00458     LCD->SEGD4L = segData;
00459     break;
00460 #endif
00461 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) 
00462   case 5:
00463     segData     = LCD->SEGD5L;
00464     segData    &= ~(mask);
00465     segData    |= (mask & bits);
00466     LCD->SEGD5L = segData;
00467     break;
00468 #endif
00469 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00470   case 6:
00471     segData     = LCD->SEGD6L;
00472     segData    &= ~(mask);
00473     segData    |= (mask & bits);
00474     LCD->SEGD6L = segData;
00475     break;
00476 #endif
00477 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00478   case 7:
00479     segData     = LCD->SEGD7L;
00480     segData    &= ~(mask);
00481     segData    |= (mask & bits);
00482     LCD->SEGD7L = segData;
00483     break;
00484 #endif
00485   default:
00486     EFM_ASSERT(0);
00487     break;
00488   }
00489 }
00490 
00491 
00492 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00493 /***************************************************************************/
00506 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)
00507 {
00508   uint32_t segData;
00509 
00510 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00511   EFM_ASSERT(com < 8);
00512 #endif
00513 #if defined(_EFM32_GECKO_FAMILY)
00514   EFM_ASSERT(com < 4);
00515 #endif
00516 
00517   /* Maximum number of com lines */
00518   switch (com)
00519   {
00520   case 0:
00521     segData     = LCD->SEGD0H;
00522     segData    &= ~(mask);
00523     segData    |= (mask & bits);
00524     LCD->SEGD0H = segData;
00525     break;
00526   case 1:
00527     segData     = LCD->SEGD1H;
00528     segData    &= ~(mask);
00529     segData    |= (mask & bits);
00530     LCD->SEGD1H = segData;
00531     break;
00532   case 2:
00533     segData     = LCD->SEGD2H;
00534     segData    &= ~(mask);
00535     segData    |= (mask & bits);
00536     LCD->SEGD2H = segData;
00537     break;
00538   case 3:
00539     segData     = LCD->SEGD3H;
00540     segData    &= ~(mask);
00541     segData    |= (mask & bits);
00542     LCD->SEGD3H = segData;
00543     break;
00544 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00545   case 4:
00546     segData     = LCD->SEGD4H;
00547     segData    &= ~(mask);
00548     segData    |= (mask & bits);
00549     LCD->SEGD4H = segData;
00550     break;
00551 #endif
00552 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00553   case 5:
00554     segData     = LCD->SEGD5H;
00555     segData    &= ~(mask);
00556     segData    |= (mask & bits);
00557     LCD->SEGD5H = segData;
00558     break;
00559 #endif
00560 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00561   case 6:
00562     segData     = LCD->SEGD6H;
00563     segData    &= ~(mask);
00564     segData    |= (mask & bits);
00565     LCD->SEGD6H = segData;
00566     break;
00567 #endif
00568 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00569   case 7:
00570     segData     = LCD->SEGD7H;
00571     segData    &= ~(mask);
00572     segData    |= (mask & bits);
00573     LCD->SEGD7H = segData;
00574     break;
00575 #endif
00576   default:
00577     break;
00578   }
00579 }
00580 #endif
00581 
00582 /***************************************************************************/
00589 void LCD_ContrastSet(int level)
00590 {
00591   EFM_ASSERT(level < 32);
00592 
00593   LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_CONLEV_MASK)
00594                   | (level << _LCD_DISPCTRL_CONLEV_SHIFT);
00595 }
00596 
00597 
00598 /***************************************************************************/
00607 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost)
00608 {
00609   /* Reconfigure Voltage Boost */
00610   LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_VBLEV_MASK) | vboost;
00611 }
00612 
00613 
00614 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00615 /***************************************************************************/
00634 void LCD_BiasSegmentSet(int segmentLine, int biasLevel)
00635 {
00636   int               biasRegister;
00637   int               bitShift;
00638   volatile uint32_t *segmentRegister;
00639 
00640 #if defined(_EFM32_TINY_FAMILY)
00641   EFM_ASSERT(segmentLine < 20);
00642 #endif
00643 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00644   EFM_ASSERT(segmentLine < 40);
00645 #endif
00646 #if defined(_EFM32_TINY_FAMILY)
00647   /* Bias config for 8 segment lines per SEGDnL register */
00648   biasRegister = segmentLine / 8;
00649   bitShift     = (segmentLine % 8) * 4;
00650 
00651   switch (biasRegister)
00652   {
00653   case 0:
00654     segmentRegister = &LCD->SEGD0L;
00655     break;
00656   case 1:
00657     segmentRegister = &LCD->SEGD1L;
00658     break;
00659   case 2:
00660     segmentRegister = &LCD->SEGD2L;
00661     break;
00662   case 3:
00663     segmentRegister = &LCD->SEGD3L;
00664     break;
00665   default:
00666     segmentRegister = (uint32_t *)0x00000000;
00667     EFM_ASSERT(0);
00668     break;
00669   }
00670 #endif
00671 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) 
00672   /* Bias config for 10 segment lines per SEGDn L+H registers */
00673   biasRegister = segmentLine / 10;
00674   bitShift     = (segmentLine % 10) * 4;
00675 
00676   switch (biasRegister)
00677   {
00678   case 0:
00679     if (bitShift < 32)
00680     {
00681       segmentRegister = &LCD->SEGD0L;
00682     }
00683     else
00684     {
00685       segmentRegister = &LCD->SEGD0H;
00686       bitShift       -= 32;
00687     }
00688     break;
00689   case 1:
00690     if (bitShift < 32)
00691     {
00692       segmentRegister = &LCD->SEGD1L;
00693     }
00694     else
00695     {
00696       segmentRegister = &LCD->SEGD1H;
00697       bitShift       -= 32;
00698     }
00699     break;
00700   case 2:
00701     if (bitShift < 32)
00702     {
00703       segmentRegister = &LCD->SEGD2L;
00704     }
00705     else
00706     {
00707       segmentRegister = &LCD->SEGD1H;
00708       bitShift       -= 32;
00709     }
00710     break;
00711   case 3:
00712     if (bitShift < 32)
00713     {
00714       segmentRegister = &LCD->SEGD3L;
00715     }
00716     else
00717     {
00718       segmentRegister = &LCD->SEGD3H;
00719       bitShift       -= 32;
00720     }
00721     break;
00722   default:
00723     segmentRegister = (uint32_t *)0x00000000;
00724     EFM_ASSERT(0);
00725     break;
00726   }
00727 #endif
00728 
00729   /* Configure new bias setting */
00730   *segmentRegister = (*segmentRegister & ~(0xF << bitShift)) | (biasLevel << bitShift);
00731 }
00732 
00733 
00734 /***************************************************************************/
00753 void LCD_BiasComSet(int comLine, int biasLevel)
00754 {
00755   int bitShift;
00756   EFM_ASSERT(comLine < 8);
00757 
00758   bitShift    = comLine * 4;
00759   LCD->SEGD4L = (LCD->SEGD4L & ~(0xF << bitShift)) | (biasLevel << bitShift);
00760 }
00761 #endif
00762 
00766 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */