/***************************************************************************//** * @file * @brief Liquid Crystal Display (LCD) peripheral API ******************************************************************************* * # License * Copyright 2018 Silicon Laboratories Inc. www.silabs.com ******************************************************************************* * * SPDX-License-Identifier: Zlib * * The licensor of this software is Silicon Laboratories Inc. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * ******************************************************************************/ #ifndef EM_LCD_H #define EM_LCD_H #include "em_device.h" #if defined(LCD_COUNT) && (LCD_COUNT > 0) #include #include #ifdef __cplusplus extern "C" { #endif /***************************************************************************//** * @addtogroup lcd * @{ ******************************************************************************/ /******************************************************************************* ******************************** DEFINES ********************************** ******************************************************************************/ /** Default Clock Prescaler. */ #define LCD_DEFAULT_CLOCK_PRESCALER 64 /** Default LCD Frame Rate Divisor. */ #define LCD_DEFAULT_FRAME_RATE_DIV 4 /** Default LCD Contrast. */ #define LCD_DEFAULT_CONTRAST 15 #if defined(_SILICON_LABS_32B_SERIES_2) /** Maximum common lines of LCD. */ #if defined(LCD_OCTAPLEX) && (LCD_OCTAPLEX == 1) #define LCD_COM_LINES_MAX (LCD_COM_NUM + LCD_SEGASCOM_NUM) #else #define LCD_COM_LINES_MAX LCD_COM_NUM #endif /** Maximum segment lines of LCD. */ #define LCD_SEGMENT_LINES_MAX LCD_SEG_NUM #endif /******************************************************************************* ******************************** ENUMS ************************************ ******************************************************************************/ /** MUX setting. */ typedef enum { /** Static (segments can be multiplexed with LCD_COM[0]). */ lcdMuxStatic = LCD_DISPCTRL_MUX_STATIC, /** Duplex / 1/2 Duty cycle (segments can be multiplexed with LCD_COM[0:1]). */ lcdMuxDuplex = LCD_DISPCTRL_MUX_DUPLEX, /** Triplex / 1/3 Duty cycle (segments can be multiplexed with LCD_COM[0:2]). */ lcdMuxTriplex = LCD_DISPCTRL_MUX_TRIPLEX, /** Quadruplex / 1/4 Duty cycle (segments can be multiplexed with LCD_COM[0:3]). */ lcdMuxQuadruplex = LCD_DISPCTRL_MUX_QUADRUPLEX, #if defined(LCD_DISPCTRL_MUXE_MUXE) /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]). */ lcdMuxSextaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_DUPLEX, /** Octaplex / 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]). */ lcdMuxOctaplex = LCD_DISPCTRL_MUXE_MUXE | LCD_DISPCTRL_MUX_QUADRUPLEX #elif defined(LCD_DISPCTRL_MUX_SEXTAPLEX) /** Sextaplex / 1/6 Duty cycle (segments can be multiplexed with LCD_COM[0:5]). */ lcdMuxSextaplex = LCD_DISPCTRL_MUX_SEXTAPLEX, /** Octaplex / 1/8 Duty cycle (segments can be multiplexed with LCD_COM[0:7]). */ lcdMuxOctaplex = LCD_DISPCTRL_MUX_OCTAPLEX, #endif } LCD_Mux_TypeDef; /** Wave type. */ typedef enum { #if defined(_SILICON_LABS_32B_SERIES_2) /** Low power optimized waveform output. */ lcdWaveLowPower = LCD_DISPCTRL_WAVE_TYPEB, /** Regular waveform output */ lcdWaveNormal = LCD_DISPCTRL_WAVE_TYPEA #else /** Low power optimized waveform output. */ lcdWaveLowPower = LCD_DISPCTRL_WAVE_LOWPOWER, /** Regular waveform output */ lcdWaveNormal = LCD_DISPCTRL_WAVE_NORMAL #endif } LCD_Wave_TypeDef; /** Bias setting. */ typedef enum { /** Static (2 levels). */ lcdBiasStatic = LCD_DISPCTRL_BIAS_STATIC, /** 1/2 Bias (3 levels). */ lcdBiasOneHalf = LCD_DISPCTRL_BIAS_ONEHALF, /** 1/3 Bias (4 levels). */ lcdBiasOneThird = LCD_DISPCTRL_BIAS_ONETHIRD, #if defined(LCD_DISPCTRL_BIAS_ONEFOURTH) /** 1/4 Bias (5 levels). */ lcdBiasOneFourth = LCD_DISPCTRL_BIAS_ONEFOURTH, #endif } LCD_Bias_TypeDef; #if defined(_SILICON_LABS_32B_SERIES_0) /** VLCD Voltage Source. */ typedef enum { /** VLCD Powered by VDD. */ lcdVLCDSelVDD = LCD_DISPCTRL_VLCDSEL_VDD, /** VLCD Powered by external VDD / Voltage Boost. */ lcdVLCDSelVExtBoost = LCD_DISPCTRL_VLCDSEL_VEXTBOOST } LCD_VLCDSel_TypeDef; #endif /** Contrast Configuration. */ #if defined(_SILICON_LABS_32B_SERIES_0) typedef enum { /** Contrast is adjusted relative to VDD (VLCD). */ lcdConConfVLCD = LCD_DISPCTRL_CONCONF_VLCD, /** Contrast is adjusted relative to Ground. */ lcdConConfGND = LCD_DISPCTRL_CONCONF_GND } LCD_ConConf_TypeDef; #endif #if defined(_SILICON_LABS_32B_SERIES_0) /** Voltage Boost Level - Data sheets document setting for each part number. */ typedef enum { lcdVBoostLevel0 = LCD_DISPCTRL_VBLEV_LEVEL0, /**< Voltage boost LEVEL0. */ lcdVBoostLevel1 = LCD_DISPCTRL_VBLEV_LEVEL1, /**< Voltage boost LEVEL1. */ lcdVBoostLevel2 = LCD_DISPCTRL_VBLEV_LEVEL2, /**< Voltage boost LEVEL2. */ lcdVBoostLevel3 = LCD_DISPCTRL_VBLEV_LEVEL3, /**< Voltage boost LEVEL3. */ lcdVBoostLevel4 = LCD_DISPCTRL_VBLEV_LEVEL4, /**< Voltage boost LEVEL4. */ lcdVBoostLevel5 = LCD_DISPCTRL_VBLEV_LEVEL5, /**< Voltage boost LEVEL5. */ lcdVBoostLevel6 = LCD_DISPCTRL_VBLEV_LEVEL6, /**< Voltage boost LEVEL6. */ lcdVBoostLevel7 = LCD_DISPCTRL_VBLEV_LEVEL7 /**< Voltage boost LEVEL7. */ } LCD_VBoostLevel_TypeDef; #endif #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2) /** Mode of operation. */ typedef enum { #if defined(_SILICON_LABS_32B_SERIES_1) lcdModeNoExtCap = LCD_DISPCTRL_MODE_NOEXTCAP, /**< No external capacitor. */ lcdModeStepDown = LCD_DISPCTRL_MODE_STEPDOWN, /**< External cap with resistor string. */ lcdModeCpIntOsc = LCD_DISPCTRL_MODE_CPINTOSC, /**< External cap and internal oscillator. */ #elif defined(_SILICON_LABS_32B_SERIES_2) lcdModeStepDown = LCD_BIASCTRL_MODE_STEPDOWN, /**< External cap with resistor string. */ lcdModeChargePump = LCD_BIASCTRL_MODE_CHARGEPUMP, /**< External cap and internal oscillator. */ #endif } LCD_Mode_Typedef; #endif /** Frame Counter Clock Prescaler, FC-CLK = FrameRate (Hz) / this factor. */ typedef enum { #if defined(_SILICON_LABS_32B_SERIES_2) /** Prescale Div 1. */ lcdFCPrescDiv1 = LCD_BACFG_FCPRESC_DIV1, /** Prescale Div 2. */ lcdFCPrescDiv2 = LCD_BACFG_FCPRESC_DIV2, /** Prescale Div 4. */ lcdFCPrescDiv4 = LCD_BACFG_FCPRESC_DIV4, /** Prescale Div 8. */ lcdFCPrescDiv8 = LCD_BACFG_FCPRESC_DIV8 #else /** Prescale Div 1. */ lcdFCPrescDiv1 = LCD_BACTRL_FCPRESC_DIV1, /** Prescale Div 2. */ lcdFCPrescDiv2 = LCD_BACTRL_FCPRESC_DIV2, /** Prescale Div 4. */ lcdFCPrescDiv4 = LCD_BACTRL_FCPRESC_DIV4, /** Prescale Div 8. */ lcdFCPrescDiv8 = LCD_BACTRL_FCPRESC_DIV8 #endif } LCD_FCPreScale_TypeDef; #if defined(_SILICON_LABS_32B_SERIES_0) /** Segment selection. */ typedef enum { /** Select segment lines 0 to 3. */ lcdSegment0_3 = (1 << 0), /** Select segment lines 4 to 7. */ lcdSegment4_7 = (1 << 1), /** Select segment lines 8 to 11. */ lcdSegment8_11 = (1 << 2), /** Select segment lines 12 to 15. */ lcdSegment12_15 = (1 << 3), /** Select segment lines 16 to 19. */ lcdSegment16_19 = (1 << 4), /** Select segment lines 20 to 23. */ lcdSegment20_23 = (1 << 5), #if defined(_LCD_SEGD0L_MASK) && (_LCD_SEGD0L_MASK == 0x00FFFFFFUL) /** Select all segment lines. */ lcdSegmentAll = (0x003f) #elif defined(_LCD_SEGD0H_MASK) && (_LCD_SEGD0H_MASK == 0x000000FFUL) /** Select segment lines 24 to 27. */ lcdSegment24_27 = (1 << 6), /** Select segment lines 28 to 31. */ lcdSegment28_31 = (1 << 7), /** Select segment lines 32 to 35. */ lcdSegment32_35 = (1 << 8), /** Select segment lines 36 to 39. */ lcdSegment36_39 = (1 << 9), /** Select all segment lines. */ lcdSegmentAll = (0x03ff) #endif } LCD_SegmentRange_TypeDef; #endif /** Update Data Control. */ typedef enum { /** Regular update, data transfer done immediately. */ lcdUpdateCtrlRegular = LCD_CTRL_UDCTRL_REGULAR, /** Data transfer done at Frame Counter event. */ lcdUpdateCtrlFCEvent = LCD_CTRL_UDCTRL_FCEVENT, /** Data transfer done at Frame Start. */ lcdUpdateCtrlFrameStart = LCD_CTRL_UDCTRL_FRAMESTART, #if defined(_SILICON_LABS_32B_SERIES_2) /** Data transfer done at Display Counter event. */ lcdUpdateCtrlDisplayEvent = LCD_CTRL_UDCTRL_DISPLAYEVENT #endif } LCD_UpdateCtrl_TypeDef; #if defined(_SILICON_LABS_32B_SERIES_2) /** Auto Load address which will start the synchronization from CLK_BUS to CLK_PER. */ typedef enum { /** Starts synchronizing registers after a write to BACTRL. */ lcdLoadAddrNone = 0, /** Starts synchronizing registers after a write to BACTRL. */ lcdLoadAddrBactrl = LCD_UPDATECTRL_LOADADDR_BACTRLWR, /** Starts synchronizing registers after a write to AREGA. */ lcdLoadAddrAregA = LCD_UPDATECTRL_LOADADDR_AREGAWR, /** Starts synchronizing registers after a write to AREGB. */ lcdLoadAddrAregB = LCD_UPDATECTRL_LOADADDR_AREGBWR, /** Starts synchronizing registers after a write to SEGD0. */ lcdLoadAddrSegd0 = LCD_UPDATECTRL_LOADADDR_SEGD0WR, /** Starts synchronizing registers after a write to SEGD1. */ lcdLoadAddrSegd1 = LCD_UPDATECTRL_LOADADDR_SEGD1WR, /** Starts synchronizing registers after a write to SEGD2. */ lcdLoadAddrSegd2 = LCD_UPDATECTRL_LOADADDR_SEGD2WR, /** Starts synchronizing registers after a write to SEGD3. */ lcdLoadAddrSegd3 = LCD_UPDATECTRL_LOADADDR_SEGD3WR, #if defined(LCD_UPDATECTRL_LOADADDR_SEGD4WR) /** Starts synchronizing registers after a write to SEGD4. */ lcdLoadAddrSegd4 = LCD_UPDATECTRL_LOADADDR_SEGD4WR, #endif #if defined(LCD_UPDATECTRL_LOADADDR_SEGD5WR) /** Starts synchronizing registers after a write to SEGD5. */ lcdLoadAddrSegd5 = LCD_UPDATECTRL_LOADADDR_SEGD5WR, #endif #if defined(LCD_UPDATECTRL_LOADADDR_SEGD6WR) /** Starts synchronizing registers after a write to SEGD6. */ lcdLoadAddrSegd6 = LCD_UPDATECTRL_LOADADDR_SEGD6WR, #endif #if defined(LCD_UPDATECTRL_LOADADDR_SEGD7WR) /** Starts synchronizing registers after a write to SEGD7. */ lcdLoadAddrSegd7 = LCD_UPDATECTRL_LOADADDR_SEGD7WR, #endif } LCD_LoadAddr_TypeDef; #endif /** Animation Shift operation; none, left or right. */ typedef enum { /** No shift. */ lcdAnimShiftNone = _LCD_BACTRL_AREGASC_NOSHIFT, /** Shift segment bits left. */ lcdAnimShiftLeft = _LCD_BACTRL_AREGASC_SHIFTLEFT, /** Shift segment bits right. */ lcdAnimShiftRight = _LCD_BACTRL_AREGASC_SHIFTRIGHT } LCD_AnimShift_TypeDef; /** Animation Logic Control, how AReg and BReg should be combined. */ typedef enum { /** Use bitwise logic AND to mix animation register A (AREGA) and B (AREGB). */ lcdAnimLogicAnd = LCD_BACTRL_ALOGSEL_AND, /** Use bitwise logic OR to mix animation register A (AREGA) and B (AREGB). */ lcdAnimLogicOr = LCD_BACTRL_ALOGSEL_OR } LCD_AnimLogic_TypeDef; #if defined(_LCD_BACTRL_ALOC_MASK) /** Animation Location, set the LCD segments which animation applies to. */ typedef enum { /** Animation appears on segments 0 to 7. */ lcdAnimLocSeg0To7 = LCD_BACTRL_ALOC_SEG0TO7, /** Animation appears on segments 8 to 15. */ lcdAnimLocSeg8To15 = LCD_BACTRL_ALOC_SEG8TO15 } LCD_AnimLoc_TypeDef; #endif #if defined(_LCD_DISPCTRL_CHGRDST_MASK) /** Charge redistribution control. */ typedef enum { /** Disable charge redistribution. */ lcdChargeRedistributionDisable = LCD_DISPCTRL_CHGRDST_DISABLE, /** Use 1 prescaled low frequency clock cycle for charge redistribution. */ lcdChargeRedistributionEnable = LCD_DISPCTRL_CHGRDST_ONE, /** Use 2 prescaled low frequency clock cycle for charge redistribution. */ lcdChargeRedistributionTwoCycle = LCD_DISPCTRL_CHGRDST_TWO, /** Use 3 prescaled low frequency clock cycle for charge redistribution. */ lcdChargeRedistributionThreeCycle = LCD_DISPCTRL_CHGRDST_THREE, /** Use 4 prescaled low frequency clock cycle for charge redistribution. */ lcdChargeRedistributionFourCycle = LCD_DISPCTRL_CHGRDST_FOUR } LCD_ChargeRedistribution_TypeDef; #endif #if defined(_SILICON_LABS_32B_SERIES_2) /** DMA mode of operation. */ typedef enum { lcdDmaModeDisable = LCD_BIASCTRL_DMAMODE_DMADISABLE, /**< No DMA requests are generated. */ lcdDmaModeFrameCounterEvent = LCD_BIASCTRL_DMAMODE_DMAFC, /**< DMA request on frame counter event. */ lcdDmaModeDisplayEvent = LCD_BIASCTRL_DMAMODE_DMADISPLAY /**< DMA request on display counter event. */ } LCD_DmaMode_Typedef; #endif /******************************************************************************* ******************************* STRUCTS *********************************** ******************************************************************************/ /** LCD Animation Configuration. */ typedef struct { /** Enable Animation at end of initialization. */ bool enable; /** Initial Animation Register A Value. */ uint32_t AReg; /** Shift operation of Animation Register A. */ LCD_AnimShift_TypeDef AShift; /** Initial Animation Register B Value. */ uint32_t BReg; /** Shift operation of Animation Register B. */ LCD_AnimShift_TypeDef BShift; /** A and B Logical Operation to use for mixing and outputting resulting segments. */ LCD_AnimLogic_TypeDef animLogic; #if defined(_LCD_BACTRL_ALOC_MASK) /** Number of first segment to animate. */ LCD_AnimLoc_TypeDef startSeg; #endif } LCD_AnimInit_TypeDef; /** LCD Frame Control Initialization. */ typedef struct { /** Enable at end. */ bool enable; /** Frame Counter top value. */ uint32_t top; /** Frame Counter clock prescaler. */ LCD_FCPreScale_TypeDef prescale; } LCD_FrameCountInit_TypeDef; /** LCD Controller Initialization structure. */ typedef struct { /** Enable controller at end of initialization. */ bool enable; /** Mux configuration. */ LCD_Mux_TypeDef mux; /** Bias configuration. */ LCD_Bias_TypeDef bias; /** Wave configuration. */ LCD_Wave_TypeDef wave; #if defined(_SILICON_LABS_32B_SERIES_0) /** VLCD Select. */ LCD_VLCDSel_TypeDef vlcd; /** Contrast Configuration. */ LCD_ConConf_TypeDef contrast; #endif #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2) /** Mode of operation. */ LCD_Mode_Typedef mode; /** Charge redistribution cycles. */ LCD_ChargeRedistribution_TypeDef chargeRedistribution; /** Frame rate divider. */ uint8_t frameRateDivider; /** Contrast level. */ int contrastLevel; #if defined(_SILICON_LABS_32B_SERIES_2) /** Clock Prescaler. */ uint32_t clockPrescaler; #endif #endif } LCD_Init_TypeDef; /** Default configuration for LCD initialization structure, enables 160 segments. */ #if defined(_SILICON_LABS_32B_SERIES_0) #define LCD_INIT_DEFAULT \ { \ true, \ lcdMuxQuadruplex, \ lcdBiasOneThird, \ lcdWaveLowPower, \ lcdVLCDSelVDD, \ lcdConConfVLCD, \ } #endif #if defined(_SILICON_LABS_32B_SERIES_1) #define LCD_INIT_DEFAULT \ { \ true, \ lcdMuxOctaplex, \ lcdBiasOneFourth, \ lcdWaveLowPower, \ lcdModeNoExtCap, \ lcdChargeRedistributionEnable, \ LCD_DEFAULT_FRAME_RATE_DIV, \ LCD_DEFAULT_CONTRAST \ } #endif #if defined(_SILICON_LABS_32B_SERIES_2) #define LCD_INIT_DEFAULT \ { \ true, \ lcdMuxQuadruplex, \ lcdBiasOneFourth, \ lcdWaveLowPower, \ lcdModeStepDown, \ lcdChargeRedistributionEnable, \ LCD_DEFAULT_FRAME_RATE_DIV, \ LCD_DEFAULT_CONTRAST, \ LCD_DEFAULT_CLOCK_PRESCALER \ } #endif /******************************************************************************* ***************************** PROTOTYPES ********************************** ******************************************************************************/ void LCD_Init(const LCD_Init_TypeDef *lcdInit); #if defined(_SILICON_LABS_32B_SERIES_0) void LCD_VLCDSelect(LCD_VLCDSel_TypeDef vlcd); #endif void LCD_UpdateCtrl(LCD_UpdateCtrl_TypeDef ud); void LCD_FrameCountInit(const LCD_FrameCountInit_TypeDef *fcInit); void LCD_AnimInit(const LCD_AnimInit_TypeDef *animInit); #if defined(_SILICON_LABS_32B_SERIES_0) void LCD_SegmentRangeEnable(LCD_SegmentRange_TypeDef segment, bool enable); #endif #if defined(_SILICON_LABS_32B_SERIES_2) void LCD_SegmentEnable(uint32_t seg_nbr, bool enable); void LCD_ComEnable(uint8_t com, bool enable); void LCD_DmaModeSet(LCD_DmaMode_Typedef mode); #endif void LCD_SegmentSet(int com, int bit, bool enable); void LCD_SegmentSetLow(int com, uint32_t mask, uint32_t bits); #if defined(_LCD_SEGD0H_MASK) void LCD_SegmentSetHigh(int com, uint32_t mask, uint32_t bits); #endif void LCD_ContrastSet(int level); void LCD_BiasSet(LCD_Bias_TypeDef bias); #if defined(_SILICON_LABS_32B_SERIES_0) void LCD_VBoostSet(LCD_VBoostLevel_TypeDef vboost); #endif #if defined(LCD_CTRL_DSC) void LCD_BiasSegmentSet(int segment, int biasLevel); void LCD_BiasComSet(int com, int biasLevel); #endif #if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LABS_32B_SERIES_2) void LCD_ModeSet(LCD_Mode_Typedef mode); void LCD_ChargeRedistributionCyclesSet(uint8_t cycles); #endif #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Wait for load synchronization completion. * * @note * Doing any writes to HV registers will not go through and will cause a * bus fault. ******************************************************************************/ __STATIC_INLINE void LCD_LoadBusyWait(void) { while (LCD->STATUS & _LCD_STATUS_LOADBUSY_MASK) ; } #endif #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Wait for the LCD to complete resetting or disabling procedure. ******************************************************************************/ __STATIC_INLINE void LCD_ReadyWait(void) { while ((LCD->SWRST & _LCD_SWRST_RESETTING_MASK) || (LCD->EN & _LCD_EN_DISABLING_MASK) || (LCD->STATUS & _LCD_STATUS_LOADBUSY_MASK)) { // Wait for all synchronizations to finish } } #endif /***************************************************************************//** * @brief * Enable or disable LCD controller. * * @param[in] enable * If true, enables LCD controller with current configuration. If false, * disables LCD controller. Enable CMU clock for LCD for correct * operation. ******************************************************************************/ __STATIC_INLINE void LCD_Enable(bool enable) { #if defined(_SILICON_LABS_32B_SERIES_2) if (enable) { LCD->EN_SET = LCD_EN_EN; } else { /* Wait for internal synchronization completion. */ LCD_LoadBusyWait(); LCD->EN_CLR = LCD_EN_EN; while (LCD->EN & _LCD_EN_DISABLING_MASK) { } } #else #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->CTRL_SET = LCD_CTRL_EN; } else { LCD->CTRL_CLR = LCD_CTRL_EN; } #else if (enable) { LCD->CTRL |= LCD_CTRL_EN; } else { LCD->CTRL &= ~LCD_CTRL_EN; } #endif // LCD_HAS_SET_CLEAR #endif // _SILICON_LABS_32B_SERIES_2 } #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Reset the LCD. ******************************************************************************/ __STATIC_INLINE void LCD_Reset(void) { LCD->SWRST_SET = LCD_SWRST_SWRST; /* Wait for reset to complete. */ while ((LCD->SWRST & _LCD_SWRST_RESETTING_MASK)) { } } #endif /***************************************************************************//** * @brief * Enable or disable LCD Animation feature. * * @param[in] enable * Boolean true enables animation, false disables animation. ******************************************************************************/ __STATIC_INLINE void LCD_AnimEnable(bool enable) { #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->BACTRL_SET = LCD_BACTRL_AEN; } else { LCD->BACTRL_CLR = LCD_BACTRL_AEN; } #else if (enable) { LCD->BACTRL |= LCD_BACTRL_AEN; } else { LCD->BACTRL &= ~LCD_BACTRL_AEN; } #endif } /***************************************************************************//** * @brief * Enable or disable the LCD blink. * * @param[in] enable * Boolean true enables blink, false disables blink. ******************************************************************************/ __STATIC_INLINE void LCD_BlinkEnable(bool enable) { #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->BACTRL_SET = LCD_BACTRL_BLINKEN; } else { LCD->BACTRL_CLR = LCD_BACTRL_BLINKEN; } #else if (enable) { LCD->BACTRL |= LCD_BACTRL_BLINKEN; } else { LCD->BACTRL &= ~LCD_BACTRL_BLINKEN; } #endif } /***************************************************************************//** * @brief * Disable all segments while keeping segment state. * * @param[in] enable * Boolean true clears all segments, boolean false restores all segment lines. ******************************************************************************/ __STATIC_INLINE void LCD_BlankEnable(bool enable) { #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->BACTRL_SET = LCD_BACTRL_BLANK; } else { LCD->BACTRL_CLR = LCD_BACTRL_BLANK; } #else if (enable) { LCD->BACTRL |= LCD_BACTRL_BLANK; } else { LCD->BACTRL &= ~LCD_BACTRL_BLANK; } #endif } /***************************************************************************//** * @brief * Enable or disable LCD Frame counter. * * @param[in] enable * Boolean true enables frame counter, false disables frame counter. ******************************************************************************/ __STATIC_INLINE void LCD_FrameCountEnable(bool enable) { #if defined(_SILICON_LABS_32B_SERIES_2) /* Ensure no internal sync is in progress. */ LCD_LoadBusyWait(); #endif #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->BACTRL_SET = LCD_BACTRL_FCEN; } else { LCD->BACTRL_CLR = LCD_BACTRL_FCEN; } #else if (enable) { LCD->BACTRL |= LCD_BACTRL_FCEN; } else { LCD->BACTRL &= ~LCD_BACTRL_FCEN; } #endif } #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Enable or disable the LCD Display counter. * * @param[in] enable * Boolean true enables display counter, false disables display counter. ******************************************************************************/ __STATIC_INLINE void LCD_DisplayCountEnable(bool enable) { /* Ensure no internal sync is in progress. */ LCD_LoadBusyWait(); if (enable) { LCD->BACTRL_SET = LCD_BACTRL_DISPLAYCNTEN; } else { LCD->BACTRL_CLR = LCD_BACTRL_DISPLAYCNTEN; } } #endif /***************************************************************************//** * @brief * Return the current animation state. * * @return * Animation state, in range 0-15. ******************************************************************************/ __STATIC_INLINE int LCD_AnimState(void) { return (int)(LCD->STATUS & _LCD_STATUS_ASTATE_MASK) >> _LCD_STATUS_ASTATE_SHIFT; } /***************************************************************************//** * @brief * Return the current blink state. * * @return * Return value is 1 if segments are enabled, 0 if disabled. ******************************************************************************/ __STATIC_INLINE int LCD_BlinkState(void) { return (int)(LCD->STATUS & _LCD_STATUS_BLINK_MASK) >> _LCD_STATUS_BLINK_SHIFT; } #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1) /***************************************************************************//** * @brief * When set, LCD registers will not be updated until cleared. * * @param[in] enable * When enable is true, update is stopped; when false, all registers are * updated. ******************************************************************************/ __STATIC_INLINE void LCD_FreezeEnable(bool enable) { if (enable) { LCD->FREEZE = LCD_FREEZE_REGFREEZE_FREEZE; } else { LCD->FREEZE = LCD_FREEZE_REGFREEZE_UPDATE; } } #endif #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1) /***************************************************************************//** * @brief * Return SYNCBUSY bits, indicating which registers have pending updates. * * @return * Bit fields for LCD registers that have pending updates. ******************************************************************************/ __STATIC_INLINE uint32_t LCD_SyncBusyGet(void) { return LCD->SYNCBUSY; } #endif #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1) /***************************************************************************//** * @brief * Poll LCD SYNCBUSY flags until the flag has been cleared. * * @param[in] flags * Bit fields for LCD registers that will be updated before we continue. ******************************************************************************/ __STATIC_INLINE void LCD_SyncBusyDelay(uint32_t flags) { while (LCD->SYNCBUSY & flags) ; } #endif #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Start the synchronization process. * * @param[in] autoload * Flag indicating if the synchronization is started manually with CMD.LOAD * (false) or if the synchronization is managed automatically by Auto Load * (true). * * @param[in] load_addr * Address which will start the synchronization from CLK_BUS to CLK_PER * when Auto Load is selected. This argument has no effect if 'autoload' is * false. ******************************************************************************/ __STATIC_INLINE void LCD_SyncStart(bool autoload, LCD_LoadAddr_TypeDef load_addr) { /* Ensure no synchronization in progress. */ LCD_LoadBusyWait(); if (autoload) { LCD_Enable(false); /* Ensure LCD disabled before writing WSTATIC fields. */ LCD_ReadyWait(); LCD->UPDATECTRL_CLR = _LCD_UPDATECTRL_LOADADDR_MASK; LCD->UPDATECTRL |= load_addr; LCD->UPDATECTRL_SET = LCD_UPDATECTRL_AUTOLOAD; LCD_Enable(true); } else { /* Start synchronization from HV registers to CLK_PER domain. */ LCD->CMD = LCD_CMD_LOAD; } } #endif #if defined(_SILICON_LABS_32B_SERIES_2) /***************************************************************************//** * @brief * Stop the synchronization process. * * @param[in] autoload * Flag indicating if the synchronization is stopped manually with CMD.CLEAR * (false) or if the synchronization managed by Auto Load is disabled (true). ******************************************************************************/ __STATIC_INLINE void LCD_SyncStop(bool autoload) { if (autoload) { /* Autoload cannot be disabled if synchronization in progress. */ LCD_LoadBusyWait(); LCD->UPDATECTRL_CLR = LCD_UPDATECTRL_AUTOLOAD; LCD->UPDATECTRL_CLR = _LCD_UPDATECTRL_LOADADDR_MASK; } else { LCD->CMD = LCD_CMD_CLEAR; } } #endif /***************************************************************************//** * @brief * Get pending LCD interrupt flags. * * @return * Pending LCD interrupt sources. Returns a set of interrupt flags OR-ed * together for multiple interrupt sources in the LCD module (LCD_IFS_nnn). ******************************************************************************/ __STATIC_INLINE uint32_t LCD_IntGet(void) { return LCD->IF; } /***************************************************************************//** * @brief * Get enabled and pending LCD interrupt flags. * * @details * Useful for handling more interrupt sources in the same interrupt handler. * * @note * Event bits are not cleared by the use of this function. * * @return * Pending and enabled LCD interrupt sources. * Return value is the bitwise AND combination of * - the OR combination of enabled interrupt sources in LCD_IEN_nnn * register (LCD_IEN_nnn) and * - the bitwise OR combination of valid interrupt flags of LCD module * (LCD_IF_nnn). ******************************************************************************/ __STATIC_INLINE uint32_t LCD_IntGetEnabled(void) { uint32_t ien; /* Store the LCD->IEN in temporary variable to define the explicit order * of volatile accesses. */ ien = LCD->IEN; /* Bitwise AND of pending and enabled interrupts */ return LCD->IF & ien; } /***************************************************************************//** * @brief * Set one or more pending LCD interrupts from SW. * * @param[in] flags * LCD interrupt sources to set to pending. Use a set of interrupt flags * OR-ed together to set multiple interrupt sources for the LCD module * (LCD_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void LCD_IntSet(uint32_t flags) { #if defined(_SILICON_LABS_32B_SERIES_2) #if defined(LCD_HAS_SET_CLEAR) LCD->IF_SET = flags; #else LCD->IF |= flags; #endif // LCD_HAS_SET_CLEAR #else LCD->IFS = flags; #endif } /***************************************************************************//** * @brief * Enable LCD interrupts. * * @param[in] flags * LCD interrupt sources to enable. Use a set of interrupt flags OR-ed * together to set multiple interrupt sources for LCD module * (LCD_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void LCD_IntEnable(uint32_t flags) { #if defined(LCD_HAS_SET_CLEAR) LCD->IEN_SET = flags; #else LCD->IEN |= flags; #endif } /***************************************************************************//** * @brief * Disable LCD interrupts. * * @param[in] flags * LCD interrupt sources to disable. Use a set of interrupt flags OR-ed * together to disable multiple interrupt sources for LCD module * (LCD_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void LCD_IntDisable(uint32_t flags) { #if defined(LCD_HAS_SET_CLEAR) LCD->IEN_CLR = flags; #else LCD->IEN &= ~flags; #endif } /***************************************************************************//** * @brief * Clear one or more interrupt flags. * * @param[in] flags * LCD interrupt sources to clear. Use a set of interrupt flags OR-ed * together to clear multiple interrupt sources for LCD module * (LCD_IFS_nnn). ******************************************************************************/ __STATIC_INLINE void LCD_IntClear(uint32_t flags) { #if defined(_SILICON_LABS_32B_SERIES_2) #if defined(LCD_HAS_SET_CLEAR) LCD->IF_CLR = flags; #else LCD->IF &= ~flags; #endif // LCD_HAS_SET_CLEAR #else LCD->IFC = flags; #endif } #if defined(LCD_CTRL_DSC) /***************************************************************************//** * @brief * Enable or disable LCD Direct Segment Control. * * @param[in] enable * If true, enables LCD controller Direct Segment Control * Segment and COM line bias levels need to be set explicitly with * LCD_BiasSegmentSet() and LCD_BiasComSet() function calls respectively. ******************************************************************************/ __STATIC_INLINE void LCD_DSCEnable(bool enable) { #if defined(_SILICON_LABS_32B_SERIES_2) LCD_Enable(false); /* Ensure LCD disabled before writing WSTATIC fields. */ LCD_ReadyWait(); #endif #if defined(LCD_HAS_SET_CLEAR) if (enable) { LCD->CTRL_SET = LCD_CTRL_DSC; } else { LCD->CTRL_CLR = LCD_CTRL_DSC; } #else if (enable) { LCD->CTRL |= LCD_CTRL_DSC; } else { LCD->CTRL &= ~LCD_CTRL_DSC; } #endif #if defined(_SILICON_LABS_32B_SERIES_2) LCD_Enable(true); #endif } #endif /** @} (end addtogroup lcd) */ #ifdef __cplusplus } #endif #endif /* defined(LCD_COUNT) && (LCD_COUNT > 0) */ #endif /* EM_LCD_H */