rt-thread/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_lcd.c

339 lines
10 KiB
C

/**************************************************************************//**
* @file lcd.c
* @version V3.00
* @brief Liquid-Crystal Display(LCD) driver source file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "NuMicro.h"
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup LCD_Driver LCD Driver
@{
*/
/// @cond HIDDEN_SYMBOLS
/** @addtogroup LCD_EXPORTED_VARIABLES LCD Exported Variables
@{
*/
/*---------------------------------------------------------------------------------------------------------*/
/* Global file scope (static) variables */
/*---------------------------------------------------------------------------------------------------------*/
static uint32_t g_LCDFrameRate;
/**@}*/ /* end of group LCD_EXPORTED_VARIABLES */
/// @endcond /* HIDDEN_SYMBOLS */
/** @addtogroup LCD_EXPORTED_FUNCTIONS LCD Exported Functions
@{
*/
/**
* @brief LCD Initialization routine
*
* @param[in] pLCDCfg Specify the LCD property. It includes:
* u32SrcFreq: Clock source frequency of LCD controller.
* u32ComDuty: LCD COM duty ratio selection. Valid values are:
* - \ref LCD_COM_DUTY_1_1
* - \ref LCD_COM_DUTY_1_2
* - \ref LCD_COM_DUTY_1_3
* - \ref LCD_COM_DUTY_1_4
* - \ref LCD_COM_DUTY_1_5
* - \ref LCD_COM_DUTY_1_6
* - \ref LCD_COM_DUTY_1_7
* - \ref LCD_COM_DUTY_1_8
* u32BiasLevel: LCD Bias level selection. Valid values are:
* - \ref LCD_BIAS_LV_1_2
* - \ref LCD_BIAS_LV_1_3
* - \ref LCD_BIAS_LV_1_4
* u32Framerate: Specify the target LCD operating frame rate (Hz).
* u32WaveformType: Specify the LCD waveform type. Valid values are:
* - \ref LCD_WAVEFORM_TYPE_A_NORMAL
* - \ref LCD_WAVEFORM_TYPE_B_NORMAL
* - \ref LCD_WAVEFORM_TYPE_A_INVERSE
* - \ref LCD_WAVEFORM_TYPE_B_INVERSE
* u32IntSrc: Interrupt source selection. Valid values are:
* - \ref LCD_DISABLE_ALL_INT
* - \ref LCD_FRAME_COUNTING_END_INT
* - \ref LCD_FRAME_END_INT
* - \ref LCD_CPTOUT_INT
* - \ref LCD_ENABLE_ALL_INT
* u32DrivingMode: LCD operation driving mode selection. Valid values are:
* - \ref LCD_LOW_DRIVING_AND_BUF_OFF
* - \ref LCD_HIGH_DRIVING_AND_BUF_OFF
* - \ref LCD_HIGH_DRIVING_AND_BUF_OFF_AND_PWR_SAVING
* - \ref LCD_HIGH_DRIVING_AND_BUF_OFF_AND_PWR_SAVING
* - \ref LCD_LOW_DRIVING_AND_BUF_ON_AND_PWR_SAVING
* u32VSrc: Voltage source selection. Valid values are:
* - \ref LCD_VOLTAGE_SOURCE_VLCD
* - \ref LCD_VOLTAGE_SOURCE_AVDD
* - \ref LCD_VOLTAGE_SOURCE_CP
*
* @return The real LCD operating frame rate. Or 0 means LCD_Open failed.
*
* @details This function will configure the LCD properties for driving the LCD display well.
* After that, user can perform \ref LCD_ENABLE_DISPLAY() to enable LCD controller for LCD display.
*/
uint32_t LCD_Open(S_LCD_CFG_T *pLCDCfg)
{
uint32_t u32ComNum, u32FreqLCD, u32FreqDiv;
/* Display LCD display first */
LCD_DISABLE_DISPLAY();
/* Turn all segments off */
LCD_SetAllPixels(0);
/* Set com and bias */
LCD->PCTL = (pLCDCfg->u32ComDuty | pLCDCfg->u32BiasLevel);
/* Set waveform type */
LCD_WAVEFORM_TYPE(pLCDCfg->u32WaveformType);
/* Configure interrupt source */
LCD->INTEN = pLCDCfg->u32IntSrc;
/* Set driving mode */
LCD_DRIVING_MODE(pLCDCfg->u32DrivingMode);
/* Select voltage source */
LCD_VOLTAGE_SOURCE(pLCDCfg->u32VSrc);
/*
An example for specify frame rate.
If LCD source clock is 32768Hz, COM duty 4.
In type-A:
One frame rate 32Hz, frame end event rate 32Hz.
32 = (1/4) * F_LCD * (1/2)
F_LCD = 32 * 4 * 2 = 256 = (32768 / F_Div)
F_Div = (32768 / F_LCD) = 128
In type-B:
Each even/odd frame rate 32Hz, frame end event rate 16Hz.
32 = (1/4) * F_LCD
F_LCD = 32 * 4 = (32768 / F_Div)
F_Div = (32768 / F_LCD) = 256
*/
u32ComNum = ((pLCDCfg->u32ComDuty & LCD_PCTL_DUTY_Msk) >> LCD_PCTL_DUTY_Pos) + 1;
if((pLCDCfg->u32WaveformType & LCD_PCTL_TYPE_Msk) == LCD_PCTL_TYPE_Msk)
{
/* In type-B */
/* Calculate LCD operation frequency */
u32FreqLCD = (pLCDCfg->u32Framerate * u32ComNum);
/* Calculate possible freq. divider */
u32FreqDiv = (pLCDCfg->u32SrcFreq / u32FreqLCD);
if(u32FreqDiv > 1024)
{
/* Invalid frame rate */
g_LCDFrameRate = 0ul;
}
else
{
/* Set freq. divider */
LCD_SET_FREQDIV(u32FreqDiv);
/* Calculate target frame rate */
g_LCDFrameRate = pLCDCfg->u32SrcFreq / (u32ComNum * u32FreqDiv);
}
}
else
{
/* In type-A */
/* Calculate LCD operation frequency */
u32FreqLCD = (pLCDCfg->u32Framerate * u32ComNum) * 2;
/* Calculate possible freq. divider */
u32FreqDiv = (pLCDCfg->u32SrcFreq / u32FreqLCD);
if(u32FreqDiv > 1024)
{
/* Invalid frame rate */
g_LCDFrameRate = 0ul;
}
else
{
/* Set freq. divider */
LCD_SET_FREQDIV(u32FreqDiv);
/* Calculate target frame rate */
g_LCDFrameRate = (pLCDCfg->u32SrcFreq / (u32ComNum * u32FreqDiv)) / 2;
}
}
return g_LCDFrameRate;
}
/**
* @brief Disable LCD Display
*
* @param[in] None
*
* @return None
*
* @details This function is used to disable LCD display.
*/
void LCD_Close(void)
{
LCD_DISABLE_DISPLAY();
}
/**
* @brief Enables a Segment Display
*
* @param[in] u32Com Specify COM number. Valid values are from 0~7.
* @param[in] u32Seg Specify Segment number. Valid values are from 0~43.
* @param[in] u32OnFlag 0 : Segment not display
* 1 : Segment display
*
* @return None
*
* @details This function is used to enable specified segment display on the LCD.
*/
void LCD_SetPixel(uint32_t u32Com, uint32_t u32Seg, uint32_t u32OnFlag)
{
uint32_t seg_num = (u32Seg / 4);
uint32_t seg_shift = (8 * (u32Seg - (4 * seg_num)));
if(seg_num < 11)
{
if(u32OnFlag)
{
LCD->DATA[seg_num] |= ((uint32_t)(1 << u32Com) << seg_shift);
}
else
{
LCD->DATA[seg_num] &= (~((uint32_t)(1 << u32Com) << seg_shift));
}
}
}
/**
* @brief Enable/Disable all LCD segments
*
* @param[in] u32OnOff 0 : Disable all segments display
* 1 : Enable all segments display
*
* @return None
*
* @details This function is used to enable/disable all LCD segments display.
*/
void LCD_SetAllPixels(uint32_t u32OnOff)
{
uint32_t i, u32Value;
if(u32OnOff == 1ul)
{
u32Value = 0xFFFFFFFFul;
}
else
{
u32Value = 0x00000000ul;
}
for(i = 0; i < 11; i++)
LCD->DATA[i] = u32Value;
}
/**
* @brief Enable LCD Blinking
*
* @param[in] u32ms Blinking period time(unit: ms)
*
* @return Real blinking period time(ms)
*
* @details This function is used to enable blink display with specified period.
*/
uint32_t LCD_EnableBlink(uint32_t u32ms)
{
uint32_t u32OneCountPeriod, u32TargetCounts;
if((LCD->PCTL & LCD_PCTL_TYPE_Msk) == LCD_PCTL_TYPE_Msk)
{
/* In type-B */
u32OneCountPeriod = (1000 * 2) / g_LCDFrameRate; // ms
}
else
{
/* In type-A */
u32OneCountPeriod = 1000 / g_LCDFrameRate; // ms
}
u32TargetCounts = (u32ms / u32OneCountPeriod);
if(u32TargetCounts == 0)
u32TargetCounts = 1;
if(u32TargetCounts > 1024)
u32TargetCounts = 1024;
LCD_SET_FRAME_COUNTING_VALUE(u32TargetCounts);
/* Enable blink display */
LCD_BLINKING_ON();
return (u32OneCountPeriod * u32TargetCounts);
}
/**
* @brief Disable LCD Blinking
*
* @param[in] None
*
* @return None
*
* @details This function is used to disable LCD blink display.
*/
void LCD_DisableBlink(void)
{
/* Disable blink display */
LCD_BLINKING_OFF();
}
/**
* @brief Enable LCD Interrupt
*
* @param[in] IntSrc Interrupt Source. It could be a combination of
* \ref LCD_FRAME_COUNTING_END_INT, \ref LCD_FRAME_END_INT and \ref LCD_CPTOUT_INT.
*
* @return None
*
* @details This function is used to enable the specific LCD interrupt.
*/
void LCD_EnableInt(uint32_t u32IntSrc)
{
LCD->INTEN |= (u32IntSrc);
}
/**
* @brief Disable LCD Interrupt
*
* @param[in] IntSrc Interrupt Source. It could be a combination of
* \ref LCD_FRAME_COUNTING_END_INT, \ref LCD_FRAME_END_INT and \ref LCD_CPTOUT_INT.
*
* @return None
*
* @details This function is used to disable the specific LCD interrupt.
*/
void LCD_DisableInt(uint32_t u32IntSrc)
{
LCD->INTEN &= ~(u32IntSrc);
}
/**@}*/ /* end of group LCD_EXPORTED_FUNCTIONS */
/**@}*/ /* end of group LCD_Driver */
/**@}*/ /* end of group Standard_Driver */