EFM32 Giant Gecko Software Documentation  efm32gg-doc-4.2.1
em_lcd.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_lcd.h"
34 #if defined(LCD_COUNT) && (LCD_COUNT > 0)
35 #include "em_assert.h"
36 #include "em_bus.h"
37 
38 /***************************************************************************/
43 /***************************************************************************/
49 /***************************************************************************/
62 void LCD_Init(const LCD_Init_TypeDef *lcdInit)
63 {
64  uint32_t dispCtrl = LCD->DISPCTRL;
65 
66  EFM_ASSERT(lcdInit != (void *) 0);
67 
68  /* Disable controller before reconfiguration */
69  LCD_Enable(false);
70 
71  /* Make sure we don't touch other bit fields (i.e. voltage boost) */
72  dispCtrl &= ~(0
73 #if defined(LCD_DISPCTRL_MUXE)
75 #endif
81 
82  /* Configure controller according to initialization structure */
83  dispCtrl |= lcdInit->mux; /* also configures MUXE */
84  dispCtrl |= lcdInit->bias;
85  dispCtrl |= lcdInit->wave;
86  dispCtrl |= lcdInit->vlcd;
87  dispCtrl |= lcdInit->contrast;
88 
89  /* Update display controller */
90  LCD->DISPCTRL = dispCtrl;
91 
92  /* Enable controller if wanted */
93  if (lcdInit->enable)
94  {
95  LCD_Enable(true);
96  }
97 }
98 
99 
100 /***************************************************************************/
108 {
109  uint32_t dispctrl = LCD->DISPCTRL;
110 
111  /* Select VEXT or VDD */
112  dispctrl &= ~_LCD_DISPCTRL_VLCDSEL_MASK;
113  switch (vlcd)
114  {
115  case lcdVLCDSelVExtBoost:
116  dispctrl |= LCD_DISPCTRL_VLCDSEL_VEXTBOOST;
117  break;
118  case lcdVLCDSelVDD:
119  dispctrl |= LCD_DISPCTRL_VLCDSEL_VDD;
120  break;
121  default:
122  break;
123  }
124 
125  LCD->DISPCTRL = dispctrl;
126 }
127 
128 
129 /***************************************************************************/
137 {
138  LCD->CTRL = (LCD->CTRL & ~_LCD_CTRL_UDCTRL_MASK) | ud;
139 }
140 
141 
142 /***************************************************************************/
150 {
151  uint32_t bactrl = LCD->BACTRL;
152 
153  EFM_ASSERT(fcInit != (void *) 0);
154 
155  /* Verify FC Top Counter to be within limits */
156  EFM_ASSERT(fcInit->top < 64);
157 
158  /* Reconfigure frame count configuration */
159  bactrl &= ~(_LCD_BACTRL_FCTOP_MASK
161  bactrl |= (fcInit->top << _LCD_BACTRL_FCTOP_SHIFT);
162  bactrl |= fcInit->prescale;
163 
164  /* Set Blink and Animation Control Register */
165  LCD->BACTRL = bactrl;
166 
167  LCD_FrameCountEnable(fcInit->enable);
168 }
169 
170 
171 /***************************************************************************/
178 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)
179 {
180  uint32_t bactrl = LCD->BACTRL;
181 
182  EFM_ASSERT(animInit != (void *) 0);
183 
184  /* Set Animation Register Values */
185  LCD->AREGA = animInit->AReg;
186  LCD->AREGB = animInit->BReg;
187 
188  /* Configure Animation Shift and Logic */
189  bactrl &= ~(_LCD_BACTRL_AREGASC_MASK
192 
193  bactrl |= (animInit->AShift << _LCD_BACTRL_AREGASC_SHIFT);
194  bactrl |= (animInit->BShift << _LCD_BACTRL_AREGBSC_SHIFT);
195  bactrl |= animInit->animLogic;
196 
197 #if defined(LCD_BACTRL_ALOC)
198  bactrl &= ~(_LCD_BACTRL_ALOC_MASK);
199 
200  if(animInit->startSeg == 0)
201  {
202  bactrl |= LCD_BACTRL_ALOC_SEG0TO7;
203  }
204  else if(animInit->startSeg == 8)
205  {
206  bactrl |= LCD_BACTRL_ALOC_SEG8TO15;
207  }
208 #endif
209 
210  /* Reconfigure */
211  LCD->BACTRL = bactrl;
212 
213  /* Enable */
214  LCD_AnimEnable(animInit->enable);
215 }
216 
217 
218 /***************************************************************************/
229 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segmentRange, bool enable)
230 {
231  if (enable)
232  {
233  LCD->SEGEN |= segmentRange;
234  }
235  else
236  {
237  LCD->SEGEN &= ~((uint32_t)segmentRange);
238  }
239 }
240 
241 
242 /***************************************************************************/
260 void LCD_SegmentSet(int com, int bit, bool enable)
261 {
262 #if defined(_LCD_SEGD7L_MASK)
263  /* Tiny and Giant Family supports up to 8 COM lines */
264  EFM_ASSERT(com < 8);
265 #else
266  /* Gecko Family supports up to 4 COM lines */
267  EFM_ASSERT(com < 4);
268 #endif
269 
270 #if defined(_LCD_SEGD0H_MASK)
271  EFM_ASSERT(bit < 40);
272 #else
273  /* Tiny Gecko Family supports only "low" segment registers */
274  EFM_ASSERT(bit < 32);
275 #endif
276 
277  /* Use bitband access for atomic bit set/clear of segment */
278  switch (com)
279  {
280  case 0:
281  if (bit < 32)
282  {
283  BUS_RegBitWrite(&(LCD->SEGD0L), bit, enable);
284  }
285 #if defined(_LCD_SEGD0H_MASK)
286  else
287  {
288  bit -= 32;
289  BUS_RegBitWrite(&(LCD->SEGD0H), bit, enable);
290  }
291 #endif
292  break;
293  case 1:
294  if (bit < 32)
295  {
296  BUS_RegBitWrite(&(LCD->SEGD1L), bit, enable);
297  }
298 #if defined(_LCD_SEGD1H_MASK)
299  else
300  {
301  bit -= 32;
302  BUS_RegBitWrite(&(LCD->SEGD1H), bit, enable);
303  }
304 #endif
305  break;
306  case 2:
307  if (bit < 32)
308  {
309  BUS_RegBitWrite(&(LCD->SEGD2L), bit, enable);
310  }
311 #if defined(_LCD_SEGD2H_MASK)
312  else
313  {
314  bit -= 32;
315  BUS_RegBitWrite(&(LCD->SEGD2H), bit, enable);
316  }
317 #endif
318  break;
319  case 3:
320  if (bit < 32)
321  {
322  BUS_RegBitWrite(&(LCD->SEGD3L), bit, enable);
323  }
324 #if defined(_LCD_SEGD3H_MASK)
325  else
326  {
327  bit -= 32;
328  BUS_RegBitWrite(&(LCD->SEGD3H), bit, enable);
329  }
330 #endif
331  break;
332 #if defined(_LCD_SEGD4L_MASK)
333  case 4:
334  if (bit < 32)
335  {
336  BUS_RegBitWrite(&(LCD->SEGD4L), bit, enable);
337  }
338 #if defined(_LCD_SEGD4H_MASK)
339  else
340  {
341  bit -= 32;
342  BUS_RegBitWrite(&(LCD->SEGD4H), bit, enable);
343  }
344 #endif
345  break;
346 #endif
347 #if defined(_LCD_SEGD5L_MASK)
348  case 5:
349  if (bit < 32)
350  {
351  BUS_RegBitWrite(&(LCD->SEGD5L), bit, enable);
352  }
353 #if defined(_LCD_SEGD5H_MASK)
354  else
355  {
356  bit -= 32;
357  BUS_RegBitWrite(&(LCD->SEGD5H), bit, enable);
358  }
359 #endif
360  break;
361 #endif
362  case 6:
363 #if defined(_LCD_SEGD6L_MASK)
364  if (bit < 32)
365  {
366  BUS_RegBitWrite(&(LCD->SEGD6L), bit, enable);
367  }
368 #if defined(_LCD_SEGD6H_MASK)
369  else
370  {
371  bit -= 32;
372  BUS_RegBitWrite(&(LCD->SEGD6H), bit, enable);
373  }
374 #endif
375  break;
376 #endif
377 #if defined(_LCD_SEGD7L_MASK)
378  case 7:
379  if (bit < 32)
380  {
381  BUS_RegBitWrite(&(LCD->SEGD7L), bit, enable);
382  }
383 #if defined(_LCD_SEGD7H_MASK)
384  else
385  {
386  bit -= 32;
387  BUS_RegBitWrite(&(LCD->SEGD7H), bit, enable);
388  }
389 #endif
390  break;
391 #endif
392 
393  default:
394  EFM_ASSERT(0);
395  break;
396  }
397 }
398 
399 
400 /***************************************************************************/
414 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)
415 {
416  uint32_t segData;
417 
418  /* Maximum number of com lines */
419 #if defined(_LCD_SEGD7L_MASK)
420  EFM_ASSERT(com < 8);
421 #else
422  /* Gecko Family supports up to 4 COM lines */
423  EFM_ASSERT(com < 4);
424 #endif
425 
426  switch (com)
427  {
428  case 0:
429  segData = LCD->SEGD0L;
430  segData &= ~(mask);
431  segData |= (mask & bits);
432  LCD->SEGD0L = segData;
433  break;
434  case 1:
435  segData = LCD->SEGD1L;
436  segData &= ~(mask);
437  segData |= (mask & bits);
438  LCD->SEGD1L = segData;
439  break;
440  case 2:
441  segData = LCD->SEGD2L;
442  segData &= ~(mask);
443  segData |= (mask & bits);
444  LCD->SEGD2L = segData;
445  break;
446  case 3:
447  segData = LCD->SEGD3L;
448  segData &= ~(mask);
449  segData |= (mask & bits);
450  LCD->SEGD3L = segData;
451  break;
452 #if defined(_LCD_SEGD4L_MASK)
453  case 4:
454  segData = LCD->SEGD4L;
455  segData &= ~(mask);
456  segData |= (mask & bits);
457  LCD->SEGD4L = segData;
458  break;
459 #endif
460 #if defined(_LCD_SEGD5L_MASK)
461  case 5:
462  segData = LCD->SEGD5L;
463  segData &= ~(mask);
464  segData |= (mask & bits);
465  LCD->SEGD5L = segData;
466  break;
467 #endif
468 #if defined(_LCD_SEGD6L_MASK)
469  case 6:
470  segData = LCD->SEGD6L;
471  segData &= ~(mask);
472  segData |= (mask & bits);
473  LCD->SEGD6L = segData;
474  break;
475 #endif
476 #if defined(_LCD_SEGD7L_MASK)
477  case 7:
478  segData = LCD->SEGD7L;
479  segData &= ~(mask);
480  segData |= (mask & bits);
481  LCD->SEGD7L = segData;
482  break;
483 #endif
484  default:
485  EFM_ASSERT(0);
486  break;
487  }
488 }
489 
490 
491 #if defined(_LCD_SEGD0H_MASK)
492 /***************************************************************************/
505 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)
506 {
507  uint32_t segData;
508 
509 #if defined(_LCD_SEGD7H_MASK)
510  EFM_ASSERT(com < 8);
511 #else
512  EFM_ASSERT(com < 4);
513 #endif
514 
515  /* Maximum number of com lines */
516  switch (com)
517  {
518  case 0:
519  segData = LCD->SEGD0H;
520  segData &= ~(mask);
521  segData |= (mask & bits);
522  LCD->SEGD0H = segData;
523  break;
524  case 1:
525  segData = LCD->SEGD1H;
526  segData &= ~(mask);
527  segData |= (mask & bits);
528  LCD->SEGD1H = segData;
529  break;
530  case 2:
531  segData = LCD->SEGD2H;
532  segData &= ~(mask);
533  segData |= (mask & bits);
534  LCD->SEGD2H = segData;
535  break;
536  case 3:
537  segData = LCD->SEGD3H;
538  segData &= ~(mask);
539  segData |= (mask & bits);
540  LCD->SEGD3H = segData;
541  break;
542 #if defined(_LCD_SEGD4H_MASK)
543  case 4:
544  segData = LCD->SEGD4H;
545  segData &= ~(mask);
546  segData |= (mask & bits);
547  LCD->SEGD4H = segData;
548  break;
549 #endif
550 #if defined(_LCD_SEGD5H_MASK)
551  case 5:
552  segData = LCD->SEGD5H;
553  segData &= ~(mask);
554  segData |= (mask & bits);
555  LCD->SEGD5H = segData;
556  break;
557 #endif
558 #if defined(_LCD_SEGD6H_MASK)
559  case 6:
560  segData = LCD->SEGD6H;
561  segData &= ~(mask);
562  segData |= (mask & bits);
563  LCD->SEGD6H = segData;
564  break;
565 #endif
566 #if defined(_LCD_SEGD7H_MASK)
567  case 7:
568  segData = LCD->SEGD7H;
569  segData &= ~(mask);
570  segData |= (mask & bits);
571  LCD->SEGD7H = segData;
572  break;
573 #endif
574  default:
575  break;
576  }
577 }
578 #endif
579 
580 /***************************************************************************/
587 void LCD_ContrastSet(int level)
588 {
589  EFM_ASSERT(level < 32);
590 
591  LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_CONLEV_MASK)
592  | (level << _LCD_DISPCTRL_CONLEV_SHIFT);
593 }
594 
595 
596 /***************************************************************************/
606 {
607  /* Reconfigure Voltage Boost */
608  LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_VBLEV_MASK) | vboost;
609 }
610 
611 
612 #if defined(LCD_CTRL_DSC)
613 /***************************************************************************/
632 void LCD_BiasSegmentSet(int segmentLine, int biasLevel)
633 {
634  int biasRegister;
635  int bitShift;
636  volatile uint32_t *segmentRegister;
637 
638 #if !defined(_LCD_SEGD0H_MASK)
639  EFM_ASSERT(segmentLine < 20);
640 
641  /* Bias config for 8 segment lines per SEGDnL register */
642  biasRegister = segmentLine / 8;
643  bitShift = (segmentLine % 8) * 4;
644 
645  switch (biasRegister)
646  {
647  case 0:
648  segmentRegister = &LCD->SEGD0L;
649  break;
650  case 1:
651  segmentRegister = &LCD->SEGD1L;
652  break;
653  case 2:
654  segmentRegister = &LCD->SEGD2L;
655  break;
656  case 3:
657  segmentRegister = &LCD->SEGD3L;
658  break;
659  default:
660  segmentRegister = (uint32_t *)0x00000000;
661  EFM_ASSERT(0);
662  break;
663  }
664 #else
665  EFM_ASSERT(segmentLine < 40);
666 
667  /* Bias config for 10 segment lines per SEGDn L+H registers */
668  biasRegister = segmentLine / 10;
669  bitShift = (segmentLine % 10) * 4;
670 
671  switch (biasRegister)
672  {
673  case 0:
674  if (bitShift < 32)
675  {
676  segmentRegister = &LCD->SEGD0L;
677  }
678  else
679  {
680  segmentRegister = &LCD->SEGD0H;
681  bitShift -= 32;
682  }
683  break;
684  case 1:
685  if (bitShift < 32)
686  {
687  segmentRegister = &LCD->SEGD1L;
688  }
689  else
690  {
691  segmentRegister = &LCD->SEGD1H;
692  bitShift -= 32;
693  }
694  break;
695  case 2:
696  if (bitShift < 32)
697  {
698  segmentRegister = &LCD->SEGD2L;
699  }
700  else
701  {
702  segmentRegister = &LCD->SEGD1H;
703  bitShift -= 32;
704  }
705  break;
706  case 3:
707  if (bitShift < 32)
708  {
709  segmentRegister = &LCD->SEGD3L;
710  }
711  else
712  {
713  segmentRegister = &LCD->SEGD3H;
714  bitShift -= 32;
715  }
716  break;
717  default:
718  segmentRegister = (uint32_t *)0x00000000;
719  EFM_ASSERT(0);
720  break;
721  }
722 #endif
723 
724  /* Configure new bias setting */
725  *segmentRegister = (*segmentRegister & ~(0xF << bitShift)) | (biasLevel << bitShift);
726 }
727 #endif
728 
729 
730 #if defined(LCD_CTRL_DSC)
731 /***************************************************************************/
750 void LCD_BiasComSet(int comLine, int biasLevel)
751 {
752  int bitShift;
753  EFM_ASSERT(comLine < 8);
754 
755  bitShift = comLine * 4;
756  LCD->SEGD4L = (LCD->SEGD4L & ~(0xF << bitShift)) | (biasLevel << bitShift);
757 }
758 #endif
759 
763 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */
LCD_ConConf_TypeDef contrast
Definition: em_lcd.h:261
#define _LCD_BACTRL_AREGASC_SHIFT
Definition: efm32gg_lcd.h:227
#define _LCD_BACTRL_AREGBSC_MASK
Definition: efm32gg_lcd.h:238
Emlib peripheral API "assert" implementation.
#define LCD
void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost)
Configure voltage booster.
Definition: em_lcd.c:605
#define _LCD_DISPCTRL_MUXE_MASK
Definition: efm32gg_lcd.h:193
LCD_Wave_TypeDef wave
Definition: em_lcd.h:257
RAM and peripheral bit-field set and clear API.
void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)
Updates the 0-31 lowest segments on a given COM-line in one operation, according to bit mask...
Definition: em_lcd.c:414
#define LCD_BACTRL_ALOC_SEG0TO7
Definition: efm32gg_lcd.h:284
void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segment, bool enable)
Enables update of this range of LCD segment lines.
Definition: em_lcd.c:229
void LCD_BiasComSet(int com, int biasLevel)
Configure bias level for a specific segment line.
Definition: em_lcd.c:750
#define _LCD_BACTRL_ALOGSEL_MASK
Definition: efm32gg_lcd.h:249
LCD_AnimShift_TypeDef BShift
Definition: em_lcd.h:227
#define _LCD_DISPCTRL_CONLEV_MASK
Definition: efm32gg_lcd.h:146
LCD_Bias_TypeDef bias
Definition: em_lcd.h:255
LCD_VLCDSel_TypeDef vlcd
Definition: em_lcd.h:259
#define _LCD_BACTRL_FCTOP_MASK
Definition: efm32gg_lcd.h:274
void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit)
Initialize LCD Frame Counter.
Definition: em_lcd.c:149
void LCD_SegmentSet(int com, int bit, bool enable)
Turn on or clear a segment.
Definition: em_lcd.c:260
#define _LCD_BACTRL_AREGBSC_SHIFT
Definition: efm32gg_lcd.h:237
void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd)
Select source for VLCD.
Definition: em_lcd.c:107
LCD_VBoostLevel_TypeDef
Definition: em_lcd.h:122
__STATIC_INLINE void LCD_FrameCountEnable(bool enable)
Enables or disables LCD Frame Control.
Definition: em_lcd.h:388
#define _LCD_BACTRL_FCPRESC_MASK
Definition: efm32gg_lcd.h:262
void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud)
Configure Update Control.
Definition: em_lcd.c:136
LCD_FCPreScale_TypeDef prescale
Definition: em_lcd.h:244
#define _LCD_DISPCTRL_CONCONF_MASK
Definition: efm32gg_lcd.h:155
#define _LCD_BACTRL_AREGASC_MASK
Definition: efm32gg_lcd.h:228
void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)
Updated the high (32-39) segments on a given COM-line in one operation.
Definition: em_lcd.c:505
#define _LCD_DISPCTRL_VLCDSEL_MASK
Definition: efm32gg_lcd.h:164
#define _LCD_DISPCTRL_CONLEV_SHIFT
Definition: efm32gg_lcd.h:145
Liquid Crystal Display (LCD) peripheral API.
#define LCD_DISPCTRL_VLCDSEL_VEXTBOOST
Definition: efm32gg_lcd.h:170
#define LCD_DISPCTRL_VLCDSEL_VDD
Definition: efm32gg_lcd.h:169
#define _LCD_DISPCTRL_WAVE_MASK
Definition: efm32gg_lcd.h:138
LCD_AnimShift_TypeDef AShift
Definition: em_lcd.h:223
void LCD_ContrastSet(int level)
Configure contrast level on LCD panel.
Definition: em_lcd.c:587
LCD_AnimLogic_TypeDef animLogic
Definition: em_lcd.h:229
void LCD_BiasSegmentSet(int segment, int biasLevel)
Configure bias level for a specific segment line for Direct Segment Control.
Definition: em_lcd.c:632
LCD_Mux_TypeDef mux
Definition: em_lcd.h:253
#define _LCD_CTRL_UDCTRL_MASK
Definition: efm32gg_lcd.h:94
#define _LCD_DISPCTRL_VBLEV_MASK
Definition: efm32gg_lcd.h:172
#define _LCD_BACTRL_ALOC_MASK
Definition: efm32gg_lcd.h:279
#define LCD_BACTRL_ALOC_SEG8TO15
Definition: efm32gg_lcd.h:285
LCD_UpdateCtrl_TypeDef
Definition: em_lcd.h:180
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:146
#define _LCD_DISPCTRL_MUX_MASK
Definition: efm32gg_lcd.h:113
#define _LCD_BACTRL_FCTOP_SHIFT
Definition: efm32gg_lcd.h:273
LCD_VLCDSel_TypeDef
Definition: em_lcd.h:104
void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)
Configures LCD controller Animation feature.
Definition: em_lcd.c:178
__STATIC_INLINE void LCD_Enable(bool enable)
Enable or disable LCD controller.
Definition: em_lcd.h:308
LCD_SegmentRange_TypeDef
Definition: em_lcd.h:148
void LCD_Init(const LCD_Init_TypeDef *lcdInit)
Initalize Liquid Crystal Display (LCD) controller.
Definition: em_lcd.c:62
__STATIC_INLINE void LCD_AnimEnable(bool enable)
Enables or disables LCD Animation feature.
Definition: em_lcd.h:328
#define _LCD_DISPCTRL_BIAS_MASK
Definition: efm32gg_lcd.h:125