1 /***************************************************************************//**
2 * @file
3 * @brief Liquid Crystal Display (LCD) peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #ifndef EM_LCD_H
32 #define EM_LCD_H
33
34 #include "em_device.h"
35
36 #if defined(LCD_COUNT) && (LCD_COUNT > 0)
37 #include <stdint.h>
38 #include <stdbool.h>
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 /***************************************************************************//**
45 * @addtogroup lcd
46 * @{
47 ******************************************************************************/
48
49 /*******************************************************************************
50 ******************************** DEFINES **********************************
51 ******************************************************************************/
52
53 /** Default Clock Prescaler. */
54 #define LCD_DEFAULT_CLOCK_PRESCALER 64
55 /** Default LCD Frame Rate Divisor. */
56 #define LCD_DEFAULT_FRAME_RATE_DIV 4
57 /** Default LCD Contrast. */
58 #define LCD_DEFAULT_CONTRAST 15
59
60 #if defined(_SILICON_LABS_32B_SERIES_2)
61 /** Maximum common lines of LCD. */
62 #if defined(LCD_OCTAPLEX) && (LCD_OCTAPLEX == 1)
63 #define LCD_COM_LINES_MAX (LCD_COM_NUM + LCD_SEGASCOM_NUM)
64 #else
65 #define LCD_COM_LINES_MAX LCD_COM_NUM
66 #endif
67 /** Maximum segment lines of LCD. */
68 #define LCD_SEGMENT_LINES_MAX LCD_SEG_NUM
69 #endif
70
71 /*******************************************************************************
72 ******************************** ENUMS ************************************
73 ******************************************************************************/
74
75 /** MUX setting. */
76 typedef enum {
77 /** Static (segments can be multiplexed with LCD_COM[0]). */
78 lcdMuxStatic = LCD_DISPCTRL_MUX_STATIC,
79 /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]). */
80 lcdMuxDuplex = LCD_DISPCTRL_MUX_DUPLEX,
81 /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]). */
82 lcdMuxTriplex = LCD_DISPCTRL_MUX_TRIPLEX,
83 /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]). */
84 lcdMuxQuadruplex = LCD_DISPCTRL_MUX_QUADRUPLEX,
85 #if defined(LCD_DISPCTRL_MUXE_MUXE)
86 /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]). */
87 lcdMuxSextaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_DUPLEX,
88 /** Octaplex / 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]). */
89 lcdMuxOctaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_QUADRUPLEX
90 #elif defined(LCD_DISPCTRL_MUX_SEXTAPLEX)
91 /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]). */
92 lcdMuxSextaplex = LCD_DISPCTRL_MUX_SEXTAPLEX,
93 /** Octaplex / 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]). */
94 lcdMuxOctaplex = LCD_DISPCTRL_MUX_OCTAPLEX,
95 #endif
96 } LCD_Mux_TypeDef;
97
98 /** Wave type. */
99 typedef enum {
100 #if defined(_SILICON_LABS_32B_SERIES_2)
101 /** Low power optimized waveform output. */
102 lcdWaveLowPower = LCD_DISPCTRL_WAVE_TYPEB,
103 /** Regular waveform output */
104 lcdWaveNormal = LCD_DISPCTRL_WAVE_TYPEA
105 #else
106 /** Low power optimized waveform output. */
107 lcdWaveLowPower = LCD_DISPCTRL_WAVE_LOWPOWER,
108 /** Regular waveform output */
109 lcdWaveNormal = LCD_DISPCTRL_WAVE_NORMAL
110 #endif
111 } LCD_Wave_TypeDef;
112
113 /** Bias setting. */
114 typedef enum {
115 /** Static (2 levels). */
116 lcdBiasStatic = LCD_DISPCTRL_BIAS_STATIC,
117 /** 1/2 Bias (3 levels). */
118 lcdBiasOneHalf = LCD_DISPCTRL_BIAS_ONEHALF,
119 /** 1/3 Bias (4 levels). */
120 lcdBiasOneThird = LCD_DISPCTRL_BIAS_ONETHIRD,
121 #if defined(LCD_DISPCTRL_BIAS_ONEFOURTH)
122 /** 1/4 Bias (5 levels). */
123 lcdBiasOneFourth = LCD_DISPCTRL_BIAS_ONEFOURTH,
124 #endif
125 } LCD_Bias_TypeDef;
126
127 #if defined(_SILICON_LABS_32B_SERIES_0)
128 /** VLCD Voltage Source. */
129 typedef enum {
130 /** VLCD Powered by VDD. */
131 lcdVLCDSelVDD = LCD_DISPCTRL_VLCDSEL_VDD,
132 /** VLCD Powered by external VDD / Voltage Boost. */
133 lcdVLCDSelVExtBoost = LCD_DISPCTRL_VLCDSEL_VEXTBOOST
134 } LCD_VLCDSel_TypeDef;
135 #endif
136
137 /** Contrast Configuration. */
138 #if defined(_SILICON_LABS_32B_SERIES_0)
139 typedef enum {
140 /** Contrast is adjusted relative to VDD (VLCD). */
141 lcdConConfVLCD = LCD_DISPCTRL_CONCONF_VLCD,
142 /** Contrast is adjusted relative to Ground. */
143 lcdConConfGND = LCD_DISPCTRL_CONCONF_GND
144 } LCD_ConConf_TypeDef;
145 #endif
146
147 #if defined(_SILICON_LABS_32B_SERIES_0)
148 /** Voltage Boost Level - Data sheets document setting for each part number. */
149 typedef enum {
150 lcdVBoostLevel0 = LCD_DISPCTRL_VBLEV_LEVEL0, /**< Voltage boost LEVEL0. */
151 lcdVBoostLevel1 = LCD_DISPCTRL_VBLEV_LEVEL1, /**< Voltage boost LEVEL1. */
152 lcdVBoostLevel2 = LCD_DISPCTRL_VBLEV_LEVEL2, /**< Voltage boost LEVEL2. */
153 lcdVBoostLevel3 = LCD_DISPCTRL_VBLEV_LEVEL3, /**< Voltage boost LEVEL3. */
154 lcdVBoostLevel4 = LCD_DISPCTRL_VBLEV_LEVEL4, /**< Voltage boost LEVEL4. */
155 lcdVBoostLevel5 = LCD_DISPCTRL_VBLEV_LEVEL5, /**< Voltage boost LEVEL5. */
156 lcdVBoostLevel6 = LCD_DISPCTRL_VBLEV_LEVEL6, /**< Voltage boost LEVEL6. */
157 lcdVBoostLevel7 = LCD_DISPCTRL_VBLEV_LEVEL7 /**< Voltage boost LEVEL7. */
158 } LCD_VBoostLevel_TypeDef;
159 #endif
160
161 #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2)
162 /** Mode of operation. */
163 typedef enum {
164 #if defined(_SILICON_LABS_32B_SERIES_1)
165 lcdModeNoExtCap = LCD_DISPCTRL_MODE_NOEXTCAP, /**< No external capacitor. */
166 lcdModeStepDown = LCD_DISPCTRL_MODE_STEPDOWN, /**< External cap with resistor string. */
167 lcdModeCpIntOsc = LCD_DISPCTRL_MODE_CPINTOSC, /**< External cap and internal oscillator. */
168 #elif defined(_SILICON_LABS_32B_SERIES_2)
169 lcdModeStepDown = LCD_BIASCTRL_MODE_STEPDOWN, /**< External cap with resistor string. */
170 lcdModeChargePump = LCD_BIASCTRL_MODE_CHARGEPUMP, /**< External cap and internal oscillator. */
171 #endif
172 } LCD_Mode_Typedef;
173 #endif
174
175 /** Frame Counter Clock Prescaler, FC-CLK = FrameRate (Hz) / this factor. */
176 typedef enum {
177 #if defined(_SILICON_LABS_32B_SERIES_2)
178 /** Prescale Div 1. */
179 lcdFCPrescDiv1 = LCD_BACFG_FCPRESC_DIV1,
180 /** Prescale Div 2. */
181 lcdFCPrescDiv2 = LCD_BACFG_FCPRESC_DIV2,
182 /** Prescale Div 4. */
183 lcdFCPrescDiv4 = LCD_BACFG_FCPRESC_DIV4,
184 /** Prescale Div 8. */
185 lcdFCPrescDiv8 = LCD_BACFG_FCPRESC_DIV8
186 #else
187 /** Prescale Div 1. */
188 lcdFCPrescDiv1 = LCD_BACTRL_FCPRESC_DIV1,
189 /** Prescale Div 2. */
190 lcdFCPrescDiv2 = LCD_BACTRL_FCPRESC_DIV2,
191 /** Prescale Div 4. */
192 lcdFCPrescDiv4 = LCD_BACTRL_FCPRESC_DIV4,
193 /** Prescale Div 8. */
194 lcdFCPrescDiv8 = LCD_BACTRL_FCPRESC_DIV8
195 #endif
196 } LCD_FCPreScale_TypeDef;
197
198 #if defined(_SILICON_LABS_32B_SERIES_0)
199 /** Segment selection. */
200 typedef enum {
201 /** Select segment lines 0 to 3. */
202 lcdSegment0_3 = (1 << 0),
203 /** Select segment lines 4 to 7. */
204 lcdSegment4_7 = (1 << 1),
205 /** Select segment lines 8 to 11. */
206 lcdSegment8_11 = (1 << 2),
207 /** Select segment lines 12 to 15. */
208 lcdSegment12_15 = (1 << 3),
209 /** Select segment lines 16 to 19. */
210 lcdSegment16_19 = (1 << 4),
211 /** Select segment lines 20 to 23. */
212 lcdSegment20_23 = (1 << 5),
213 #if defined(_LCD_SEGD0L_MASK) && (_LCD_SEGD0L_MASK == 0x00FFFFFFUL)
214 /** Select all segment lines. */
215 lcdSegmentAll = (0x003f)
216 #elif defined(_LCD_SEGD0H_MASK) && (_LCD_SEGD0H_MASK == 0x000000FFUL)
217 /** Select segment lines 24 to 27. */
218 lcdSegment24_27 = (1 << 6),
219 /** Select segment lines 28 to 31. */
220 lcdSegment28_31 = (1 << 7),
221 /** Select segment lines 32 to 35. */
222 lcdSegment32_35 = (1 << 8),
223 /** Select segment lines 36 to 39. */
224 lcdSegment36_39 = (1 << 9),
225 /** Select all segment lines. */
226 lcdSegmentAll = (0x03ff)
227 #endif
228 } LCD_SegmentRange_TypeDef;
229 #endif
230
231 /** Update Data Control. */
232 typedef enum {
233 /** Regular update, data transfer done immediately. */
234 lcdUpdateCtrlRegular = LCD_CTRL_UDCTRL_REGULAR,
235 /** Data transfer done at Frame Counter event. */
236 lcdUpdateCtrlFCEvent = LCD_CTRL_UDCTRL_FCEVENT,
237 /** Data transfer done at Frame Start. */
238 lcdUpdateCtrlFrameStart = LCD_CTRL_UDCTRL_FRAMESTART,
239 #if defined(_SILICON_LABS_32B_SERIES_2)
240 /** Data transfer done at Display Counter event. */
241 lcdUpdateCtrlDisplayEvent = LCD_CTRL_UDCTRL_DISPLAYEVENT
242 #endif
243 } LCD_UpdateCtrl_TypeDef;
244
245 #if defined(_SILICON_LABS_32B_SERIES_2)
246 /** Auto Load address which will start the synchronization from CLK_BUS to CLK_PER. */
247 typedef enum {
248 /** Starts synchronizing registers after a write to BACTRL. */
249 lcdLoadAddrNone = 0,
250 /** Starts synchronizing registers after a write to BACTRL. */
251 lcdLoadAddrBactrl = LCD_UPDATECTRL_LOADADDR_BACTRLWR,
252 /** Starts synchronizing registers after a write to AREGA. */
253 lcdLoadAddrAregA = LCD_UPDATECTRL_LOADADDR_AREGAWR,
254 /** Starts synchronizing registers after a write to AREGB. */
255 lcdLoadAddrAregB = LCD_UPDATECTRL_LOADADDR_AREGBWR,
256 /** Starts synchronizing registers after a write to SEGD0. */
257 lcdLoadAddrSegd0 = LCD_UPDATECTRL_LOADADDR_SEGD0WR,
258 /** Starts synchronizing registers after a write to SEGD1. */
259 lcdLoadAddrSegd1 = LCD_UPDATECTRL_LOADADDR_SEGD1WR,
260 /** Starts synchronizing registers after a write to SEGD2. */
261 lcdLoadAddrSegd2 = LCD_UPDATECTRL_LOADADDR_SEGD2WR,
262 /** Starts synchronizing registers after a write to SEGD3. */
263 lcdLoadAddrSegd3 = LCD_UPDATECTRL_LOADADDR_SEGD3WR,
264 #if defined(LCD_UPDATECTRL_LOADADDR_SEGD4WR)
265 /** Starts synchronizing registers after a write to SEGD4. */
266 lcdLoadAddrSegd4 = LCD_UPDATECTRL_LOADADDR_SEGD4WR,
267 #endif
268 #if defined(LCD_UPDATECTRL_LOADADDR_SEGD5WR)
269 /** Starts synchronizing registers after a write to SEGD5. */
270 lcdLoadAddrSegd5 = LCD_UPDATECTRL_LOADADDR_SEGD5WR,
271 #endif
272 #if defined(LCD_UPDATECTRL_LOADADDR_SEGD6WR)
273 /** Starts synchronizing registers after a write to SEGD6. */
274 lcdLoadAddrSegd6 = LCD_UPDATECTRL_LOADADDR_SEGD6WR,
275 #endif
276 #if defined(LCD_UPDATECTRL_LOADADDR_SEGD7WR)
277 /** Starts synchronizing registers after a write to SEGD7. */
278 lcdLoadAddrSegd7 = LCD_UPDATECTRL_LOADADDR_SEGD7WR,
279 #endif
280 } LCD_LoadAddr_TypeDef;
281 #endif
282
283 /** Animation Shift operation; none, left or right. */
284 typedef enum {
285 /** No shift. */
286 lcdAnimShiftNone = _LCD_BACTRL_AREGASC_NOSHIFT,
287 /** Shift segment bits left. */
288 lcdAnimShiftLeft = _LCD_BACTRL_AREGASC_SHIFTLEFT,
289 /** Shift segment bits right. */
290 lcdAnimShiftRight = _LCD_BACTRL_AREGASC_SHIFTRIGHT
291 } LCD_AnimShift_TypeDef;
292
293 /** Animation Logic Control, how AReg and BReg should be combined. */
294 typedef enum {
295 /** Use bitwise logic AND to mix animation register A (AREGA) and B (AREGB). */
296 lcdAnimLogicAnd = LCD_BACTRL_ALOGSEL_AND,
297 /** Use bitwise logic OR to mix animation register A (AREGA) and B (AREGB). */
298 lcdAnimLogicOr = LCD_BACTRL_ALOGSEL_OR
299 } LCD_AnimLogic_TypeDef;
300
301 #if defined(_LCD_BACTRL_ALOC_MASK)
302 /** Animation Location, set the LCD segments which animation applies to. */
303 typedef enum {
304 /** Animation appears on segments 0 to 7. */
305 lcdAnimLocSeg0To7 = LCD_BACTRL_ALOC_SEG0TO7,
306 /** Animation appears on segments 8 to 15. */
307 lcdAnimLocSeg8To15 = LCD_BACTRL_ALOC_SEG8TO15
308 } LCD_AnimLoc_TypeDef;
309 #endif
310
311 #if defined(_LCD_DISPCTRL_CHGRDST_MASK)
312 /** Charge redistribution control. */
313 typedef enum {
314 /** Disable charge redistribution. */
315 lcdChargeRedistributionDisable = LCD_DISPCTRL_CHGRDST_DISABLE,
316 /** Use 1 prescaled low frequency clock cycle for charge redistribution. */
317 lcdChargeRedistributionEnable = LCD_DISPCTRL_CHGRDST_ONE,
318 /** Use 2 prescaled low frequency clock cycle for charge redistribution. */
319 lcdChargeRedistributionTwoCycle = LCD_DISPCTRL_CHGRDST_TWO,
320 /** Use 3 prescaled low frequency clock cycle for charge redistribution. */
321 lcdChargeRedistributionThreeCycle = LCD_DISPCTRL_CHGRDST_THREE,
322 /** Use 4 prescaled low frequency clock cycle for charge redistribution. */
323 lcdChargeRedistributionFourCycle = LCD_DISPCTRL_CHGRDST_FOUR
324 } LCD_ChargeRedistribution_TypeDef;
325 #endif
326
327 #if defined(_SILICON_LABS_32B_SERIES_2)
328 /** DMA mode of operation. */
329 typedef enum {
330 lcdDmaModeDisable = LCD_BIASCTRL_DMAMODE_DMADISABLE, /**< No DMA requests are generated. */
331 lcdDmaModeFrameCounterEvent = LCD_BIASCTRL_DMAMODE_DMAFC, /**< DMA request on frame counter event. */
332 lcdDmaModeDisplayEvent = LCD_BIASCTRL_DMAMODE_DMADISPLAY /**< DMA request on display counter event. */
333 } LCD_DmaMode_Typedef;
334 #endif
335
336 /*******************************************************************************
337 ******************************* STRUCTS ***********************************
338 ******************************************************************************/
339
340 /** LCD Animation Configuration. */
341 typedef struct {
342 /** Enable Animation at end of initialization. */
343 bool enable;
344 /** Initial Animation Register A Value. */
345 uint32_t AReg;
346 /** Shift operation of Animation Register A. */
347 LCD_AnimShift_TypeDef AShift;
348 /** Initial Animation Register B Value. */
349 uint32_t BReg;
350 /** Shift operation of Animation Register B. */
351 LCD_AnimShift_TypeDef BShift;
352 /** A and B Logical Operation to use for mixing and outputting resulting segments. */
353 LCD_AnimLogic_TypeDef animLogic;
354 #if defined(_LCD_BACTRL_ALOC_MASK)
355 /** Number of first segment to animate. */
356 LCD_AnimLoc_TypeDef startSeg;
357 #endif
358 } LCD_AnimInit_TypeDef;
359
360 /** LCD Frame Control Initialization. */
361 typedef struct {
362 /** Enable at end. */
363 bool enable;
364 /** Frame Counter top value. */
365 uint32_t top;
366 /** Frame Counter clock prescaler. */
367 LCD_FCPreScale_TypeDef prescale;
368 } LCD_FrameCountInit_TypeDef;
369
370 /** LCD Controller Initialization structure. */
371 typedef struct {
372 /** Enable controller at end of initialization. */
373 bool enable;
374 /** Mux configuration. */
375 LCD_Mux_TypeDef mux;
376 /** Bias configuration. */
377 LCD_Bias_TypeDef bias;
378 /** Wave configuration. */
379 LCD_Wave_TypeDef wave;
380 #if defined(_SILICON_LABS_32B_SERIES_0)
381 /** VLCD Select. */
382 LCD_VLCDSel_TypeDef vlcd;
383 /** Contrast Configuration. */
384 LCD_ConConf_TypeDef contrast;
385 #endif
386 #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2)
387 /** Mode of operation. */
388 LCD_Mode_Typedef mode;
389 /** Charge redistribution cycles. */
390 LCD_ChargeRedistribution_TypeDef chargeRedistribution;
391 /** Frame rate divider. */
392 uint8_t frameRateDivider;
393 /** Contrast level. */
394 int contrastLevel;
395 #if defined(_SILICON_LABS_32B_SERIES_2)
396 /** Clock Prescaler. */
397 uint32_t clockPrescaler;
398 #endif
399 #endif
400 } LCD_Init_TypeDef;
401
402 /** Default configuration for LCD initialization structure, enables 160 segments. */
403 #if defined(_SILICON_LABS_32B_SERIES_0)
404 #define LCD_INIT_DEFAULT \
405 { \
406 true, \
407 lcdMuxQuadruplex, \
408 lcdBiasOneThird, \
409 lcdWaveLowPower, \
410 lcdVLCDSelVDD, \
411 lcdConConfVLCD, \
412 }
413 #endif
414
415 #if defined(_SILICON_LABS_32B_SERIES_1)
416 #define LCD_INIT_DEFAULT \
417 { \
418 true, \
419 lcdMuxOctaplex, \
420 lcdBiasOneFourth, \
421 lcdWaveLowPower, \
422 lcdModeNoExtCap, \
423 lcdChargeRedistributionEnable, \
424 LCD_DEFAULT_FRAME_RATE_DIV, \
425 LCD_DEFAULT_CONTRAST \
426 }
427 #endif
428
429 #if defined(_SILICON_LABS_32B_SERIES_2)
430 #define LCD_INIT_DEFAULT \
431 { \
432 true, \
433 lcdMuxQuadruplex, \
434 lcdBiasOneFourth, \
435 lcdWaveLowPower, \
436 lcdModeStepDown, \
437 lcdChargeRedistributionEnable, \
438 LCD_DEFAULT_FRAME_RATE_DIV, \
439 LCD_DEFAULT_CONTRAST, \
440 LCD_DEFAULT_CLOCK_PRESCALER \
441 }
442 #endif
443
444 /*******************************************************************************
445 ***************************** PROTOTYPES **********************************
446 ******************************************************************************/
447
448 void LCD_Init(const LCD_Init_TypeDef *lcdInit);
449 #if defined(_SILICON_LABS_32B_SERIES_0)
450 void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd);
451 #endif
452 void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud);
453 void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit);
454 void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit);
455
456 #if defined(_SILICON_LABS_32B_SERIES_0)
457 void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segment, bool enable);
458 #endif
459 #if defined(_SILICON_LABS_32B_SERIES_2)
460 void LCD_SegmentEnable(uint32_t seg_nbr, bool enable);
461 void LCD_ComEnable(uint8_t com, bool enable);
462 void LCD_DmaModeSet(LCD_DmaMode_Typedef mode);
463 #endif
464 void LCD_SegmentSet(int com, int bit, bool enable);
465 void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits);
466 #if defined(_LCD_SEGD0H_MASK)
467 void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits);
468 #endif
469 void LCD_ContrastSet(int level);
470 void LCD_BiasSet(LCD_Bias_TypeDef bias);
471 #if defined(_SILICON_LABS_32B_SERIES_0)
472 void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost);
473 #endif
474 #if defined(LCD_CTRL_DSC)
475 void LCD_BiasSegmentSet(int segment, int biasLevel);
476 void LCD_BiasComSet(int com, int biasLevel);
477 #endif
478 #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2)
479 void LCD_ModeSet(LCD_Mode_Typedef mode);
480 void LCD_ChargeRedistributionCyclesSet(uint8_t cycles);
481 #endif
482
483 #if defined(_SILICON_LABS_32B_SERIES_2)
484 /***************************************************************************//**
485 * @brief
486 * Wait for load synchronization completion.
487 *
488 * @note
489 * Doing any writes to HV registers will not go through and will cause a
490 * bus fault.
491 ******************************************************************************/
LCD_LoadBusyWait(void)492 __STATIC_INLINE void LCD_LoadBusyWait(void)
493 {
494 while (LCD->STATUS & _LCD_STATUS_LOADBUSY_MASK) ;
495 }
496 #endif
497
498 #if defined(_SILICON_LABS_32B_SERIES_2)
499 /***************************************************************************//**
500 * @brief
501 * Wait for the LCD to complete resetting or disabling procedure.
502 ******************************************************************************/
LCD_ReadyWait(void)503 __STATIC_INLINE void LCD_ReadyWait(void)
504 {
505 while ((LCD->SWRST & _LCD_SWRST_RESETTING_MASK)
506 || (LCD->EN & _LCD_EN_DISABLING_MASK)
507 || (LCD->STATUS & _LCD_STATUS_LOADBUSY_MASK)) {
508 // Wait for all synchronizations to finish
509 }
510 }
511 #endif
512
513 /***************************************************************************//**
514 * @brief
515 * Enable or disable LCD controller.
516 *
517 * @param[in] enable
518 * If true, enables LCD controller with current configuration. If false,
519 * disables LCD controller. Enable CMU clock for LCD for correct
520 * operation.
521 ******************************************************************************/
LCD_Enable(bool enable)522 __STATIC_INLINE void LCD_Enable(bool enable)
523 {
524 #if defined(_SILICON_LABS_32B_SERIES_2)
525 if (enable) {
526 LCD->EN_SET = LCD_EN_EN;
527 } else {
528 /* Wait for internal synchronization completion. */
529 LCD_LoadBusyWait();
530
531 LCD->EN_CLR = LCD_EN_EN;
532 while (LCD->EN & _LCD_EN_DISABLING_MASK) {
533 }
534 }
535 #else
536
537 #if defined(LCD_HAS_SET_CLEAR)
538 if (enable) {
539 LCD->CTRL_SET = LCD_CTRL_EN;
540 } else {
541 LCD->CTRL_CLR = LCD_CTRL_EN;
542 }
543 #else
544 if (enable) {
545 LCD->CTRL |= LCD_CTRL_EN;
546 } else {
547 LCD->CTRL &= ~LCD_CTRL_EN;
548 }
549 #endif // LCD_HAS_SET_CLEAR
550
551 #endif // _SILICON_LABS_32B_SERIES_2
552 }
553
554 #if defined(_SILICON_LABS_32B_SERIES_2)
555 /***************************************************************************//**
556 * @brief
557 * Reset the LCD.
558 ******************************************************************************/
LCD_Reset(void)559 __STATIC_INLINE void LCD_Reset(void)
560 {
561 LCD->SWRST_SET = LCD_SWRST_SWRST;
562
563 /* Wait for reset to complete. */
564 while ((LCD->SWRST & _LCD_SWRST_RESETTING_MASK)) {
565 }
566 }
567 #endif
568
569 /***************************************************************************//**
570 * @brief
571 * Enable or disable LCD Animation feature.
572 *
573 * @param[in] enable
574 * Boolean true enables animation, false disables animation.
575 ******************************************************************************/
LCD_AnimEnable(bool enable)576 __STATIC_INLINE void LCD_AnimEnable(bool enable)
577 {
578 #if defined(LCD_HAS_SET_CLEAR)
579 if (enable) {
580 LCD->BACTRL_SET = LCD_BACTRL_AEN;
581 } else {
582 LCD->BACTRL_CLR = LCD_BACTRL_AEN;
583 }
584 #else
585 if (enable) {
586 LCD->BACTRL |= LCD_BACTRL_AEN;
587 } else {
588 LCD->BACTRL &= ~LCD_BACTRL_AEN;
589 }
590 #endif
591 }
592
593 /***************************************************************************//**
594 * @brief
595 * Enable or disable the LCD blink.
596 *
597 * @param[in] enable
598 * Boolean true enables blink, false disables blink.
599 ******************************************************************************/
LCD_BlinkEnable(bool enable)600 __STATIC_INLINE void LCD_BlinkEnable(bool enable)
601 {
602 #if defined(LCD_HAS_SET_CLEAR)
603 if (enable) {
604 LCD->BACTRL_SET = LCD_BACTRL_BLINKEN;
605 } else {
606 LCD->BACTRL_CLR = LCD_BACTRL_BLINKEN;
607 }
608 #else
609 if (enable) {
610 LCD->BACTRL |= LCD_BACTRL_BLINKEN;
611 } else {
612 LCD->BACTRL &= ~LCD_BACTRL_BLINKEN;
613 }
614 #endif
615 }
616
617 /***************************************************************************//**
618 * @brief
619 * Disable all segments while keeping segment state.
620 *
621 * @param[in] enable
622 * Boolean true clears all segments, boolean false restores all segment lines.
623 ******************************************************************************/
LCD_BlankEnable(bool enable)624 __STATIC_INLINE void LCD_BlankEnable(bool enable)
625 {
626 #if defined(LCD_HAS_SET_CLEAR)
627 if (enable) {
628 LCD->BACTRL_SET = LCD_BACTRL_BLANK;
629 } else {
630 LCD->BACTRL_CLR = LCD_BACTRL_BLANK;
631 }
632 #else
633 if (enable) {
634 LCD->BACTRL |= LCD_BACTRL_BLANK;
635 } else {
636 LCD->BACTRL &= ~LCD_BACTRL_BLANK;
637 }
638 #endif
639 }
640
641 /***************************************************************************//**
642 * @brief
643 * Enable or disable LCD Frame counter.
644 *
645 * @param[in] enable
646 * Boolean true enables frame counter, false disables frame counter.
647 ******************************************************************************/
LCD_FrameCountEnable(bool enable)648 __STATIC_INLINE void LCD_FrameCountEnable(bool enable)
649 {
650 #if defined(_SILICON_LABS_32B_SERIES_2)
651 /* Ensure no internal sync is in progress. */
652 LCD_LoadBusyWait();
653 #endif
654
655 #if defined(LCD_HAS_SET_CLEAR)
656 if (enable) {
657 LCD->BACTRL_SET = LCD_BACTRL_FCEN;
658 } else {
659 LCD->BACTRL_CLR = LCD_BACTRL_FCEN;
660 }
661 #else
662 if (enable) {
663 LCD->BACTRL |= LCD_BACTRL_FCEN;
664 } else {
665 LCD->BACTRL &= ~LCD_BACTRL_FCEN;
666 }
667 #endif
668 }
669
670 #if defined(_SILICON_LABS_32B_SERIES_2)
671 /***************************************************************************//**
672 * @brief
673 * Enable or disable the LCD Display counter.
674 *
675 * @param[in] enable
676 * Boolean true enables display counter, false disables display counter.
677 ******************************************************************************/
LCD_DisplayCountEnable(bool enable)678 __STATIC_INLINE void LCD_DisplayCountEnable(bool enable)
679 {
680 /* Ensure no internal sync is in progress. */
681 LCD_LoadBusyWait();
682
683 if (enable) {
684 LCD->BACTRL_SET = LCD_BACTRL_DISPLAYCNTEN;
685 } else {
686 LCD->BACTRL_CLR = LCD_BACTRL_DISPLAYCNTEN;
687 }
688 }
689 #endif
690
691 /***************************************************************************//**
692 * @brief
693 * Return the current animation state.
694 *
695 * @return
696 * Animation state, in range 0-15.
697 ******************************************************************************/
LCD_AnimState(void)698 __STATIC_INLINE int LCD_AnimState(void)
699 {
700 return (int)(LCD->STATUS & _LCD_STATUS_ASTATE_MASK) >> _LCD_STATUS_ASTATE_SHIFT;
701 }
702
703 /***************************************************************************//**
704 * @brief
705 * Return the current blink state.
706 *
707 * @return
708 * Return value is 1 if segments are enabled, 0 if disabled.
709 ******************************************************************************/
LCD_BlinkState(void)710 __STATIC_INLINE int LCD_BlinkState(void)
711 {
712 return (int)(LCD->STATUS & _LCD_STATUS_BLINK_MASK) >> _LCD_STATUS_BLINK_SHIFT;
713 }
714
715 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
716 /***************************************************************************//**
717 * @brief
718 * When set, LCD registers will not be updated until cleared.
719 *
720 * @param[in] enable
721 * When enable is true, update is stopped; when false, all registers are
722 * updated.
723 ******************************************************************************/
LCD_FreezeEnable(bool enable)724 __STATIC_INLINE void LCD_FreezeEnable(bool enable)
725 {
726 if (enable) {
727 LCD->FREEZE = LCD_FREEZE_REGFREEZE_FREEZE;
728 } else {
729 LCD->FREEZE = LCD_FREEZE_REGFREEZE_UPDATE;
730 }
731 }
732 #endif
733
734 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
735 /***************************************************************************//**
736 * @brief
737 * Return SYNCBUSY bits, indicating which registers have pending updates.
738 *
739 * @return
740 * Bit fields for LCD registers that have pending updates.
741 ******************************************************************************/
LCD_SyncBusyGet(void)742 __STATIC_INLINE uint32_t LCD_SyncBusyGet(void)
743 {
744 return LCD->SYNCBUSY;
745 }
746 #endif
747
748 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
749 /***************************************************************************//**
750 * @brief
751 * Poll LCD SYNCBUSY flags until the flag has been cleared.
752 *
753 * @param[in] flags
754 * Bit fields for LCD registers that will be updated before we continue.
755 ******************************************************************************/
LCD_SyncBusyDelay(uint32_t flags)756 __STATIC_INLINE void LCD_SyncBusyDelay(uint32_t flags)
757 {
758 while (LCD->SYNCBUSY & flags) ;
759 }
760 #endif
761
762 #if defined(_SILICON_LABS_32B_SERIES_2)
763 /***************************************************************************//**
764 * @brief
765 * Start the synchronization process.
766 *
767 * @param[in] autoload
768 * Flag indicating if the synchronization is started manually with CMD.LOAD
769 * (false) or if the synchronization is managed automatically by Auto Load
770 * (true).
771 *
772 * @param[in] load_addr
773 * Address which will start the synchronization from CLK_BUS to CLK_PER
774 * when Auto Load is selected. This argument has no effect if 'autoload' is
775 * false.
776 ******************************************************************************/
LCD_SyncStart(bool autoload,LCD_LoadAddr_TypeDef load_addr)777 __STATIC_INLINE void LCD_SyncStart(bool autoload, LCD_LoadAddr_TypeDef load_addr)
778 {
779 /* Ensure no synchronization in progress. */
780 LCD_LoadBusyWait();
781
782 if (autoload) {
783 LCD_Enable(false); /* Ensure LCD disabled before writing WSTATIC fields. */
784 LCD_ReadyWait();
785 LCD->UPDATECTRL_CLR = _LCD_UPDATECTRL_LOADADDR_MASK;
786 LCD->UPDATECTRL |= load_addr;
787 LCD->UPDATECTRL_SET = LCD_UPDATECTRL_AUTOLOAD;
788 LCD_Enable(true);
789 } else {
790 /* Start synchronization from HV registers to CLK_PER domain. */
791 LCD->CMD = LCD_CMD_LOAD;
792 }
793 }
794 #endif
795
796 #if defined(_SILICON_LABS_32B_SERIES_2)
797 /***************************************************************************//**
798 * @brief
799 * Stop the synchronization process.
800 *
801 * @param[in] autoload
802 * Flag indicating if the synchronization is stopped manually with CMD.CLEAR
803 * (false) or if the synchronization managed by Auto Load is disabled (true).
804 ******************************************************************************/
LCD_SyncStop(bool autoload)805 __STATIC_INLINE void LCD_SyncStop(bool autoload)
806 {
807 if (autoload) {
808 /* Autoload cannot be disabled if synchronization in progress. */
809 LCD_LoadBusyWait();
810
811 LCD->UPDATECTRL_CLR = LCD_UPDATECTRL_AUTOLOAD;
812 LCD->UPDATECTRL_CLR = _LCD_UPDATECTRL_LOADADDR_MASK;
813 } else {
814 LCD->CMD = LCD_CMD_CLEAR;
815 }
816 }
817 #endif
818
819 /***************************************************************************//**
820 * @brief
821 * Get pending LCD interrupt flags.
822 *
823 * @return
824 * Pending LCD interrupt sources. Returns a set of interrupt flags OR-ed
825 * together for multiple interrupt sources in the LCD module (LCD_IFS_nnn).
826 ******************************************************************************/
LCD_IntGet(void)827 __STATIC_INLINE uint32_t LCD_IntGet(void)
828 {
829 return LCD->IF;
830 }
831
832 /***************************************************************************//**
833 * @brief
834 * Get enabled and pending LCD interrupt flags.
835 *
836 * @details
837 * Useful for handling more interrupt sources in the same interrupt handler.
838 *
839 * @note
840 * Event bits are not cleared by the use of this function.
841 *
842 * @return
843 * Pending and enabled LCD interrupt sources.
844 * Return value is the bitwise AND combination of
845 * - the OR combination of enabled interrupt sources in LCD_IEN_nnn
846 * register (LCD_IEN_nnn) and
847 * - the bitwise OR combination of valid interrupt flags of LCD module
848 * (LCD_IF_nnn).
849 ******************************************************************************/
LCD_IntGetEnabled(void)850 __STATIC_INLINE uint32_t LCD_IntGetEnabled(void)
851 {
852 uint32_t ien;
853
854 /* Store the LCD->IEN in temporary variable to define the explicit order
855 * of volatile accesses. */
856 ien = LCD->IEN;
857
858 /* Bitwise AND of pending and enabled interrupts */
859 return LCD->IF & ien;
860 }
861
862 /***************************************************************************//**
863 * @brief
864 * Set one or more pending LCD interrupts from SW.
865 *
866 * @param[in] flags
867 * LCD interrupt sources to set to pending. Use a set of interrupt flags
868 * OR-ed together to set multiple interrupt sources for the LCD module
869 * (LCD_IFS_nnn).
870 ******************************************************************************/
LCD_IntSet(uint32_t flags)871 __STATIC_INLINE void LCD_IntSet(uint32_t flags)
872 {
873 #if defined(_SILICON_LABS_32B_SERIES_2)
874 #if defined(LCD_HAS_SET_CLEAR)
875 LCD->IF_SET = flags;
876 #else
877 LCD->IF |= flags;
878 #endif // LCD_HAS_SET_CLEAR
879 #else
880 LCD->IFS = flags;
881 #endif
882 }
883
884 /***************************************************************************//**
885 * @brief
886 * Enable LCD interrupts.
887 *
888 * @param[in] flags
889 * LCD interrupt sources to enable. Use a set of interrupt flags OR-ed
890 * together to set multiple interrupt sources for LCD module
891 * (LCD_IFS_nnn).
892 ******************************************************************************/
LCD_IntEnable(uint32_t flags)893 __STATIC_INLINE void LCD_IntEnable(uint32_t flags)
894 {
895 #if defined(LCD_HAS_SET_CLEAR)
896 LCD->IEN_SET = flags;
897 #else
898 LCD->IEN |= flags;
899 #endif
900 }
901
902 /***************************************************************************//**
903 * @brief
904 * Disable LCD interrupts.
905 *
906 * @param[in] flags
907 * LCD interrupt sources to disable. Use a set of interrupt flags OR-ed
908 * together to disable multiple interrupt sources for LCD module
909 * (LCD_IFS_nnn).
910 ******************************************************************************/
LCD_IntDisable(uint32_t flags)911 __STATIC_INLINE void LCD_IntDisable(uint32_t flags)
912 {
913 #if defined(LCD_HAS_SET_CLEAR)
914 LCD->IEN_CLR = flags;
915 #else
916 LCD->IEN &= ~flags;
917 #endif
918 }
919
920 /***************************************************************************//**
921 * @brief
922 * Clear one or more interrupt flags.
923 *
924 * @param[in] flags
925 * LCD interrupt sources to clear. Use a set of interrupt flags OR-ed
926 * together to clear multiple interrupt sources for LCD module
927 * (LCD_IFS_nnn).
928 ******************************************************************************/
LCD_IntClear(uint32_t flags)929 __STATIC_INLINE void LCD_IntClear(uint32_t flags)
930 {
931 #if defined(_SILICON_LABS_32B_SERIES_2)
932 #if defined(LCD_HAS_SET_CLEAR)
933 LCD->IF_CLR = flags;
934 #else
935 LCD->IF &= ~flags;
936 #endif // LCD_HAS_SET_CLEAR
937 #else
938 LCD->IFC = flags;
939 #endif
940 }
941
942 #if defined(LCD_CTRL_DSC)
943 /***************************************************************************//**
944 * @brief
945 * Enable or disable LCD Direct Segment Control.
946 *
947 * @param[in] enable
948 * If true, enables LCD controller Direct Segment Control
949 * Segment and COM line bias levels need to be set explicitly with
950 * LCD_BiasSegmentSet() and LCD_BiasComSet() function calls respectively.
951 ******************************************************************************/
LCD_DSCEnable(bool enable)952 __STATIC_INLINE void LCD_DSCEnable(bool enable)
953 {
954 #if defined(_SILICON_LABS_32B_SERIES_2)
955 LCD_Enable(false); /* Ensure LCD disabled before writing WSTATIC fields. */
956 LCD_ReadyWait();
957 #endif
958
959 #if defined(LCD_HAS_SET_CLEAR)
960 if (enable) {
961 LCD->CTRL_SET = LCD_CTRL_DSC;
962 } else {
963 LCD->CTRL_CLR = LCD_CTRL_DSC;
964 }
965 #else
966 if (enable) {
967 LCD->CTRL |= LCD_CTRL_DSC;
968 } else {
969 LCD->CTRL &= ~LCD_CTRL_DSC;
970 }
971 #endif
972
973 #if defined(_SILICON_LABS_32B_SERIES_2)
974 LCD_Enable(true);
975 #endif
976 }
977
978 #endif
979
980 /** @} (end addtogroup lcd) */
981
982 #ifdef __cplusplus
983 }
984 #endif
985
986 #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */
987
988 #endif /* EM_LCD_H */
989