EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
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 /***************************************************************************/
54 /***************************************************************************/
67 void LCD_Init(const LCD_Init_TypeDef *lcdInit)
68 {
69  uint32_t dispCtrl = LCD->DISPCTRL;
70 
71  EFM_ASSERT(lcdInit != (void *) 0);
72 
73  /* Disable controller before reconfiguration */
74  LCD_Enable(false);
75 
76  /* Make sure we don't touch other bit fields (i.e. voltage boost) */
77  dispCtrl &= ~(0
78 #if defined(LCD_DISPCTRL_MUXE)
79  | _LCD_DISPCTRL_MUXE_MASK
80 #endif
81  | _LCD_DISPCTRL_MUX_MASK
82  | _LCD_DISPCTRL_BIAS_MASK
83  | _LCD_DISPCTRL_WAVE_MASK
84  | _LCD_DISPCTRL_VLCDSEL_MASK
85  | _LCD_DISPCTRL_CONCONF_MASK);
86 
87  /* Configure controller according to initialization structure */
88  dispCtrl |= lcdInit->mux; /* also configures MUXE */
89  dispCtrl |= lcdInit->bias;
90  dispCtrl |= lcdInit->wave;
91  dispCtrl |= lcdInit->vlcd;
92  dispCtrl |= lcdInit->contrast;
93 
94  /* Update display controller */
95  LCD->DISPCTRL = dispCtrl;
96 
97  /* Enable controller if wanted */
98  if (lcdInit->enable)
99  {
100  LCD_Enable(true);
101  }
102 }
103 
104 
105 /***************************************************************************/
112 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd)
113 {
114  uint32_t dispctrl = LCD->DISPCTRL;
115 
116  /* Select VEXT or VDD */
117  dispctrl &= ~_LCD_DISPCTRL_VLCDSEL_MASK;
118  switch (vlcd)
119  {
120  case lcdVLCDSelVExtBoost:
121  dispctrl |= LCD_DISPCTRL_VLCDSEL_VEXTBOOST;
122  break;
123  case lcdVLCDSelVDD:
124  dispctrl |= LCD_DISPCTRL_VLCDSEL_VDD;
125  break;
126  default:
127  break;
128  }
129 
130  LCD->DISPCTRL = dispctrl;
131 }
132 
133 
134 /***************************************************************************/
141 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud)
142 {
143  LCD->CTRL = (LCD->CTRL & ~_LCD_CTRL_UDCTRL_MASK) | ud;
144 }
145 
146 
147 /***************************************************************************/
154 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit)
155 {
156  uint32_t bactrl = LCD->BACTRL;
157 
158  EFM_ASSERT(fcInit != (void *) 0);
159 
160  /* Verify FC Top Counter to be within limits */
161  EFM_ASSERT(fcInit->top < 64);
162 
163  /* Reconfigure frame count configuration */
164  bactrl &= ~(_LCD_BACTRL_FCTOP_MASK
165  | _LCD_BACTRL_FCPRESC_MASK);
166  bactrl |= (fcInit->top << _LCD_BACTRL_FCTOP_SHIFT);
167  bactrl |= fcInit->prescale;
168 
169  /* Set Blink and Animation Control Register */
170  LCD->BACTRL = bactrl;
171 
172  LCD_FrameCountEnable(fcInit->enable);
173 }
174 
175 
176 /***************************************************************************/
183 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)
184 {
185  uint32_t bactrl = LCD->BACTRL;
186 
187  EFM_ASSERT(animInit != (void *) 0);
188 
189  /* Set Animation Register Values */
190  LCD->AREGA = animInit->AReg;
191  LCD->AREGB = animInit->BReg;
192 
193  /* Configure Animation Shift and Logic */
194  bactrl &= ~(_LCD_BACTRL_AREGASC_MASK
195  | _LCD_BACTRL_AREGBSC_MASK
196  | _LCD_BACTRL_ALOGSEL_MASK);
197 
198  bactrl |= (animInit->AShift << _LCD_BACTRL_AREGASC_SHIFT);
199  bactrl |= (animInit->BShift << _LCD_BACTRL_AREGBSC_SHIFT);
200  bactrl |= animInit->animLogic;
201 
202 #if defined(LCD_BACTRL_ALOC)
203  bactrl &= ~(_LCD_BACTRL_ALOC_MASK);
204 
205  if(animInit->startSeg == 0)
206  {
207  bactrl |= LCD_BACTRL_ALOC_SEG0TO7;
208  }
209  else if(animInit->startSeg == 8)
210  {
211  bactrl |= LCD_BACTRL_ALOC_SEG8TO15;
212  }
213 #endif
214 
215  /* Reconfigure */
216  LCD->BACTRL = bactrl;
217 
218  /* Enable */
219  LCD_AnimEnable(animInit->enable);
220 }
221 
222 
223 /***************************************************************************/
234 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segmentRange, bool enable)
235 {
236  if (enable)
237  {
238  LCD->SEGEN |= segmentRange;
239  }
240  else
241  {
242  LCD->SEGEN &= ~((uint32_t)segmentRange);
243  }
244 }
245 
246 
247 /***************************************************************************/
265 void LCD_SegmentSet(int com, int bit, bool enable)
266 {
267 #if defined(_LCD_SEGD7L_MASK)
268  /* Tiny and Giant Family supports up to 8 COM lines */
269  EFM_ASSERT(com < 8);
270 #else
271  /* Gecko Family supports up to 4 COM lines */
272  EFM_ASSERT(com < 4);
273 #endif
274 
275 #if defined(_LCD_SEGD0H_MASK)
276  EFM_ASSERT(bit < 40);
277 #else
278  /* Tiny Gecko Family supports only "low" segment registers */
279  EFM_ASSERT(bit < 32);
280 #endif
281 
282  /* Use bitband access for atomic bit set/clear of segment */
283  switch (com)
284  {
285  case 0:
286  if (bit < 32)
287  {
288  BUS_RegBitWrite(&(LCD->SEGD0L), bit, enable);
289  }
290 #if defined(_LCD_SEGD0H_MASK)
291  else
292  {
293  bit -= 32;
294  BUS_RegBitWrite(&(LCD->SEGD0H), bit, enable);
295  }
296 #endif
297  break;
298  case 1:
299  if (bit < 32)
300  {
301  BUS_RegBitWrite(&(LCD->SEGD1L), bit, enable);
302  }
303 #if defined(_LCD_SEGD1H_MASK)
304  else
305  {
306  bit -= 32;
307  BUS_RegBitWrite(&(LCD->SEGD1H), bit, enable);
308  }
309 #endif
310  break;
311  case 2:
312  if (bit < 32)
313  {
314  BUS_RegBitWrite(&(LCD->SEGD2L), bit, enable);
315  }
316 #if defined(_LCD_SEGD2H_MASK)
317  else
318  {
319  bit -= 32;
320  BUS_RegBitWrite(&(LCD->SEGD2H), bit, enable);
321  }
322 #endif
323  break;
324  case 3:
325  if (bit < 32)
326  {
327  BUS_RegBitWrite(&(LCD->SEGD3L), bit, enable);
328  }
329 #if defined(_LCD_SEGD3H_MASK)
330  else
331  {
332  bit -= 32;
333  BUS_RegBitWrite(&(LCD->SEGD3H), bit, enable);
334  }
335 #endif
336  break;
337 #if defined(_LCD_SEGD4L_MASK)
338  case 4:
339  if (bit < 32)
340  {
341  BUS_RegBitWrite(&(LCD->SEGD4L), bit, enable);
342  }
343 #if defined(_LCD_SEGD4H_MASK)
344  else
345  {
346  bit -= 32;
347  BUS_RegBitWrite(&(LCD->SEGD4H), bit, enable);
348  }
349 #endif
350  break;
351 #endif
352 #if defined(_LCD_SEGD5L_MASK)
353  case 5:
354  if (bit < 32)
355  {
356  BUS_RegBitWrite(&(LCD->SEGD5L), bit, enable);
357  }
358 #if defined(_LCD_SEGD5H_MASK)
359  else
360  {
361  bit -= 32;
362  BUS_RegBitWrite(&(LCD->SEGD5H), bit, enable);
363  }
364 #endif
365  break;
366 #endif
367  case 6:
368 #if defined(_LCD_SEGD6L_MASK)
369  if (bit < 32)
370  {
371  BUS_RegBitWrite(&(LCD->SEGD6L), bit, enable);
372  }
373 #if defined(_LCD_SEGD6H_MASK)
374  else
375  {
376  bit -= 32;
377  BUS_RegBitWrite(&(LCD->SEGD6H), bit, enable);
378  }
379 #endif
380  break;
381 #endif
382 #if defined(_LCD_SEGD7L_MASK)
383  case 7:
384  if (bit < 32)
385  {
386  BUS_RegBitWrite(&(LCD->SEGD7L), bit, enable);
387  }
388 #if defined(_LCD_SEGD7H_MASK)
389  else
390  {
391  bit -= 32;
392  BUS_RegBitWrite(&(LCD->SEGD7H), bit, enable);
393  }
394 #endif
395  break;
396 #endif
397 
398  default:
399  EFM_ASSERT(0);
400  break;
401  }
402 }
403 
404 
405 /***************************************************************************/
419 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)
420 {
421  uint32_t segData;
422 
423  /* Maximum number of com lines */
424 #if defined(_LCD_SEGD7L_MASK)
425  EFM_ASSERT(com < 8);
426 #else
427  /* Gecko Family supports up to 4 COM lines */
428  EFM_ASSERT(com < 4);
429 #endif
430 
431  switch (com)
432  {
433  case 0:
434  segData = LCD->SEGD0L;
435  segData &= ~(mask);
436  segData |= (mask & bits);
437  LCD->SEGD0L = segData;
438  break;
439  case 1:
440  segData = LCD->SEGD1L;
441  segData &= ~(mask);
442  segData |= (mask & bits);
443  LCD->SEGD1L = segData;
444  break;
445  case 2:
446  segData = LCD->SEGD2L;
447  segData &= ~(mask);
448  segData |= (mask & bits);
449  LCD->SEGD2L = segData;
450  break;
451  case 3:
452  segData = LCD->SEGD3L;
453  segData &= ~(mask);
454  segData |= (mask & bits);
455  LCD->SEGD3L = segData;
456  break;
457 #if defined(_LCD_SEGD4L_MASK)
458  case 4:
459  segData = LCD->SEGD4L;
460  segData &= ~(mask);
461  segData |= (mask & bits);
462  LCD->SEGD4L = segData;
463  break;
464 #endif
465 #if defined(_LCD_SEGD5L_MASK)
466  case 5:
467  segData = LCD->SEGD5L;
468  segData &= ~(mask);
469  segData |= (mask & bits);
470  LCD->SEGD5L = segData;
471  break;
472 #endif
473 #if defined(_LCD_SEGD6L_MASK)
474  case 6:
475  segData = LCD->SEGD6L;
476  segData &= ~(mask);
477  segData |= (mask & bits);
478  LCD->SEGD6L = segData;
479  break;
480 #endif
481 #if defined(_LCD_SEGD7L_MASK)
482  case 7:
483  segData = LCD->SEGD7L;
484  segData &= ~(mask);
485  segData |= (mask & bits);
486  LCD->SEGD7L = segData;
487  break;
488 #endif
489  default:
490  EFM_ASSERT(0);
491  break;
492  }
493 }
494 
495 
496 #if defined(_LCD_SEGD0H_MASK)
497 /***************************************************************************/
510 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)
511 {
512  uint32_t segData;
513 
514 #if defined(_LCD_SEGD7H_MASK)
515  EFM_ASSERT(com < 8);
516 #else
517  EFM_ASSERT(com < 4);
518 #endif
519 
520  /* Maximum number of com lines */
521  switch (com)
522  {
523  case 0:
524  segData = LCD->SEGD0H;
525  segData &= ~(mask);
526  segData |= (mask & bits);
527  LCD->SEGD0H = segData;
528  break;
529  case 1:
530  segData = LCD->SEGD1H;
531  segData &= ~(mask);
532  segData |= (mask & bits);
533  LCD->SEGD1H = segData;
534  break;
535  case 2:
536  segData = LCD->SEGD2H;
537  segData &= ~(mask);
538  segData |= (mask & bits);
539  LCD->SEGD2H = segData;
540  break;
541  case 3:
542  segData = LCD->SEGD3H;
543  segData &= ~(mask);
544  segData |= (mask & bits);
545  LCD->SEGD3H = segData;
546  break;
547 #if defined(_LCD_SEGD4H_MASK)
548  case 4:
549  segData = LCD->SEGD4H;
550  segData &= ~(mask);
551  segData |= (mask & bits);
552  LCD->SEGD4H = segData;
553  break;
554 #endif
555 #if defined(_LCD_SEGD5H_MASK)
556  case 5:
557  segData = LCD->SEGD5H;
558  segData &= ~(mask);
559  segData |= (mask & bits);
560  LCD->SEGD5H = segData;
561  break;
562 #endif
563 #if defined(_LCD_SEGD6H_MASK)
564  case 6:
565  segData = LCD->SEGD6H;
566  segData &= ~(mask);
567  segData |= (mask & bits);
568  LCD->SEGD6H = segData;
569  break;
570 #endif
571 #if defined(_LCD_SEGD7H_MASK)
572  case 7:
573  segData = LCD->SEGD7H;
574  segData &= ~(mask);
575  segData |= (mask & bits);
576  LCD->SEGD7H = segData;
577  break;
578 #endif
579  default:
580  break;
581  }
582 }
583 #endif
584 
585 /***************************************************************************/
592 void LCD_ContrastSet(int level)
593 {
594  EFM_ASSERT(level < 32);
595 
596  LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_CONLEV_MASK)
597  | (level << _LCD_DISPCTRL_CONLEV_SHIFT);
598 }
599 
600 
601 /***************************************************************************/
610 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost)
611 {
612  /* Reconfigure Voltage Boost */
613  LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_VBLEV_MASK) | vboost;
614 }
615 
616 
617 #if defined(LCD_CTRL_DSC)
618 /***************************************************************************/
637 void LCD_BiasSegmentSet(int segmentLine, int biasLevel)
638 {
639  int biasRegister;
640  int bitShift;
641  volatile uint32_t *segmentRegister;
642 
643 #if !defined(_LCD_SEGD0H_MASK)
644  EFM_ASSERT(segmentLine < 20);
645 
646  /* Bias config for 8 segment lines per SEGDnL register */
647  biasRegister = segmentLine / 8;
648  bitShift = (segmentLine % 8) * 4;
649 
650  switch (biasRegister)
651  {
652  case 0:
653  segmentRegister = &LCD->SEGD0L;
654  break;
655  case 1:
656  segmentRegister = &LCD->SEGD1L;
657  break;
658  case 2:
659  segmentRegister = &LCD->SEGD2L;
660  break;
661  case 3:
662  segmentRegister = &LCD->SEGD3L;
663  break;
664  default:
665  segmentRegister = (uint32_t *)0x00000000;
666  EFM_ASSERT(0);
667  break;
668  }
669 #else
670  EFM_ASSERT(segmentLine < 40);
671 
672  /* Bias config for 10 segment lines per SEGDn L+H registers */
673  biasRegister = segmentLine / 10;
674  bitShift = (segmentLine % 10) * 4;
675 
676  switch (biasRegister)
677  {
678  case 0:
679  if (bitShift < 32)
680  {
681  segmentRegister = &LCD->SEGD0L;
682  }
683  else
684  {
685  segmentRegister = &LCD->SEGD0H;
686  bitShift -= 32;
687  }
688  break;
689  case 1:
690  if (bitShift < 32)
691  {
692  segmentRegister = &LCD->SEGD1L;
693  }
694  else
695  {
696  segmentRegister = &LCD->SEGD1H;
697  bitShift -= 32;
698  }
699  break;
700  case 2:
701  if (bitShift < 32)
702  {
703  segmentRegister = &LCD->SEGD2L;
704  }
705  else
706  {
707  segmentRegister = &LCD->SEGD1H;
708  bitShift -= 32;
709  }
710  break;
711  case 3:
712  if (bitShift < 32)
713  {
714  segmentRegister = &LCD->SEGD3L;
715  }
716  else
717  {
718  segmentRegister = &LCD->SEGD3H;
719  bitShift -= 32;
720  }
721  break;
722  default:
723  segmentRegister = (uint32_t *)0x00000000;
724  EFM_ASSERT(0);
725  break;
726  }
727 #endif
728 
729  /* Configure new bias setting */
730  *segmentRegister = (*segmentRegister & ~(0xF << bitShift)) | (biasLevel << bitShift);
731 }
732 #endif
733 
734 
735 #if defined(LCD_CTRL_DSC)
736 /***************************************************************************/
755 void LCD_BiasComSet(int comLine, int biasLevel)
756 {
757  int bitShift;
758  EFM_ASSERT(comLine < 8);
759 
760  bitShift = comLine * 4;
761  LCD->SEGD4L = (LCD->SEGD4L & ~(0xF << bitShift)) | (biasLevel << bitShift);
762 }
763 #endif
764 
768 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */
Emlib peripheral API "assert" implementation.
RAM and peripheral bit-field set and clear API.
Liquid Crystal Display (LCD) peripheral API.
__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:148