1 /***************************************************************************//**
\r
3 * @brief Liquid Crystal Display (LCD) peripheral API
\r
5 *******************************************************************************
\r
7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
\r
8 *******************************************************************************
\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
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
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
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
31 ******************************************************************************/
\r
34 #ifndef __SILICON_LABS_EM_LCD_H_
\r
35 #define __SILICON_LABS_EM_LCD_H_
\r
37 #include "em_device.h"
\r
39 #if defined(LCD_COUNT) && (LCD_COUNT > 0)
\r
41 #include <stdbool.h>
\r
47 /***************************************************************************//**
\r
48 * @addtogroup EM_Library
\r
50 ******************************************************************************/
\r
52 /***************************************************************************//**
\r
55 ******************************************************************************/
\r
57 /*******************************************************************************
\r
58 ******************************** ENUMS ************************************
\r
59 ******************************************************************************/
\r
64 /** Static (segments can be multiplexed with LCD_COM[0]) */
\r
65 lcdMuxStatic = LCD_DISPCTRL_MUX_STATIC,
\r
66 /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */
\r
67 lcdMuxDuplex = LCD_DISPCTRL_MUX_DUPLEX,
\r
68 /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */
\r
69 lcdMuxTriplex = LCD_DISPCTRL_MUX_TRIPLEX,
\r
70 /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */
\r
71 lcdMuxQuadruplex = LCD_DISPCTRL_MUX_QUADRUPLEX,
\r
72 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
73 /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
\r
74 lcdMuxSextaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_DUPLEX,
\r
75 /** Octaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
\r
76 lcdMuxOctaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_QUADRUPLEX
\r
83 /** Static (2 levels) */
\r
84 lcdBiasStatic = LCD_DISPCTRL_BIAS_STATIC,
\r
85 /** 1/2 Bias (3 levels) */
\r
86 lcdBiasOneHalf = LCD_DISPCTRL_BIAS_ONEHALF,
\r
87 /** 1/3 Bias (4 levels) */
\r
88 lcdBiasOneThird = LCD_DISPCTRL_BIAS_ONETHIRD,
\r
89 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
90 /** 1/4 Bias (5 levels) */
\r
91 lcdBiasOneFourth = LCD_DISPCTRL_BIAS_ONEFOURTH,
\r
98 /** Low power optimized waveform output */
\r
99 lcdWaveLowPower = LCD_DISPCTRL_WAVE_LOWPOWER,
\r
100 /** Regular waveform output */
\r
101 lcdWaveNormal = LCD_DISPCTRL_WAVE_NORMAL
\r
102 } LCD_Wave_TypeDef;
\r
104 /** VLCD Voltage Source */
\r
107 /** VLCD Powered by VDD */
\r
108 lcdVLCDSelVDD = LCD_DISPCTRL_VLCDSEL_VDD,
\r
109 /** VLCD Powered by external VDD / Voltage Boost */
\r
110 lcdVLCDSelVExtBoost = LCD_DISPCTRL_VLCDSEL_VEXTBOOST
\r
111 } LCD_VLCDSel_TypeDef;
\r
113 /** Contrast Configuration */
\r
116 /** Contrast is adjusted relative to VDD (VLCD) */
\r
117 lcdConConfVLCD = LCD_DISPCTRL_CONCONF_VLCD,
\r
118 /** Contrast is adjusted relative to Ground */
\r
119 lcdConConfGND = LCD_DISPCTRL_CONCONF_GND
\r
120 } LCD_ConConf_TypeDef;
\r
122 /** Voltage Boost Level - Datasheets document setting for each part number */
\r
125 lcdVBoostLevel0 = LCD_DISPCTRL_VBLEV_LEVEL0, /**< Voltage boost LEVEL0 */
\r
126 lcdVBoostLevel1 = LCD_DISPCTRL_VBLEV_LEVEL1, /**< Voltage boost LEVEL1 */
\r
127 lcdVBoostLevel2 = LCD_DISPCTRL_VBLEV_LEVEL2, /**< Voltage boost LEVEL2 */
\r
128 lcdVBoostLevel3 = LCD_DISPCTRL_VBLEV_LEVEL3, /**< Voltage boost LEVEL3 */
\r
129 lcdVBoostLevel4 = LCD_DISPCTRL_VBLEV_LEVEL4, /**< Voltage boost LEVEL4 */
\r
130 lcdVBoostLevel5 = LCD_DISPCTRL_VBLEV_LEVEL5, /**< Voltage boost LEVEL5 */
\r
131 lcdVBoostLevel6 = LCD_DISPCTRL_VBLEV_LEVEL6, /**< Voltage boost LEVEL6 */
\r
132 lcdVBoostLevel7 = LCD_DISPCTRL_VBLEV_LEVEL7 /**< Voltage boost LEVEL7 */
\r
133 } LCD_VBoostLevel_TypeDef;
\r
135 /** Frame Counter Clock Prescaler, FC-CLK = FrameRate (Hz) / this factor */
\r
138 /** Prescale Div 1 */
\r
139 lcdFCPrescDiv1 = LCD_BACTRL_FCPRESC_DIV1,
\r
140 /** Prescale Div 2 */
\r
141 lcdFCPrescDiv2 = LCD_BACTRL_FCPRESC_DIV2,
\r
142 /** Prescale Div 4 */
\r
143 lcdFCPrescDiv4 = LCD_BACTRL_FCPRESC_DIV4,
\r
144 /** Prescale Div 8 */
\r
145 lcdFCPrescDiv8 = LCD_BACTRL_FCPRESC_DIV8
\r
146 } LCD_FCPreScale_TypeDef;
\r
148 /** Segment selection */
\r
151 /** Select segment lines 0 to 3 */
\r
152 lcdSegment0_3 = (1 << 0),
\r
153 /** Select segment lines 4 to 7 */
\r
154 lcdSegment4_7 = (1 << 1),
\r
155 /** Select segment lines 8 to 11 */
\r
156 lcdSegment8_11 = (1 << 2),
\r
157 /** Select segment lines 12 to 15 */
\r
158 lcdSegment12_15 = (1 << 3),
\r
159 /** Select segment lines 16 to 19 */
\r
160 lcdSegment16_19 = (1 << 4),
\r
161 /** Select segment lines 20 to 23 */
\r
162 lcdSegment20_23 = (1 << 5),
\r
163 #if defined(_EFM32_TINY_FAMILY)
\r
164 /** Select all segment lines */
\r
165 lcdSegmentAll = (0x003f)
\r
167 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
168 /** Select segment lines 24 to 27 */
\r
169 lcdSegment24_27 = (1 << 6),
\r
170 /** Select segment lines 28 to 31 */
\r
171 lcdSegment28_31 = (1 << 7),
\r
172 /** Select segment lines 32 to 35 */
\r
173 lcdSegment32_35 = (1 << 8),
\r
174 /** Select segment lines 36 to 39 */
\r
175 lcdSegment36_39 = (1 << 9),
\r
176 /** Select all segment lines */
\r
177 lcdSegmentAll = (0x03ff)
\r
179 } LCD_SegmentRange_TypeDef;
\r
181 /** Update Data Control */
\r
184 /** Regular update, data transfer done immediately */
\r
185 lcdUpdateCtrlRegular = LCD_CTRL_UDCTRL_REGULAR,
\r
186 /** Data transfer done at Frame Counter event */
\r
187 lcdUpdateCtrlFCEvent = LCD_CTRL_UDCTRL_FCEVENT,
\r
188 /** Data transfer done at Frame Start */
\r
189 lcdUpdateCtrlFrameStart = LCD_CTRL_UDCTRL_FRAMESTART
\r
190 } LCD_UpdateCtrl_TypeDef;
\r
192 /** Animation Shift operation; none, left or right */
\r
196 lcdAnimShiftNone = _LCD_BACTRL_AREGASC_NOSHIFT,
\r
197 /** Shift segment bits left */
\r
198 lcdAnimShiftLeft = _LCD_BACTRL_AREGASC_SHIFTLEFT,
\r
199 /** Shift segment bits right */
\r
200 lcdAnimShiftRight = _LCD_BACTRL_AREGASC_SHIFTRIGHT
\r
201 } LCD_AnimShift_TypeDef;
\r
203 /** Animation Logic Control, how AReg and BReg should be combined */
\r
206 /** Use bitwise logic AND to mix animation register A (AREGA) and B (AREGB) */
\r
207 lcdAnimLogicAnd = LCD_BACTRL_ALOGSEL_AND,
\r
208 /** Use bitwise logic OR to mix animation register A (AREGA) and B (AREGB) */
\r
209 lcdAnimLogicOr = LCD_BACTRL_ALOGSEL_OR
\r
210 } LCD_AnimLogic_TypeDef;
\r
213 /*******************************************************************************
\r
214 ******************************* STRUCTS ***********************************
\r
215 ******************************************************************************/
\r
217 /** LCD Animation Configuration */
\r
220 /** Enable Animation at end of initialization */
\r
222 /** Initial Animation Register A Value */
\r
224 /** Shift operation of Animation Register A */
\r
225 LCD_AnimShift_TypeDef AShift;
\r
226 /** Initial Animation Register B Value */
\r
228 /** Shift operation of Animation Register B */
\r
229 LCD_AnimShift_TypeDef BShift;
\r
230 /** A and B Logical Operation to use for mixing and outputting resulting segments */
\r
231 LCD_AnimLogic_TypeDef animLogic;
\r
232 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
233 /** Number of first segment to animate. Options are 0 or 8 for Giant/Leopard. End is startSeg+7 */
\r
236 } LCD_AnimInit_TypeDef;
\r
238 /** LCD Frame Control Initialization */
\r
241 /** Enable at end */
\r
243 /** Frame Counter top value */
\r
245 /** Frame Counter clock prescaler */
\r
246 LCD_FCPreScale_TypeDef prescale;
\r
247 } LCD_FrameCountInit_TypeDef;
\r
249 /** LCD Controller Initialization structure */
\r
252 /** Enable controller at end of initialization */
\r
254 /** Mux configuration */
\r
255 LCD_Mux_TypeDef mux;
\r
256 /** Bias configuration */
\r
257 LCD_Bias_TypeDef bias;
\r
258 /** Wave configuration */
\r
259 LCD_Wave_TypeDef wave;
\r
261 LCD_VLCDSel_TypeDef vlcd;
\r
262 /** Contrast Configuration */
\r
263 LCD_ConConf_TypeDef contrast;
\r
264 } LCD_Init_TypeDef;
\r
266 /** Default config for LCD init structure, enables 160 segments */
\r
267 #define LCD_INIT_DEFAULT \
\r
269 lcdMuxQuadruplex, \
\r
276 /*******************************************************************************
\r
277 ***************************** PROTOTYPES **********************************
\r
278 ******************************************************************************/
\r
280 void LCD_Init(const LCD_Init_TypeDef *lcdInit);
\r
281 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd);
\r
282 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud);
\r
283 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit);
\r
284 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit);
\r
286 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segment, bool enable);
\r
287 void LCD_SegmentSet(int com, int bit, bool enable);
\r
288 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits);
\r
289 #if defined(_EFM32_GECKO_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
290 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits);
\r
292 void LCD_ContrastSet(int level);
\r
293 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost);
\r
295 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
296 void LCD_BiasSegmentSet(int segment, int biasLevel);
\r
297 void LCD_BiasComSet(int com, int biasLevel);
\r
300 __STATIC_INLINE void LCD_Enable(bool enable);
\r
301 __STATIC_INLINE void LCD_AnimEnable(bool enable);
\r
302 __STATIC_INLINE void LCD_BlinkEnable(bool enable);
\r
303 __STATIC_INLINE void LCD_BlankEnable(bool enable);
\r
304 __STATIC_INLINE void LCD_FrameCountEnable(bool enable);
\r
305 __STATIC_INLINE int LCD_AnimState(void);
\r
306 __STATIC_INLINE int LCD_BlinkState(void);
\r
307 __STATIC_INLINE void LCD_FreezeEnable(bool enable);
\r
308 __STATIC_INLINE uint32_t LCD_SyncBusyGet(void);
\r
309 __STATIC_INLINE void LCD_SyncBusyDelay(uint32_t flags);
\r
310 __STATIC_INLINE uint32_t LCD_IntGet(void);
\r
311 __STATIC_INLINE uint32_t LCD_IntGetEnabled(void);
\r
312 __STATIC_INLINE void LCD_IntSet(uint32_t flags);
\r
313 __STATIC_INLINE void LCD_IntEnable(uint32_t flags);
\r
314 __STATIC_INLINE void LCD_IntDisable(uint32_t flags);
\r
315 __STATIC_INLINE void LCD_IntClear(uint32_t flags);
\r
316 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
317 __STATIC_INLINE void LCD_DSCEnable(bool enable);
\r
320 /***************************************************************************//**
\r
322 * Enable or disable LCD controller
\r
324 * @param[in] enable
\r
325 * If true, enables LCD controller with current configuration, if false
\r
326 * disables LCD controller. CMU clock for LCD must be enabled for correct
\r
328 ******************************************************************************/
\r
329 __STATIC_INLINE void LCD_Enable(bool enable)
\r
333 LCD->CTRL |= LCD_CTRL_EN;
\r
337 LCD->CTRL &= ~(LCD_CTRL_EN);
\r
342 /***************************************************************************//**
\r
344 * Enables or disables LCD Animation feature
\r
346 * @param[in] enable
\r
347 * Boolean true enables animation, false disables animation
\r
348 ******************************************************************************/
\r
349 __STATIC_INLINE void LCD_AnimEnable(bool enable)
\r
353 LCD->BACTRL |= LCD_BACTRL_AEN;
\r
357 LCD->BACTRL &= ~(LCD_BACTRL_AEN);
\r
362 /***************************************************************************//**
\r
364 * Enables or disables LCD blink
\r
366 * @param[in] enable
\r
367 * Boolean true enables blink, false disables blink
\r
368 ******************************************************************************/
\r
369 __STATIC_INLINE void LCD_BlinkEnable(bool enable)
\r
373 LCD->BACTRL |= LCD_BACTRL_BLINKEN;
\r
377 LCD->BACTRL &= ~(LCD_BACTRL_BLINKEN);
\r
382 /***************************************************************************//**
\r
384 * Disables all segments, while keeping segment state
\r
386 * @param[in] enable
\r
387 * Boolean true clears all segments, boolean false restores all segment lines
\r
388 ******************************************************************************/
\r
389 __STATIC_INLINE void LCD_BlankEnable(bool enable)
\r
393 LCD->BACTRL |= LCD_BACTRL_BLANK;
\r
397 LCD->BACTRL &= ~(LCD_BACTRL_BLANK);
\r
402 /***************************************************************************//**
\r
404 * Enables or disables LCD Frame Control
\r
406 * @param[in] enable
\r
407 * Boolean true enables frame counter, false disables frame counter
\r
408 ******************************************************************************/
\r
409 __STATIC_INLINE void LCD_FrameCountEnable(bool enable)
\r
413 LCD->BACTRL |= LCD_BACTRL_FCEN;
\r
417 LCD->BACTRL &= ~(LCD_BACTRL_FCEN);
\r
422 /***************************************************************************//**
\r
424 * Returns current animation state
\r
427 * Animation state, in range 0-15
\r
428 ******************************************************************************/
\r
429 __STATIC_INLINE int LCD_AnimState(void)
\r
431 return (int)(LCD->STATUS & _LCD_STATUS_ASTATE_MASK) >> _LCD_STATUS_ASTATE_SHIFT;
\r
435 /***************************************************************************//**
\r
437 * Returns current blink state
\r
440 * Return value is 1 if segments are enabled, 0 if disabled
\r
441 ******************************************************************************/
\r
442 __STATIC_INLINE int LCD_BlinkState(void)
\r
444 return (int)(LCD->STATUS & _LCD_STATUS_BLINK_MASK) >> _LCD_STATUS_BLINK_SHIFT;
\r
448 /***************************************************************************//**
\r
450 * When set, LCD registers will not be updated until cleared,
\r
452 * @param[in] enable
\r
453 * When enable is true, update is stopped, when false all registers are
\r
455 ******************************************************************************/
\r
456 __STATIC_INLINE void LCD_FreezeEnable(bool enable)
\r
460 LCD->FREEZE = LCD_FREEZE_REGFREEZE_FREEZE;
\r
464 LCD->FREEZE = LCD_FREEZE_REGFREEZE_UPDATE;
\r
469 /***************************************************************************//**
\r
471 * Returns SYNCBUSY bits, indicating which registers have pending updates
\r
474 * Bit fields for LCD registers which have pending updates
\r
475 ******************************************************************************/
\r
476 __STATIC_INLINE uint32_t LCD_SyncBusyGet(void)
\r
478 return(LCD->SYNCBUSY);
\r
482 /***************************************************************************//**
\r
484 * Polls LCD SYNCBUSY flags, until flag has been cleared
\r
487 * Bit fields for LCD registers that shall be updated before we continue
\r
488 ******************************************************************************/
\r
489 __STATIC_INLINE void LCD_SyncBusyDelay(uint32_t flags)
\r
491 while (LCD->SYNCBUSY & flags)
\r
496 /***************************************************************************//**
\r
498 * Get pending LCD interrupt flags
\r
501 * Pending LCD interrupt sources. Returns a set of interrupt flags OR-ed
\r
502 * together for multiple interrupt sources in the LCD module (LCD_IFS_nnn).
\r
503 ******************************************************************************/
\r
504 __STATIC_INLINE uint32_t LCD_IntGet(void)
\r
510 /***************************************************************************//**
\r
512 * Get enabled and pending LCD interrupt flags.
\r
515 * Useful for handling more interrupt sources in the same interrupt handler.
\r
518 * The event bits are not cleared by the use of this function.
\r
521 * Pending and enabled LCD interrupt sources.
\r
522 * The return value is the bitwise AND combination of
\r
523 * - the OR combination of enabled interrupt sources in LCD_IEN_nnn
\r
524 * register (LCD_IEN_nnn) and
\r
525 * - the bitwise OR combination of valid interrupt flags of the LCD module
\r
527 ******************************************************************************/
\r
528 __STATIC_INLINE uint32_t LCD_IntGetEnabled(void)
\r
532 /* Store LCD->IEN in temporary variable in order to define explicit order
\r
533 * of volatile accesses. */
\r
536 /* Bitwise AND of pending and enabled interrupts */
\r
537 return LCD->IF & tmp;
\r
541 /***************************************************************************//**
\r
543 * Set one or more pending LCD interrupts from SW.
\r
546 * LCD interrupt sources to set to pending. Use a set of interrupt flags
\r
547 * OR-ed together to set multiple interrupt sources for the LCD module
\r
549 ******************************************************************************/
\r
550 __STATIC_INLINE void LCD_IntSet(uint32_t flags)
\r
556 /***************************************************************************//**
\r
558 * Enable LCD interrupts
\r
561 * LCD interrupt sources to enable. Use a set of interrupt flags OR-ed
\r
562 * together to set multiple interrupt sources for the LCD module
\r
564 ******************************************************************************/
\r
565 __STATIC_INLINE void LCD_IntEnable(uint32_t flags)
\r
571 /***************************************************************************//**
\r
573 * Disable LCD interrupts
\r
576 * LCD interrupt sources to disable. Use a set of interrupt flags OR-ed
\r
577 * together to disable multiple interrupt sources for the LCD module
\r
579 ******************************************************************************/
\r
580 __STATIC_INLINE void LCD_IntDisable(uint32_t flags)
\r
582 LCD->IEN &= ~(flags);
\r
586 /***************************************************************************//**
\r
588 * Clear one or more interrupt flags
\r
591 * LCD interrupt sources to clear. Use a set of interrupt flags OR-ed
\r
592 * together to clear multiple interrupt sources for the LCD module
\r
594 ******************************************************************************/
\r
595 __STATIC_INLINE void LCD_IntClear(uint32_t flags)
\r
601 #if defined(_EFM32_TINY_FAMILY) || defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
\r
602 /***************************************************************************//**
\r
604 * Enable or disable LCD Direct Segment Control
\r
606 * @param[in] enable
\r
607 * If true, enables LCD controller Direct Segment Control
\r
608 * Segment and COM line bias levels needs to be set explicitly with the
\r
609 * LCD_BiasSegmentSet() and LCD_BiasComSet() function calls.
\r
610 ******************************************************************************/
\r
611 __STATIC_INLINE void LCD_DSCEnable(bool enable)
\r
615 LCD->CTRL |= LCD_CTRL_DSC;
\r
619 LCD->CTRL &= ~(LCD_CTRL_DSC);
\r
624 /** @} (end addtogroup LCD) */
\r
625 /** @} (end addtogroup EM_Library) */
\r
631 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */
\r
633 #endif /* __SILICON_LABS_EM_LCD_H_ */
\r