]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio/Source/SilLabs_Code/emlib/em_lcd.c
Add EFM32 Giant Gecko Starter Kit demo - still a work in progress as the low power...
[freertos] / FreeRTOS / Demo / CORTEX_EFM32_Gecko_Starter_Kit_Simplicity_Studio / Source / SilLabs_Code / emlib / em_lcd.c
1 /***************************************************************************//**\r
2  * @file em_lcd.c\r
3  * @brief Liquid Crystal Display (LCD) Peripheral API\r
4  * @version 4.0.0\r
5  *******************************************************************************\r
6  * @section License\r
7  * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>\r
8  *******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no\r
21  * obligation to support this Software. Silicon Labs is providing the\r
22  * Software "AS IS", with no express or implied warranties of any kind,\r
23  * including, but not limited to, any implied warranties of merchantability\r
24  * or fitness for any particular purpose or warranties against infringement\r
25  * of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Labs will not be liable for any consequential, incidental, or\r
28  * special damages, or any other relief, or for any claim by any third party,\r
29  * arising from your use of this Software.\r
30  *\r
31  ******************************************************************************/\r
32 \r
33 \r
34 #include "em_lcd.h"\r
35 #if defined(LCD_COUNT) && (LCD_COUNT > 0)\r
36 #include "em_assert.h"\r
37 #include "em_bitband.h"\r
38 \r
39 /***************************************************************************//**\r
40  * @addtogroup EM_Library\r
41  * @{\r
42  ******************************************************************************/\r
43 \r
44 /***************************************************************************//**\r
45  * @addtogroup LCD\r
46  * @brief Liquid Crystal Display (LCD) Peripheral API\r
47  * @{\r
48  ******************************************************************************/\r
49 \r
50 /***************************************************************************//**\r
51  * @brief\r
52  *   Initalize Liquid Crystal Display (LCD) controller\r
53  *\r
54  * @details\r
55  *   This function call will only configure the LCD controller. You must enable\r
56  *   it afterwards, potentially configuring Frame Control and interrupts first\r
57  *   according to requirements.\r
58  *\r
59  * @param[in] lcdInit\r
60  *   Pointer to initialization structure which configures LCD controller.\r
61  *\r
62  ******************************************************************************/\r
63 void LCD_Init(const LCD_Init_TypeDef *lcdInit)\r
64 {\r
65   uint32_t dispCtrl = LCD->DISPCTRL;\r
66 \r
67   EFM_ASSERT(lcdInit != (void *) 0);\r
68 \r
69   /* Disable controller before reconfiguration */\r
70   LCD_Enable(false);\r
71 \r
72   /* Make sure we don't touch other bit fields (i.e. voltage boost) */\r
73   dispCtrl &= ~(\r
74 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
75     _LCD_DISPCTRL_MUXE_MASK |\r
76 #endif\r
77     _LCD_DISPCTRL_MUX_MASK |\r
78     _LCD_DISPCTRL_BIAS_MASK |\r
79     _LCD_DISPCTRL_WAVE_MASK |\r
80     _LCD_DISPCTRL_VLCDSEL_MASK |\r
81     _LCD_DISPCTRL_CONCONF_MASK);\r
82 \r
83   /* Configure controller according to initialization structure */\r
84   dispCtrl |= lcdInit->mux; /* also configures MUXE */\r
85   dispCtrl |= lcdInit->bias;\r
86   dispCtrl |= lcdInit->wave;\r
87   dispCtrl |= lcdInit->vlcd;\r
88   dispCtrl |= lcdInit->contrast;\r
89 \r
90   /* Update display controller */\r
91   LCD->DISPCTRL = dispCtrl;\r
92 \r
93   /* Enable controller if wanted */\r
94   if (lcdInit->enable)\r
95   {\r
96     LCD_Enable(true);\r
97   }\r
98 }\r
99 \r
100 \r
101 /***************************************************************************//**\r
102  * @brief\r
103  *   Select source for VLCD\r
104  *\r
105  * @param[in] vlcd\r
106  *   Select source for VLD voltage\r
107  ******************************************************************************/\r
108 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd)\r
109 {\r
110   uint32_t dispctrl = LCD->DISPCTRL;\r
111 \r
112   /* Select VEXT or VDD */\r
113   dispctrl &= ~(_LCD_DISPCTRL_VLCDSEL_MASK);\r
114   switch (vlcd)\r
115   {\r
116   case lcdVLCDSelVExtBoost:\r
117     dispctrl |= LCD_DISPCTRL_VLCDSEL_VEXTBOOST;\r
118     break;\r
119   case lcdVLCDSelVDD:\r
120     dispctrl |= LCD_DISPCTRL_VLCDSEL_VDD;\r
121     break;\r
122   default:\r
123     break;\r
124   }\r
125 \r
126   LCD->DISPCTRL = dispctrl;\r
127 }\r
128 \r
129 \r
130 /***************************************************************************//**\r
131  * @brief\r
132  *   Configure Update Control\r
133  *\r
134  * @param[in] ud\r
135  *   Configures LCD update method\r
136  ******************************************************************************/\r
137 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud)\r
138 {\r
139   LCD->CTRL = (LCD->CTRL & ~_LCD_CTRL_UDCTRL_MASK) | ud;\r
140 }\r
141 \r
142 \r
143 /***************************************************************************//**\r
144  * @brief\r
145  *   Initialize LCD Frame Counter\r
146  *\r
147  * @param[in] fcInit\r
148  *   Pointer to Frame Counter initialization structure\r
149  ******************************************************************************/\r
150 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit)\r
151 {\r
152   uint32_t bactrl = LCD->BACTRL;\r
153 \r
154   EFM_ASSERT(fcInit != (void *) 0);\r
155 \r
156   /* Verify FC Top Counter to be within limits */\r
157   EFM_ASSERT(fcInit->top < 64);\r
158 \r
159   /* Reconfigure frame count configuration */\r
160   bactrl &= ~(_LCD_BACTRL_FCTOP_MASK |\r
161               _LCD_BACTRL_FCPRESC_MASK);\r
162   bactrl |= (fcInit->top << _LCD_BACTRL_FCTOP_SHIFT);\r
163   bactrl |= fcInit->prescale;\r
164 \r
165   /* Set Blink and Animation Control Register */\r
166   LCD->BACTRL = bactrl;\r
167 \r
168   LCD_FrameCountEnable(fcInit->enable);\r
169 }\r
170 \r
171 \r
172 /***************************************************************************//**\r
173  * @brief\r
174  *   Configures LCD controller Animation feature\r
175  *\r
176  * @param[in] animInit\r
177  *   Pointer to LCD Animation initialization structure\r
178  ******************************************************************************/\r
179 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit)\r
180 {\r
181   uint32_t bactrl = LCD->BACTRL;\r
182 \r
183   EFM_ASSERT(animInit != (void *) 0);\r
184 \r
185   /* Set Animation Register Values */\r
186   LCD->AREGA = animInit->AReg;\r
187   LCD->AREGB = animInit->BReg;\r
188 \r
189   /* Configure Animation Shift and Logic */\r
190   bactrl &= ~(_LCD_BACTRL_AREGASC_MASK |\r
191               _LCD_BACTRL_AREGBSC_MASK |\r
192               _LCD_BACTRL_ALOGSEL_MASK);\r
193 \r
194   bactrl |= (animInit->AShift << _LCD_BACTRL_AREGASC_SHIFT);\r
195   bactrl |= (animInit->BShift << _LCD_BACTRL_AREGBSC_SHIFT);\r
196   bactrl |= animInit->animLogic;\r
197 \r
198 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
199   bactrl &= ~(_LCD_BACTRL_ALOC_MASK);\r
200 \r
201   if(animInit->startSeg == 0)\r
202   {\r
203     bactrl |= LCD_BACTRL_ALOC_SEG0TO7;\r
204   }\r
205   else if(animInit->startSeg == 8)\r
206   {\r
207     bactrl |= LCD_BACTRL_ALOC_SEG8TO15;\r
208   }\r
209 #endif\r
210 \r
211   /* Reconfigure */\r
212   LCD->BACTRL = bactrl;\r
213 \r
214   /* Enable */\r
215   LCD_AnimEnable(animInit->enable);\r
216 }\r
217 \r
218 \r
219 /***************************************************************************//**\r
220  * @brief\r
221  *   Enables update of this range of LCD segment lines\r
222  *\r
223  * @param[in] segmentRange\r
224  *   Range of 4 LCD segments lines to enable or disable, for all enabled COM\r
225  *   lines\r
226  *\r
227  * @param[in] enable\r
228  *   Bool true to enable segment updates, false to disable updates\r
229  ******************************************************************************/\r
230 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segmentRange, bool enable)\r
231 {\r
232   if (enable)\r
233   {\r
234     LCD->SEGEN |= segmentRange;\r
235   }\r
236   else\r
237   {\r
238     LCD->SEGEN &= ~((uint32_t)segmentRange);\r
239   }\r
240 }\r
241 \r
242 \r
243 /***************************************************************************//**\r
244  * @brief\r
245  *   Turn on or clear a segment\r
246  *\r
247  * @note\r
248  *    On Gecko Family, max configuration is (COM-lines x Segment-Lines) 4x40\r
249  *    On Tiny Family, max configuration is 8x20 or 4x24\r
250  *    On Giant Family, max configuration is 8x36 or 4x40\r
251  *\r
252  * @param[in] com\r
253  *   COM line to change\r
254  *\r
255  * @param[in] bit\r
256  *   Bit index of which field to change\r
257  *\r
258  * @param[in] enable\r
259  *   When true will set segment, when false will clear segment\r
260  ******************************************************************************/\r
261 void LCD_SegmentSet(int com, int bit, bool enable)\r
262 {\r
263 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
264   /* Tiny and Giant Family supports up to 8 COM lines */\r
265   EFM_ASSERT(com < 8);\r
266 #else\r
267   /* Gecko Family supports up to 4 COM lines */\r
268   EFM_ASSERT(com < 4);\r
269 #endif\r
270 \r
271 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
272   EFM_ASSERT(bit < 40);\r
273 #else\r
274   /* Tiny Gecko Family supports only "low" segment registers */\r
275   EFM_ASSERT(bit < 32);\r
276 #endif\r
277 \r
278   /* Use bitband access for atomic bit set/clear of segment */\r
279   switch (com)\r
280   {\r
281   case 0:\r
282     if (bit < 32)\r
283     {\r
284       BITBAND_Peripheral(&(LCD->SEGD0L), bit, (unsigned int)enable);\r
285     }\r
286 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
287     else\r
288     {\r
289       bit -= 32;\r
290       BITBAND_Peripheral(&(LCD->SEGD0H), bit, (unsigned int)enable);\r
291     }\r
292 #endif\r
293     break;\r
294   case 1:\r
295     if (bit < 32)\r
296     {\r
297       BITBAND_Peripheral(&(LCD->SEGD1L), bit, (unsigned int)enable);\r
298     }\r
299 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
300     else\r
301     {\r
302       bit -= 32;\r
303       BITBAND_Peripheral(&(LCD->SEGD1H), bit, (unsigned int)enable);\r
304     }\r
305 #endif\r
306     break;\r
307   case 2:\r
308     if (bit < 32)\r
309     {\r
310       BITBAND_Peripheral(&(LCD->SEGD2L), bit, (unsigned int)enable);\r
311     }\r
312 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
313     else\r
314     {\r
315       bit -= 32;\r
316       BITBAND_Peripheral(&(LCD->SEGD2H), bit, (unsigned int)enable);\r
317     }\r
318 #endif\r
319     break;\r
320   case 3:\r
321     if (bit < 32)\r
322     {\r
323       BITBAND_Peripheral(&(LCD->SEGD3L), bit, (unsigned int)enable);\r
324     }\r
325 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
326     else\r
327     {\r
328       bit -= 32;\r
329       BITBAND_Peripheral(&(LCD->SEGD3H), bit, (unsigned int)enable);\r
330     }\r
331 #endif\r
332     break;\r
333   case 4:\r
334 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
335     if (bit < 32)\r
336     {\r
337       BITBAND_Peripheral(&(LCD->SEGD4L), bit, (unsigned int)enable);\r
338     }\r
339 #endif\r
340 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
341     else\r
342     {\r
343       bit -= 32;\r
344       BITBAND_Peripheral(&(LCD->SEGD4H), bit, (unsigned int)enable);\r
345     }\r
346 #endif\r
347     break;\r
348   case 5:\r
349 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
350     if (bit < 32)\r
351     {\r
352       BITBAND_Peripheral(&(LCD->SEGD5L), bit, (unsigned int)enable);\r
353     }\r
354 #endif\r
355 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
356     else\r
357     {\r
358       bit -= 32;\r
359       BITBAND_Peripheral(&(LCD->SEGD5H), bit, (unsigned int)enable);\r
360     }\r
361 #endif\r
362     break;\r
363   case 6:\r
364 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
365     if (bit < 32)\r
366     {\r
367       BITBAND_Peripheral(&(LCD->SEGD6L), bit, (unsigned int)enable);\r
368     }\r
369 #endif\r
370 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
371     else\r
372     {\r
373       bit -= 32;\r
374       BITBAND_Peripheral(&(LCD->SEGD6H), bit, (unsigned int)enable);\r
375     }\r
376 #endif\r
377     break;\r
378   case 7:\r
379 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
380     if (bit < 32)\r
381     {\r
382       BITBAND_Peripheral(&(LCD->SEGD7L), bit, (unsigned int)enable);\r
383     }\r
384 #endif\r
385 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
386     else\r
387     {\r
388       bit -= 32;\r
389       BITBAND_Peripheral(&(LCD->SEGD7H), bit, (unsigned int)enable);\r
390     }\r
391 #endif\r
392     break;\r
393 \r
394   default:\r
395     EFM_ASSERT(0);\r
396     break;\r
397   }\r
398 }\r
399 \r
400 \r
401 /***************************************************************************//**\r
402  * @brief\r
403  *   Updates the 0-31 lowest segments on a given COM-line in one operation,\r
404  *   according to bit mask\r
405  *\r
406  * @param[in] com\r
407  *   Which COM line to update\r
408  *\r
409  * @param[in] mask\r
410  *   Bit mask for segments 0-31\r
411  *\r
412  * @param[in] bits\r
413  *   Bit pattern for segments 0-31\r
414  ******************************************************************************/\r
415 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits)\r
416 {\r
417   uint32_t segData;\r
418 \r
419   /* Maximum number of com lines */\r
420 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
421   EFM_ASSERT(com < 8);\r
422 #else\r
423   /* Gecko Family supports up to 4 COM lines */\r
424   EFM_ASSERT(com < 4);\r
425 #endif\r
426 \r
427   switch (com)\r
428   {\r
429   case 0:\r
430     segData     = LCD->SEGD0L;\r
431     segData    &= ~(mask);\r
432     segData    |= (mask & bits);\r
433     LCD->SEGD0L = segData;\r
434     break;\r
435   case 1:\r
436     segData     = LCD->SEGD1L;\r
437     segData    &= ~(mask);\r
438     segData    |= (mask & bits);\r
439     LCD->SEGD1L = segData;\r
440     break;\r
441   case 2:\r
442     segData     = LCD->SEGD2L;\r
443     segData    &= ~(mask);\r
444     segData    |= (mask & bits);\r
445     LCD->SEGD2L = segData;\r
446     break;\r
447   case 3:\r
448     segData     = LCD->SEGD3L;\r
449     segData    &= ~(mask);\r
450     segData    |= (mask & bits);\r
451     LCD->SEGD3L = segData;\r
452     break;\r
453 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
454   case 4:\r
455     segData     = LCD->SEGD4L;\r
456     segData    &= ~(mask);\r
457     segData    |= (mask & bits);\r
458     LCD->SEGD4L = segData;\r
459     break;\r
460 #endif\r
461 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) \r
462   case 5:\r
463     segData     = LCD->SEGD5L;\r
464     segData    &= ~(mask);\r
465     segData    |= (mask & bits);\r
466     LCD->SEGD5L = segData;\r
467     break;\r
468 #endif\r
469 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
470   case 6:\r
471     segData     = LCD->SEGD6L;\r
472     segData    &= ~(mask);\r
473     segData    |= (mask & bits);\r
474     LCD->SEGD6L = segData;\r
475     break;\r
476 #endif\r
477 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
478   case 7:\r
479     segData     = LCD->SEGD7L;\r
480     segData    &= ~(mask);\r
481     segData    |= (mask & bits);\r
482     LCD->SEGD7L = segData;\r
483     break;\r
484 #endif\r
485   default:\r
486     EFM_ASSERT(0);\r
487     break;\r
488   }\r
489 }\r
490 \r
491 \r
492 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
493 /***************************************************************************//**\r
494  * @brief\r
495  *   Updated the high (32-39) segments on a given COM-line in one operation\r
496  *\r
497  * @param[in] com\r
498  *   Which COM line to update\r
499  *\r
500  * @param[in] mask\r
501  *   Bit mask for segments 32-39\r
502  *\r
503  * @param[in] bits\r
504  *   Bit pattern for segments 32-39\r
505  ******************************************************************************/\r
506 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits)\r
507 {\r
508   uint32_t segData;\r
509 \r
510 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
511   EFM_ASSERT(com < 8);\r
512 #endif\r
513 #if defined(_EFM32_GECKO_FAMILY)\r
514   EFM_ASSERT(com < 4);\r
515 #endif\r
516 \r
517   /* Maximum number of com lines */\r
518   switch (com)\r
519   {\r
520   case 0:\r
521     segData     = LCD->SEGD0H;\r
522     segData    &= ~(mask);\r
523     segData    |= (mask & bits);\r
524     LCD->SEGD0H = segData;\r
525     break;\r
526   case 1:\r
527     segData     = LCD->SEGD1H;\r
528     segData    &= ~(mask);\r
529     segData    |= (mask & bits);\r
530     LCD->SEGD1H = segData;\r
531     break;\r
532   case 2:\r
533     segData     = LCD->SEGD2H;\r
534     segData    &= ~(mask);\r
535     segData    |= (mask & bits);\r
536     LCD->SEGD2H = segData;\r
537     break;\r
538   case 3:\r
539     segData     = LCD->SEGD3H;\r
540     segData    &= ~(mask);\r
541     segData    |= (mask & bits);\r
542     LCD->SEGD3H = segData;\r
543     break;\r
544 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
545   case 4:\r
546     segData     = LCD->SEGD4H;\r
547     segData    &= ~(mask);\r
548     segData    |= (mask & bits);\r
549     LCD->SEGD4H = segData;\r
550     break;\r
551 #endif\r
552 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
553   case 5:\r
554     segData     = LCD->SEGD5H;\r
555     segData    &= ~(mask);\r
556     segData    |= (mask & bits);\r
557     LCD->SEGD5H = segData;\r
558     break;\r
559 #endif\r
560 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
561   case 6:\r
562     segData     = LCD->SEGD6H;\r
563     segData    &= ~(mask);\r
564     segData    |= (mask & bits);\r
565     LCD->SEGD6H = segData;\r
566     break;\r
567 #endif\r
568 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
569   case 7:\r
570     segData     = LCD->SEGD7H;\r
571     segData    &= ~(mask);\r
572     segData    |= (mask & bits);\r
573     LCD->SEGD7H = segData;\r
574     break;\r
575 #endif\r
576   default:\r
577     break;\r
578   }\r
579 }\r
580 #endif\r
581 \r
582 /***************************************************************************//**\r
583  * @brief\r
584  *   Configure contrast level on LCD panel\r
585  *\r
586  * @param[in] level\r
587  *   Contrast level in the range 0-31\r
588  ******************************************************************************/\r
589 void LCD_ContrastSet(int level)\r
590 {\r
591   EFM_ASSERT(level < 32);\r
592 \r
593   LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_CONLEV_MASK)\r
594                   | (level << _LCD_DISPCTRL_CONLEV_SHIFT);\r
595 }\r
596 \r
597 \r
598 /***************************************************************************//**\r
599  * @brief\r
600  *   Configure voltage booster\r
601  *\r
602  * The resulting voltage level is described in each part number's data sheet\r
603  *\r
604  * @param[in] vboost\r
605  *   Voltage boost level\r
606  ******************************************************************************/\r
607 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost)\r
608 {\r
609   /* Reconfigure Voltage Boost */\r
610   LCD->DISPCTRL = (LCD->DISPCTRL & ~_LCD_DISPCTRL_VBLEV_MASK) | vboost;\r
611 }\r
612 \r
613 \r
614 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
615 /***************************************************************************//**\r
616  * @brief\r
617  *   Configure bias level for a specific segment line for Direct Segment Control\r
618  *\r
619  * @note\r
620  *   When DSC is active, each configuration takes up 4 bits in the Segment\r
621  *   Registers (SEGD0L/SEGD1H) which defines bias level.\r
622  *   For optimal use of this feature, the entire SEGD-registers should be set\r
623  *   at once in a optimized routine, so this function is mainly here to\r
624  *   demonstrate how to correctly configure the bias levels, and should be used\r
625  *   with care.\r
626  *\r
627  * @param[in] segmentLine\r
628  *   Segment line number\r
629  *\r
630  * @param[in] biasLevel\r
631  *   Bias configuration level, 0-4. This value must be within the constraint\r
632  *   defined by the LCD_DISPCTRL bias setting, see Reference Manual/Datasheet\r
633  ******************************************************************************/\r
634 void LCD_BiasSegmentSet(int segmentLine, int biasLevel)\r
635 {\r
636   int               biasRegister;\r
637   int               bitShift;\r
638   volatile uint32_t *segmentRegister;\r
639 \r
640 #if defined(_EFM32_TINY_FAMILY)\r
641   EFM_ASSERT(segmentLine < 20);\r
642 #endif\r
643 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)\r
644   EFM_ASSERT(segmentLine < 40);\r
645 #endif\r
646 #if defined(_EFM32_TINY_FAMILY)\r
647   /* Bias config for 8 segment lines per SEGDnL register */\r
648   biasRegister = segmentLine / 8;\r
649   bitShift     = (segmentLine % 8) * 4;\r
650 \r
651   switch (biasRegister)\r
652   {\r
653   case 0:\r
654     segmentRegister = &LCD->SEGD0L;\r
655     break;\r
656   case 1:\r
657     segmentRegister = &LCD->SEGD1L;\r
658     break;\r
659   case 2:\r
660     segmentRegister = &LCD->SEGD2L;\r
661     break;\r
662   case 3:\r
663     segmentRegister = &LCD->SEGD3L;\r
664     break;\r
665   default:\r
666     segmentRegister = (uint32_t *)0x00000000;\r
667     EFM_ASSERT(0);\r
668     break;\r
669   }\r
670 #endif\r
671 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY) \r
672   /* Bias config for 10 segment lines per SEGDn L+H registers */\r
673   biasRegister = segmentLine / 10;\r
674   bitShift     = (segmentLine % 10) * 4;\r
675 \r
676   switch (biasRegister)\r
677   {\r
678   case 0:\r
679     if (bitShift < 32)\r
680     {\r
681       segmentRegister = &LCD->SEGD0L;\r
682     }\r
683     else\r
684     {\r
685       segmentRegister = &LCD->SEGD0H;\r
686       bitShift       -= 32;\r
687     }\r
688     break;\r
689   case 1:\r
690     if (bitShift < 32)\r
691     {\r
692       segmentRegister = &LCD->SEGD1L;\r
693     }\r
694     else\r
695     {\r
696       segmentRegister = &LCD->SEGD1H;\r
697       bitShift       -= 32;\r
698     }\r
699     break;\r
700   case 2:\r
701     if (bitShift < 32)\r
702     {\r
703       segmentRegister = &LCD->SEGD2L;\r
704     }\r
705     else\r
706     {\r
707       segmentRegister = &LCD->SEGD1H;\r
708       bitShift       -= 32;\r
709     }\r
710     break;\r
711   case 3:\r
712     if (bitShift < 32)\r
713     {\r
714       segmentRegister = &LCD->SEGD3L;\r
715     }\r
716     else\r
717     {\r
718       segmentRegister = &LCD->SEGD3H;\r
719       bitShift       -= 32;\r
720     }\r
721     break;\r
722   default:\r
723     segmentRegister = (uint32_t *)0x00000000;\r
724     EFM_ASSERT(0);\r
725     break;\r
726   }\r
727 #endif\r
728 \r
729   /* Configure new bias setting */\r
730   *segmentRegister = (*segmentRegister & ~(0xF << bitShift)) | (biasLevel << bitShift);\r
731 }\r
732 \r
733 \r
734 /***************************************************************************//**\r
735  * @brief\r
736  *   Configure bias level for a specific segment line\r
737  *\r
738  * @note\r
739  *   When DSC is active, each configuration takes up 4 bits in the Segment\r
740  *   Registers (SEGD4L/SEGD4H) which defines bias level.\r
741  *   For optimal use of this feature, the entire SEGD-registers should be set\r
742  *   at once in a optimized routine, so this function is mainly here to\r
743  *   demonstrate how to correctly configure the bias levels, and should be used\r
744  *   with care.\r
745  *\r
746  * @param[in] comLine\r
747  *   COM line number, 0-7\r
748  *\r
749  * @param[in] biasLevel\r
750  *   Bias configuration level, 0-4. This value must be within the constraint\r
751  *   defined by the LCD_DISPCTRL bias setting, see Reference Manual/Datasheet\r
752  ******************************************************************************/\r
753 void LCD_BiasComSet(int comLine, int biasLevel)\r
754 {\r
755   int bitShift;\r
756   EFM_ASSERT(comLine < 8);\r
757 \r
758   bitShift    = comLine * 4;\r
759   LCD->SEGD4L = (LCD->SEGD4L & ~(0xF << bitShift)) | (biasLevel << bitShift);\r
760 }\r
761 #endif\r
762 \r
763 /** @} (end addtogroup LCD) */\r
764 /** @} (end addtogroup EM_Library) */\r
765 \r
766 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */\r