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