1 /***************************************************************************//**
\r
3 * @brief Liquid Crystal Display (LCD) peripheral API
\r
5 *******************************************************************************
\r
7 * <b>(C) Copyright 2015 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
33 #ifndef __SILICON_LABS_EM_LCD_H__
\r
34 #define __SILICON_LABS_EM_LCD_H__
\r
36 #include "em_device.h"
\r
38 #if defined(LCD_COUNT) && (LCD_COUNT > 0)
\r
40 #include <stdbool.h>
\r
46 /***************************************************************************//**
\r
47 * @addtogroup EM_Library
\r
49 ******************************************************************************/
\r
51 /***************************************************************************//**
\r
54 ******************************************************************************/
\r
56 /*******************************************************************************
\r
57 ******************************** ENUMS ************************************
\r
58 ******************************************************************************/
\r
63 /** Static (segments can be multiplexed with LCD_COM[0]) */
\r
64 lcdMuxStatic = LCD_DISPCTRL_MUX_STATIC,
\r
65 /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]) */
\r
66 lcdMuxDuplex = LCD_DISPCTRL_MUX_DUPLEX,
\r
67 /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]) */
\r
68 lcdMuxTriplex = LCD_DISPCTRL_MUX_TRIPLEX,
\r
69 /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]) */
\r
70 lcdMuxQuadruplex = LCD_DISPCTRL_MUX_QUADRUPLEX,
\r
71 #if defined(LCD_DISPCTRL_MUXE_MUXE)
\r
72 /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
\r
73 lcdMuxSextaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_DUPLEX,
\r
74 /** Octaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]) */
\r
75 lcdMuxOctaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_QUADRUPLEX
\r
82 /** Static (2 levels) */
\r
83 lcdBiasStatic = LCD_DISPCTRL_BIAS_STATIC,
\r
84 /** 1/2 Bias (3 levels) */
\r
85 lcdBiasOneHalf = LCD_DISPCTRL_BIAS_ONEHALF,
\r
86 /** 1/3 Bias (4 levels) */
\r
87 lcdBiasOneThird = LCD_DISPCTRL_BIAS_ONETHIRD,
\r
88 #if defined(LCD_DISPCTRL_BIAS_ONEFOURTH)
\r
89 /** 1/4 Bias (5 levels) */
\r
90 lcdBiasOneFourth = LCD_DISPCTRL_BIAS_ONEFOURTH,
\r
97 /** Low power optimized waveform output */
\r
98 lcdWaveLowPower = LCD_DISPCTRL_WAVE_LOWPOWER,
\r
99 /** Regular waveform output */
\r
100 lcdWaveNormal = LCD_DISPCTRL_WAVE_NORMAL
\r
101 } LCD_Wave_TypeDef;
\r
103 /** VLCD Voltage Source */
\r
106 /** VLCD Powered by VDD */
\r
107 lcdVLCDSelVDD = LCD_DISPCTRL_VLCDSEL_VDD,
\r
108 /** VLCD Powered by external VDD / Voltage Boost */
\r
109 lcdVLCDSelVExtBoost = LCD_DISPCTRL_VLCDSEL_VEXTBOOST
\r
110 } LCD_VLCDSel_TypeDef;
\r
112 /** Contrast Configuration */
\r
115 /** Contrast is adjusted relative to VDD (VLCD) */
\r
116 lcdConConfVLCD = LCD_DISPCTRL_CONCONF_VLCD,
\r
117 /** Contrast is adjusted relative to Ground */
\r
118 lcdConConfGND = LCD_DISPCTRL_CONCONF_GND
\r
119 } LCD_ConConf_TypeDef;
\r
121 /** Voltage Boost Level - Datasheets document setting for each part number */
\r
124 lcdVBoostLevel0 = LCD_DISPCTRL_VBLEV_LEVEL0, /**< Voltage boost LEVEL0 */
\r
125 lcdVBoostLevel1 = LCD_DISPCTRL_VBLEV_LEVEL1, /**< Voltage boost LEVEL1 */
\r
126 lcdVBoostLevel2 = LCD_DISPCTRL_VBLEV_LEVEL2, /**< Voltage boost LEVEL2 */
\r
127 lcdVBoostLevel3 = LCD_DISPCTRL_VBLEV_LEVEL3, /**< Voltage boost LEVEL3 */
\r
128 lcdVBoostLevel4 = LCD_DISPCTRL_VBLEV_LEVEL4, /**< Voltage boost LEVEL4 */
\r
129 lcdVBoostLevel5 = LCD_DISPCTRL_VBLEV_LEVEL5, /**< Voltage boost LEVEL5 */
\r
130 lcdVBoostLevel6 = LCD_DISPCTRL_VBLEV_LEVEL6, /**< Voltage boost LEVEL6 */
\r
131 lcdVBoostLevel7 = LCD_DISPCTRL_VBLEV_LEVEL7 /**< Voltage boost LEVEL7 */
\r
132 } LCD_VBoostLevel_TypeDef;
\r
134 /** Frame Counter Clock Prescaler, FC-CLK = FrameRate (Hz) / this factor */
\r
137 /** Prescale Div 1 */
\r
138 lcdFCPrescDiv1 = LCD_BACTRL_FCPRESC_DIV1,
\r
139 /** Prescale Div 2 */
\r
140 lcdFCPrescDiv2 = LCD_BACTRL_FCPRESC_DIV2,
\r
141 /** Prescale Div 4 */
\r
142 lcdFCPrescDiv4 = LCD_BACTRL_FCPRESC_DIV4,
\r
143 /** Prescale Div 8 */
\r
144 lcdFCPrescDiv8 = LCD_BACTRL_FCPRESC_DIV8
\r
145 } LCD_FCPreScale_TypeDef;
\r
147 /** Segment selection */
\r
150 /** Select segment lines 0 to 3 */
\r
151 lcdSegment0_3 = (1 << 0),
\r
152 /** Select segment lines 4 to 7 */
\r
153 lcdSegment4_7 = (1 << 1),
\r
154 /** Select segment lines 8 to 11 */
\r
155 lcdSegment8_11 = (1 << 2),
\r
156 /** Select segment lines 12 to 15 */
\r
157 lcdSegment12_15 = (1 << 3),
\r
158 /** Select segment lines 16 to 19 */
\r
159 lcdSegment16_19 = (1 << 4),
\r
160 /** Select segment lines 20 to 23 */
\r
161 lcdSegment20_23 = (1 << 5),
\r
162 #if defined(_LCD_SEGD0L_MASK) && (_LCD_SEGD0L_MASK == 0x00FFFFFFUL)
\r
163 /** Select all segment lines */
\r
164 lcdSegmentAll = (0x003f)
\r
165 #elif defined(_LCD_SEGD0H_MASK) && (_LCD_SEGD0H_MASK == 0x000000FFUL)
\r
166 /** Select segment lines 24 to 27 */
\r
167 lcdSegment24_27 = (1 << 6),
\r
168 /** Select segment lines 28 to 31 */
\r
169 lcdSegment28_31 = (1 << 7),
\r
170 /** Select segment lines 32 to 35 */
\r
171 lcdSegment32_35 = (1 << 8),
\r
172 /** Select segment lines 36 to 39 */
\r
173 lcdSegment36_39 = (1 << 9),
\r
174 /** Select all segment lines */
\r
175 lcdSegmentAll = (0x03ff)
\r
177 } LCD_SegmentRange_TypeDef;
\r
179 /** Update Data Control */
\r
182 /** Regular update, data transfer done immediately */
\r
183 lcdUpdateCtrlRegular = LCD_CTRL_UDCTRL_REGULAR,
\r
184 /** Data transfer done at Frame Counter event */
\r
185 lcdUpdateCtrlFCEvent = LCD_CTRL_UDCTRL_FCEVENT,
\r
186 /** Data transfer done at Frame Start */
\r
187 lcdUpdateCtrlFrameStart = LCD_CTRL_UDCTRL_FRAMESTART
\r
188 } LCD_UpdateCtrl_TypeDef;
\r
190 /** Animation Shift operation; none, left or right */
\r
194 lcdAnimShiftNone = _LCD_BACTRL_AREGASC_NOSHIFT,
\r
195 /** Shift segment bits left */
\r
196 lcdAnimShiftLeft = _LCD_BACTRL_AREGASC_SHIFTLEFT,
\r
197 /** Shift segment bits right */
\r
198 lcdAnimShiftRight = _LCD_BACTRL_AREGASC_SHIFTRIGHT
\r
199 } LCD_AnimShift_TypeDef;
\r
201 /** Animation Logic Control, how AReg and BReg should be combined */
\r
204 /** Use bitwise logic AND to mix animation register A (AREGA) and B (AREGB) */
\r
205 lcdAnimLogicAnd = LCD_BACTRL_ALOGSEL_AND,
\r
206 /** Use bitwise logic OR to mix animation register A (AREGA) and B (AREGB) */
\r
207 lcdAnimLogicOr = LCD_BACTRL_ALOGSEL_OR
\r
208 } LCD_AnimLogic_TypeDef;
\r
211 /*******************************************************************************
\r
212 ******************************* STRUCTS ***********************************
\r
213 ******************************************************************************/
\r
215 /** LCD Animation Configuration */
\r
218 /** Enable Animation at end of initialization */
\r
220 /** Initial Animation Register A Value */
\r
222 /** Shift operation of Animation Register A */
\r
223 LCD_AnimShift_TypeDef AShift;
\r
224 /** Initial Animation Register B Value */
\r
226 /** Shift operation of Animation Register B */
\r
227 LCD_AnimShift_TypeDef BShift;
\r
228 /** A and B Logical Operation to use for mixing and outputting resulting segments */
\r
229 LCD_AnimLogic_TypeDef animLogic;
\r
230 #if defined(LCD_BACTRL_ALOC)
\r
231 /** Number of first segment to animate. Options are 0 or 8 for Giant/Leopard. End is startSeg+7 */
\r
234 } LCD_AnimInit_TypeDef;
\r
236 /** LCD Frame Control Initialization */
\r
239 /** Enable at end */
\r
241 /** Frame Counter top value */
\r
243 /** Frame Counter clock prescaler */
\r
244 LCD_FCPreScale_TypeDef prescale;
\r
245 } LCD_FrameCountInit_TypeDef;
\r
247 /** LCD Controller Initialization structure */
\r
250 /** Enable controller at end of initialization */
\r
252 /** Mux configuration */
\r
253 LCD_Mux_TypeDef mux;
\r
254 /** Bias configuration */
\r
255 LCD_Bias_TypeDef bias;
\r
256 /** Wave configuration */
\r
257 LCD_Wave_TypeDef wave;
\r
259 LCD_VLCDSel_TypeDef vlcd;
\r
260 /** Contrast Configuration */
\r
261 LCD_ConConf_TypeDef contrast;
\r
262 } LCD_Init_TypeDef;
\r
264 /** Default config for LCD init structure, enables 160 segments */
\r
265 #define LCD_INIT_DEFAULT \
\r
268 lcdMuxQuadruplex, \
\r
275 /*******************************************************************************
\r
276 ***************************** PROTOTYPES **********************************
\r
277 ******************************************************************************/
\r
279 void LCD_Init(const LCD_Init_TypeDef *lcdInit);
\r
280 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd);
\r
281 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud);
\r
282 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit);
\r
283 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit);
\r
285 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segment, bool enable);
\r
286 void LCD_SegmentSet(int com, int bit, bool enable);
\r
287 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits);
\r
288 #if defined(_LCD_SEGD0H_MASK)
\r
289 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits);
\r
291 void LCD_ContrastSet(int level);
\r
292 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost);
\r
294 #if defined(LCD_CTRL_DSC)
\r
295 void LCD_BiasSegmentSet(int segment, int biasLevel);
\r
296 void LCD_BiasComSet(int com, int biasLevel);
\r
299 /***************************************************************************//**
\r
301 * Enable or disable LCD controller
\r
303 * @param[in] enable
\r
304 * If true, enables LCD controller with current configuration, if false
\r
305 * disables LCD controller. CMU clock for LCD must be enabled for correct
\r
307 ******************************************************************************/
\r
308 __STATIC_INLINE void LCD_Enable(bool enable)
\r
312 LCD->CTRL |= LCD_CTRL_EN;
\r
316 LCD->CTRL &= ~LCD_CTRL_EN;
\r
321 /***************************************************************************//**
\r
323 * Enables or disables LCD Animation feature
\r
325 * @param[in] enable
\r
326 * Boolean true enables animation, false disables animation
\r
327 ******************************************************************************/
\r
328 __STATIC_INLINE void LCD_AnimEnable(bool enable)
\r
332 LCD->BACTRL |= LCD_BACTRL_AEN;
\r
336 LCD->BACTRL &= ~LCD_BACTRL_AEN;
\r
341 /***************************************************************************//**
\r
343 * Enables or disables LCD blink
\r
345 * @param[in] enable
\r
346 * Boolean true enables blink, false disables blink
\r
347 ******************************************************************************/
\r
348 __STATIC_INLINE void LCD_BlinkEnable(bool enable)
\r
352 LCD->BACTRL |= LCD_BACTRL_BLINKEN;
\r
356 LCD->BACTRL &= ~LCD_BACTRL_BLINKEN;
\r
361 /***************************************************************************//**
\r
363 * Disables all segments, while keeping segment state
\r
365 * @param[in] enable
\r
366 * Boolean true clears all segments, boolean false restores all segment lines
\r
367 ******************************************************************************/
\r
368 __STATIC_INLINE void LCD_BlankEnable(bool enable)
\r
372 LCD->BACTRL |= LCD_BACTRL_BLANK;
\r
376 LCD->BACTRL &= ~LCD_BACTRL_BLANK;
\r
381 /***************************************************************************//**
\r
383 * Enables or disables LCD Frame Control
\r
385 * @param[in] enable
\r
386 * Boolean true enables frame counter, false disables frame counter
\r
387 ******************************************************************************/
\r
388 __STATIC_INLINE void LCD_FrameCountEnable(bool enable)
\r
392 LCD->BACTRL |= LCD_BACTRL_FCEN;
\r
396 LCD->BACTRL &= ~LCD_BACTRL_FCEN;
\r
401 /***************************************************************************//**
\r
403 * Returns current animation state
\r
406 * Animation state, in range 0-15
\r
407 ******************************************************************************/
\r
408 __STATIC_INLINE int LCD_AnimState(void)
\r
410 return (int)(LCD->STATUS & _LCD_STATUS_ASTATE_MASK) >> _LCD_STATUS_ASTATE_SHIFT;
\r
414 /***************************************************************************//**
\r
416 * Returns current blink state
\r
419 * Return value is 1 if segments are enabled, 0 if disabled
\r
420 ******************************************************************************/
\r
421 __STATIC_INLINE int LCD_BlinkState(void)
\r
423 return (int)(LCD->STATUS & _LCD_STATUS_BLINK_MASK) >> _LCD_STATUS_BLINK_SHIFT;
\r
427 /***************************************************************************//**
\r
429 * When set, LCD registers will not be updated until cleared,
\r
431 * @param[in] enable
\r
432 * When enable is true, update is stopped, when false all registers are
\r
434 ******************************************************************************/
\r
435 __STATIC_INLINE void LCD_FreezeEnable(bool enable)
\r
439 LCD->FREEZE = LCD_FREEZE_REGFREEZE_FREEZE;
\r
443 LCD->FREEZE = LCD_FREEZE_REGFREEZE_UPDATE;
\r
448 /***************************************************************************//**
\r
450 * Returns SYNCBUSY bits, indicating which registers have pending updates
\r
453 * Bit fields for LCD registers which have pending updates
\r
454 ******************************************************************************/
\r
455 __STATIC_INLINE uint32_t LCD_SyncBusyGet(void)
\r
457 return LCD->SYNCBUSY;
\r
461 /***************************************************************************//**
\r
463 * Polls LCD SYNCBUSY flags, until flag has been cleared
\r
466 * Bit fields for LCD registers that shall be updated before we continue
\r
467 ******************************************************************************/
\r
468 __STATIC_INLINE void LCD_SyncBusyDelay(uint32_t flags)
\r
470 while (LCD->SYNCBUSY & flags)
\r
475 /***************************************************************************//**
\r
477 * Get pending LCD interrupt flags
\r
480 * Pending LCD interrupt sources. Returns a set of interrupt flags OR-ed
\r
481 * together for multiple interrupt sources in the LCD module (LCD_IFS_nnn).
\r
482 ******************************************************************************/
\r
483 __STATIC_INLINE uint32_t LCD_IntGet(void)
\r
489 /***************************************************************************//**
\r
491 * Get enabled and pending LCD interrupt flags.
\r
494 * Useful for handling more interrupt sources in the same interrupt handler.
\r
497 * The event bits are not cleared by the use of this function.
\r
500 * Pending and enabled LCD interrupt sources.
\r
501 * The return value is the bitwise AND combination of
\r
502 * - the OR combination of enabled interrupt sources in LCD_IEN_nnn
\r
503 * register (LCD_IEN_nnn) and
\r
504 * - the bitwise OR combination of valid interrupt flags of the LCD module
\r
506 ******************************************************************************/
\r
507 __STATIC_INLINE uint32_t LCD_IntGetEnabled(void)
\r
511 /* Store LCD->IEN in temporary variable in order to define explicit order
\r
512 * of volatile accesses. */
\r
515 /* Bitwise AND of pending and enabled interrupts */
\r
516 return LCD->IF & ien;
\r
520 /***************************************************************************//**
\r
522 * Set one or more pending LCD interrupts from SW.
\r
525 * LCD interrupt sources to set to pending. Use a set of interrupt flags
\r
526 * OR-ed together to set multiple interrupt sources for the LCD module
\r
528 ******************************************************************************/
\r
529 __STATIC_INLINE void LCD_IntSet(uint32_t flags)
\r
535 /***************************************************************************//**
\r
537 * Enable LCD interrupts
\r
540 * LCD interrupt sources to enable. Use a set of interrupt flags OR-ed
\r
541 * together to set multiple interrupt sources for the LCD module
\r
543 ******************************************************************************/
\r
544 __STATIC_INLINE void LCD_IntEnable(uint32_t flags)
\r
550 /***************************************************************************//**
\r
552 * Disable LCD interrupts
\r
555 * LCD interrupt sources to disable. Use a set of interrupt flags OR-ed
\r
556 * together to disable multiple interrupt sources for the LCD module
\r
558 ******************************************************************************/
\r
559 __STATIC_INLINE void LCD_IntDisable(uint32_t flags)
\r
561 LCD->IEN &= ~flags;
\r
565 /***************************************************************************//**
\r
567 * Clear one or more interrupt flags
\r
570 * LCD interrupt sources to clear. Use a set of interrupt flags OR-ed
\r
571 * together to clear multiple interrupt sources for the LCD module
\r
573 ******************************************************************************/
\r
574 __STATIC_INLINE void LCD_IntClear(uint32_t flags)
\r
580 #if defined(LCD_CTRL_DSC)
\r
581 /***************************************************************************//**
\r
583 * Enable or disable LCD Direct Segment Control
\r
585 * @param[in] enable
\r
586 * If true, enables LCD controller Direct Segment Control
\r
587 * Segment and COM line bias levels needs to be set explicitly with the
\r
588 * LCD_BiasSegmentSet() and LCD_BiasComSet() function calls.
\r
589 ******************************************************************************/
\r
590 __STATIC_INLINE void LCD_DSCEnable(bool enable)
\r
594 LCD->CTRL |= LCD_CTRL_DSC;
\r
598 LCD->CTRL &= ~LCD_CTRL_DSC;
\r
603 /** @} (end addtogroup LCD) */
\r
604 /** @} (end addtogroup EM_Library) */
\r
610 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */
\r
612 #endif /* __SILICON_LABS_EM_LCD_H__ */
\r