234 lines
5.9 KiB
C
234 lines
5.9 KiB
C
|
/**************************************************************************//**
|
||
|
*
|
||
|
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*
|
||
|
* Change Logs:
|
||
|
* Date Author Notes
|
||
|
* 2020-11-11 Wayne First version
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include <rtconfig.h>
|
||
|
|
||
|
#if defined(BSP_USING_SLCD)
|
||
|
|
||
|
#include <rtdevice.h>
|
||
|
#include <rthw.h>
|
||
|
#include <NuMicro.h>
|
||
|
#include <drv_slcd.h>
|
||
|
|
||
|
/* Private define ---------------------------------------------------------------*/
|
||
|
#define DBG_ENABLE
|
||
|
#define DBG_LEVEL DBG_LOG
|
||
|
#define DBG_SECTION_NAME "slcd"
|
||
|
#define DBG_COLOR
|
||
|
#include <rtdbg.h>
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
SLCD_START = -1,
|
||
|
SLCD_IDX,
|
||
|
SLCD_CNT
|
||
|
};
|
||
|
#define LCD_ALPHABET_NUM 7
|
||
|
|
||
|
/* Private typedef --------------------------------------------------------------*/
|
||
|
struct nu_slcd
|
||
|
{
|
||
|
struct rt_device dev;
|
||
|
char *name;
|
||
|
LCD_T *base;
|
||
|
uint32_t rst;
|
||
|
rt_mutex_t lock;
|
||
|
};
|
||
|
typedef struct nu_slcd *nu_slcd_t;
|
||
|
|
||
|
/* Private functions ------------------------------------------------------------*/
|
||
|
|
||
|
/* Public functions ------------------------------------------------------------*/
|
||
|
|
||
|
/* Private variables ------------------------------------------------------------*/
|
||
|
static struct nu_slcd nu_slcd_arr [] =
|
||
|
{
|
||
|
{
|
||
|
.name = "slcd",
|
||
|
.base = LCD,
|
||
|
.rst = LCD_RST,
|
||
|
}
|
||
|
}; /* nu_slcd_arr */
|
||
|
|
||
|
static S_LCD_CFG_T g_SLCDCfg =
|
||
|
{
|
||
|
__LXT, /*!< LCD clock source frequency */
|
||
|
LCD_COM_DUTY_1_8, /*!< COM duty */
|
||
|
LCD_BIAS_LV_1_4, /*!< Bias level */
|
||
|
64, /*!< Operation frame rate */
|
||
|
LCD_WAVEFORM_TYPE_A_NORMAL, /*!< Waveform type */
|
||
|
LCD_DISABLE_ALL_INT, /*!< Interrupt source */
|
||
|
LCD_LOW_DRIVING_AND_BUF_ON, /*!< Driving mode */
|
||
|
LCD_VOLTAGE_SOURCE_VLCD, /*!< Voltage source */
|
||
|
};
|
||
|
|
||
|
static rt_err_t nu_slcd_open(struct rt_device *dev, rt_uint16_t oflag)
|
||
|
{
|
||
|
if (dev->ref_count == 0)
|
||
|
{
|
||
|
nu_slcd_t psNuSLcd = (nu_slcd_t)dev;
|
||
|
|
||
|
/* Reset LCD module */
|
||
|
SYS_ResetModule(psNuSLcd->rst);
|
||
|
|
||
|
uint32_t u32ActiveFPS = LCD_Open(&g_SLCDCfg);
|
||
|
|
||
|
/* LCD Initialize and calculate real frame rate */
|
||
|
LOG_I("Working frame rate is %dHz on Type-%c.\n\n", u32ActiveFPS, (g_SLCDCfg.u32WaveformType == LCD_PCTL_TYPE_Msk) ? 'B' : 'A');
|
||
|
|
||
|
/* Enable LCD display */
|
||
|
LCD_ENABLE_DISPLAY();
|
||
|
}
|
||
|
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_err_t nu_slcd_close(struct rt_device *dev)
|
||
|
{
|
||
|
if (dev->ref_count == 0)
|
||
|
{
|
||
|
/* Disable LCD display */
|
||
|
LCD_DISABLE_DISPLAY();
|
||
|
}
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_size_t nu_slcd_write(struct rt_device *dev,
|
||
|
rt_off_t pos,
|
||
|
const void *buffer,
|
||
|
rt_size_t size)
|
||
|
{
|
||
|
nu_slcd_pixel_t psSlcdPixel;
|
||
|
nu_slcd_t psNuSLCD = (nu_slcd_t)dev;
|
||
|
|
||
|
RT_ASSERT(buffer != RT_NULL);
|
||
|
RT_ASSERT(size == sizeof(struct nu_slcd_pixel));
|
||
|
|
||
|
psSlcdPixel = (nu_slcd_pixel_t)buffer;
|
||
|
|
||
|
/* Critical section */
|
||
|
rt_mutex_take(psNuSLCD->lock, RT_WAITING_FOREVER);
|
||
|
LCD_SetPixel(psSlcdPixel->m_u32Com, psSlcdPixel->m_u32Seg, psSlcdPixel->m_u32OnFlag);
|
||
|
rt_mutex_release(psNuSLCD->lock);
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
static rt_err_t nu_slcd_control(struct rt_device *dev,
|
||
|
int cmd,
|
||
|
void *args)
|
||
|
{
|
||
|
rt_err_t ret = RT_EOK;
|
||
|
switch (cmd)
|
||
|
{
|
||
|
case NU_SLCD_CMD_SET_LCD_CFG:
|
||
|
{
|
||
|
S_LCD_CFG_T *psLCDCfg;
|
||
|
|
||
|
RT_ASSERT(args != RT_NULL);
|
||
|
psLCDCfg = (S_LCD_CFG_T *)args;
|
||
|
|
||
|
rt_memcpy((void *)&g_SLCDCfg, (void *)psLCDCfg, sizeof(S_LCD_CFG_T));
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case NU_SLCD_CMD_SET_CP_VOLTAGE:
|
||
|
{
|
||
|
/*
|
||
|
LCD_CP_VOLTAGE_LV_0 2.6 V
|
||
|
LCD_CP_VOLTAGE_LV_1 2.8 V
|
||
|
LCD_CP_VOLTAGE_LV_2 3.0 V
|
||
|
LCD_CP_VOLTAGE_LV_3 3.2 V
|
||
|
LCD_CP_VOLTAGE_LV_4 3.4 V
|
||
|
LCD_CP_VOLTAGE_LV_5 3.6 V
|
||
|
*/
|
||
|
uint32_t u32CPVol;
|
||
|
RT_ASSERT(args != RT_NULL);
|
||
|
|
||
|
u32CPVol = *((uint32_t *)args) ;
|
||
|
if ((u32CPVol >> LCD_PCTL_CPVSEL_Pos) <= (LCD_CP_VOLTAGE_LV_5 >> LCD_PCTL_CPVSEL_Pos))
|
||
|
{
|
||
|
LCD_SET_CP_VOLTAGE(u32CPVol);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ret = -RT_ERROR;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
return -RT_EINVAL;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
#ifdef RT_USING_DEVICE_OPS
|
||
|
const static struct rt_device_ops slcd_ops =
|
||
|
{
|
||
|
RT_NULL,
|
||
|
nu_slcd_open,
|
||
|
nu_slcd_close,
|
||
|
RT_NULL,
|
||
|
nu_slcd_write,
|
||
|
nu_slcd_control
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
rt_err_t rt_hw_slcd_register(struct rt_device *device,
|
||
|
const char *name,
|
||
|
rt_uint32_t flag,
|
||
|
void *data)
|
||
|
{
|
||
|
RT_ASSERT(device != RT_NULL);
|
||
|
|
||
|
device->type = RT_Device_Class_Char;
|
||
|
device->rx_indicate = RT_NULL;
|
||
|
device->tx_complete = RT_NULL;
|
||
|
|
||
|
#ifdef RT_USING_DEVICE_OPS
|
||
|
device->ops = &slcd_ops;
|
||
|
#else
|
||
|
device->init = RT_NULL;
|
||
|
device->open = nu_slcd_open;
|
||
|
device->close = nu_slcd_close;
|
||
|
device->read = RT_NULL;
|
||
|
device->write = nu_slcd_write;
|
||
|
device->control = nu_slcd_control;
|
||
|
#endif
|
||
|
device->user_data = data;
|
||
|
|
||
|
/* register a character device */
|
||
|
return rt_device_register(device, name, flag);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hardware SLCD Initialization
|
||
|
*/
|
||
|
static int rt_hw_slcd_init(void)
|
||
|
{
|
||
|
int i;
|
||
|
rt_err_t ret = RT_EOK;
|
||
|
|
||
|
for (i = (SLCD_START + 1); i < SLCD_CNT; i++)
|
||
|
{
|
||
|
ret = rt_hw_slcd_register(&nu_slcd_arr[i].dev, nu_slcd_arr[i].name, RT_DEVICE_FLAG_RDWR, NULL);
|
||
|
RT_ASSERT(ret == RT_EOK);
|
||
|
nu_slcd_arr[i].lock = rt_mutex_create(nu_slcd_arr[i].name, RT_IPC_FLAG_FIFO);
|
||
|
RT_ASSERT(nu_slcd_arr[i].lock != RT_NULL);
|
||
|
}
|
||
|
|
||
|
return (int)ret;
|
||
|
}
|
||
|
INIT_DEVICE_EXPORT(rt_hw_slcd_init);
|
||
|
|
||
|
#endif //#if defined(BSP_USING_SLCD)
|