1 /******************************************************************************************************************************************
2 * 文件名称: SWM341_lcd.c
3 * 功能说明: SWM341单片机的LCD功能驱动库
4 * 技术支持: http://www.synwit.com.cn/e/tool/gbook/?bid=1
5 * 注意事项:
6 * 版本日期: V1.1.0      2017年10月25日
7 * 升级记录:
8 *
9 *
10 *******************************************************************************************************************************************
11 * @attention
12 *
13 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
14 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
15 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
16 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
17 * -ECTION WITH THEIR PRODUCTS.
18 *
19 * COPYRIGHT 2012 Synwit Technology
20 *******************************************************************************************************************************************/
21 #include "SWM341.h"
22 #include "SWM341_lcd.h"
23 
24 #include <string.h>
25 
26 
27 /******************************************************************************************************************************************
28 * 函数名称: LCD_Init()
29 * 功能说明: LCD初始化
30 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
31 *           LCD_InitStructure * initStruct    包含LCD相关设定值的结构体
32 * 输    出: 无
33 * 注意事项: 无
34 ******************************************************************************************************************************************/
LCD_Init(LCD_TypeDef * LCDx,LCD_InitStructure * initStruct)35 void LCD_Init(LCD_TypeDef * LCDx, LCD_InitStructure * initStruct)
36 {
37     switch((uint32_t)LCDx)
38     {
39     case ((uint32_t)LCD):
40         SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_LCD_Pos);
41         break;
42     }
43 
44     LCDx->CR  = ((initStruct->ClkDiv - 2)  << LCD_CR_CLKDIV_Pos)   |
45                 (initStruct->SampleEdge    << LCD_CR_CLKINV_Pos)   |
46                 (1                         << LCD_CR_CLKALW_Pos)   |
47                 ((initStruct->Format & 1)  << LCD_CR_FORMAT_Pos)   |
48                 ((initStruct->Format >> 1) << LCD_CR_SEREN_Pos)    |
49                 (1                         << LCD_CR_BURSTEN_Pos)  |
50                 (1                         << LCD_CR_BURSTLEN_Pos) |
51                 ((1-initStruct->IntEOTEn)  << LCD_CR_AUTORESTA_Pos);
52 
53     LCDx->CRH = ((initStruct->HsyncWidth - 1) << LCD_CRH_HSW_Pos) |
54                 ((initStruct->Hbp - 1)        << LCD_CRH_HBP_Pos) |
55                 ((initStruct->HnPixel - 1)    << LCD_CRH_PIX_Pos) |
56                 ((initStruct->Hfp - 1)        << LCD_CRH_HFP_Pos);
57 
58     LCDx->CRV = ((initStruct->VsyncWidth - 1) << LCD_CRV_VSW_Pos) |
59                 ((initStruct->Vbp - 1)        << LCD_CRV_VBP_Pos) |
60                 ((initStruct->VnPixel - 1)    << LCD_CRV_PIX_Pos) |
61                 ((initStruct->Vfp - 1)        << LCD_CRV_VFP_Pos);
62 
63     LCDx->BGC = initStruct->Background;
64 
65     LCDx->L[0].LCR = (1    << LCD_LCR_EN_Pos)   |
66                      (0    << LCD_LCR_CKEN_Pos) |
67                      (0xFF << LCD_LCR_ALPHA_Pos);
68 
69     LCDx->L[0].WHP = (0                         << LCD_WHP_STA_Pos) |
70                      ((initStruct->HnPixel - 1) << LCD_WHP_STP_Pos);
71 
72     LCDx->L[0].WVP = (0                         << LCD_WVP_STA_Pos) |
73                      ((initStruct->VnPixel - 1) << LCD_WVP_STP_Pos);
74 
75     LCDx->L[0].ADDR = initStruct->DataSource;
76 
77     LCDx->L[0].LLEN = (initStruct->HnPixel - 1);
78 
79     LCDx->IF = 1;   //清除标志
80     LCDx->IE = initStruct->IntEOTEn;
81 
82     switch((uint32_t)LCDx)
83     {
84     case ((uint32_t)LCD):
85         if(initStruct->IntEOTEn) NVIC_EnableIRQ(LCD_IRQn);
86         break;
87     }
88 }
89 
90 /******************************************************************************************************************************************
91 * 函数名称: LCD_LayerInit()
92 * 功能说明: LCD层初始化
93 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
94 *           uint32_t layerx     要初始化的LCD层,取值LCD_LAYER_1、LCD_LAYER_2
95 *           LCD_LayerInitStructure * initStruct    包含LCD层相关设定值的结构体
96 * 输    出: 无
97 * 注意事项: 无
98 ******************************************************************************************************************************************/
LCD_LayerInit(LCD_TypeDef * LCDx,uint32_t layerx,LCD_LayerInitStructure * initStruct)99 void LCD_LayerInit(LCD_TypeDef * LCDx, uint32_t layerx, LCD_LayerInitStructure * initStruct)
100 {
101     LCDx->L[layerx].LCR = (1                 << LCD_LCR_EN_Pos)   |
102                           (0                 << LCD_LCR_CKEN_Pos) |
103                           (initStruct->Alpha << LCD_LCR_ALPHA_Pos);
104 
105     LCDx->L[layerx].WHP = (initStruct->HStart << LCD_WHP_STA_Pos) |
106                           (initStruct->HStop  << LCD_WHP_STP_Pos);
107 
108     LCDx->L[layerx].WVP = (initStruct->VStart << LCD_WVP_STA_Pos) |
109                           (initStruct->VStop  << LCD_WVP_STP_Pos);
110 
111     LCDx->L[layerx].ADDR = initStruct->DataSource;
112 
113     LCDx->L[layerx].LLEN = (initStruct->HStop - initStruct->HStart);
114 
115     LCD->CR |= (1 << LCD_CR_VBPRELOAD_Pos);
116 }
117 
118 /******************************************************************************************************************************************
119 * 函数名称: LCD_SetLayerPos()
120 * 功能说明: LCD层位置设定
121 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
122 *           uint32_t layerx     要设置的LCD层,取值LCD_LAYER_1、LCD_LAYER_2
123 *           uint16_t hstart, uint16_t hstop, uint16_t vstart, uint16_t vstop,详细说明见 LCD_LayerInitStructure
124 * 输    出: 无
125 * 注意事项: 无
126 ******************************************************************************************************************************************/
LCD_SetLayerPos(LCD_TypeDef * LCDx,uint32_t layerx,uint16_t hstart,uint16_t hstop,uint16_t vstart,uint16_t vstop)127 void LCD_SetLayerPos(LCD_TypeDef * LCDx, uint32_t layerx, uint16_t hstart, uint16_t hstop, uint16_t vstart, uint16_t vstop)
128 {
129     LCDx->L[layerx].WHP = (hstart << LCD_WHP_STA_Pos) |
130                           (hstop  << LCD_WHP_STP_Pos);
131 
132     LCDx->L[layerx].WVP = (vstart << LCD_WVP_STA_Pos) |
133                           (vstop  << LCD_WVP_STP_Pos);
134 
135     LCD->CR |= (1 << LCD_CR_VBPRELOAD_Pos);
136 }
137 
138 /******************************************************************************************************************************************
139 * 函数名称: LCD_Start()
140 * 功能说明: 启动一次数据传输
141 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
142 * 输    出: 无
143 * 注意事项: 无
144 ******************************************************************************************************************************************/
LCD_Start(LCD_TypeDef * LCDx)145 void LCD_Start(LCD_TypeDef * LCDx)
146 {
147     LCDx->START |= (1 << LCD_START_GO_Pos);
148 }
149 
150 /******************************************************************************************************************************************
151 * 函数名称: LCD_IsBusy()
152 * 功能说明: 是否正在进行数据传输
153 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
154 * 输    出: uint32_t          1 正在传输数据    0 数据传输已完成
155 * 注意事项: 无
156 ******************************************************************************************************************************************/
LCD_IsBusy(LCD_TypeDef * LCDx)157 uint32_t LCD_IsBusy(LCD_TypeDef * LCDx)
158 {
159     return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0;
160 }
161 
162 /******************************************************************************************************************************************
163 * 函数名称: LCD_INTEn()
164 * 功能说明: LCD中断使能,完成指定长度的数据传输时触发中断
165 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
166 * 输    出: 无
167 * 注意事项: 无
168 ******************************************************************************************************************************************/
LCD_INTEn(LCD_TypeDef * LCDx)169 void LCD_INTEn(LCD_TypeDef * LCDx)
170 {
171     LCDx->IE = 1;
172 }
173 
174 /******************************************************************************************************************************************
175 * 函数名称: LCD_INTDis()
176 * 功能说明: LCD中断禁止,完成指定长度的数据传输时不触发中断
177 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
178 * 输    出: 无
179 * 注意事项: 无
180 ******************************************************************************************************************************************/
LCD_INTDis(LCD_TypeDef * LCDx)181 void LCD_INTDis(LCD_TypeDef * LCDx)
182 {
183     LCDx->IE = 0;
184 }
185 
186 /******************************************************************************************************************************************
187 * 函数名称: LCD_INTClr()
188 * 功能说明: LCD中断标志清除
189 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
190 * 输    出: 无
191 * 注意事项: 无
192 ******************************************************************************************************************************************/
LCD_INTClr(LCD_TypeDef * LCDx)193 void LCD_INTClr(LCD_TypeDef * LCDx)
194 {
195     LCDx->IF = 1;
196 }
197 
198 /******************************************************************************************************************************************
199 * 函数名称: LCD_INTStat()
200 * 功能说明: LCD中断状态查询
201 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
202 * 输    出: uint32_t          0 未完成指定长度的数据传输   非0 完成指定长度的数据传输
203 * 注意事项: 无
204 ******************************************************************************************************************************************/
LCD_INTStat(LCD_TypeDef * LCDx)205 uint32_t LCD_INTStat(LCD_TypeDef * LCDx)
206 {
207     return (LCDx->IF & 1);
208 }
209 
210 
211 /******************************************************************************************************************************************
212 * 函数名称: MPULCD_Init()
213 * 功能说明: MPU LCD初始化
214 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
215 *           MPULCD_InitStructure * initStruct    包含MPU LCD相关设定值的结构体
216 * 输    出: 无
217 * 注意事项: 无
218 ******************************************************************************************************************************************/
MPULCD_Init(LCD_TypeDef * LCDx,MPULCD_InitStructure * initStruct)219 void MPULCD_Init(LCD_TypeDef * LCDx, MPULCD_InitStructure * initStruct)
220 {
221     switch((uint32_t)LCDx)
222     {
223     case ((uint32_t)LCD):
224         SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_LCD_Pos);
225         __NOP();__NOP();__NOP();
226         break;
227     }
228 
229     LCDx->CR  = (1              << LCD_CR_MPUEN_Pos) |
230                 (LCD_FMT_RGB565 << LCD_CR_FORMAT_Pos);  //MPU模式只支持RGB565
231 
232     LCDx->L[0].LCR |= (1 << LCD_LCR_EN_Pos);            //MPU模式下需要使能Layer1
233 
234     LCDx->MPUCR = ((initStruct->RDHoldTime    - 1) << LCD_MPUCR_RDHOLD_Pos) |
235                   ((initStruct->WRHoldTime    - 1) << LCD_MPUCR_WRHOLD_Pos) |
236                   ((initStruct->CSFall_WRFall - 1) << LCD_MPUCR_CS0WR0_Pos) |
237                   ((initStruct->WRRise_CSRise - 1) << LCD_MPUCR_WR1CS1_Pos) |
238                   ((initStruct->RDCSRise_Fall - 1) << LCD_MPUCR_RCS1_0_Pos) |
239                   ((initStruct->WRCSRise_Fall - 1) << LCD_MPUCR_WCS1_0_Pos);
240 }
241 
LCD_WR_REG(LCD_TypeDef * LCDx,uint16_t reg)242 void LCD_WR_REG(LCD_TypeDef * LCDx, uint16_t reg)
243 {
244     LCDx->MPUIR = reg;
245     while(LCD_IsBusy(LCDx)) __NOP();
246 }
247 
LCD_WR_DATA(LCD_TypeDef * LCDx,uint16_t val)248 void LCD_WR_DATA(LCD_TypeDef * LCDx, uint16_t val)
249 {
250     LCDx->MPUDR = val;
251     while(LCD_IsBusy(LCDx)) __NOP();
252 }
253 
LCD_WriteReg(LCD_TypeDef * LCDx,uint16_t reg,uint16_t val)254 void LCD_WriteReg(LCD_TypeDef * LCDx, uint16_t reg, uint16_t val)
255 {
256     LCDx->MPUIR = reg;
257     while(LCD_IsBusy(LCDx)) __NOP();
258 
259     LCDx->MPUDR = val;
260     while(LCD_IsBusy(LCDx)) __NOP();
261 }
262 
LCD_ReadReg(LCD_TypeDef * LCDx,uint16_t reg)263 uint16_t LCD_ReadReg(LCD_TypeDef * LCDx, uint16_t reg)
264 {
265     LCDx->MPUIR = reg;
266     while(LCD_IsBusy(LCDx)) __NOP();
267 
268     return LCDx->MPUDR;
269 }
270 
271 /******************************************************************************************************************************************
272 * 函数名称: MPULCD_DMAStart()
273 * 功能说明: MPU LCD DMA搬运显示数据
274 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
275 *           uint32_t * buff     要搬运的显示数据
276 *           uint16_t hpix       横向像素数,即每行像素数,必须是偶数
277 *           uint16_t vpix       纵向像素数,即行数
278 * 输    出: 无
279 * 注意事项: 无
280 ******************************************************************************************************************************************/
MPULCD_DMAStart(LCD_TypeDef * LCDx,uint32_t * buff,uint16_t hpix,uint16_t vpix)281 void MPULCD_DMAStart(LCD_TypeDef * LCDx, uint32_t * buff, uint16_t hpix, uint16_t vpix)
282 {
283     LCDx->MPUAR = (uint32_t)buff;
284 
285     LCDx->MPULEN = ((vpix - 1) << LCD_MPULEN_VPIX_Pos) |
286                    ((hpix - 1) << LCD_MPULEN_HPIX_Pos);
287 
288     LCDx->START |= (1 << LCD_START_GO_Pos);
289 }
290 
291 /******************************************************************************************************************************************
292 * 函数名称: MPULCD_DMABusy()
293 * 功能说明: MPU LCD DMA搬运显示数据忙查询
294 * 输    入: LCD_TypeDef * LCDx    指定要被设置的LCD,有效值包括LCD
295 * 输    出: uint32_t          1 搬运中   0 搬运完成
296 * 注意事项: 无
297 ******************************************************************************************************************************************/
MPULCD_DMABusy(LCD_TypeDef * LCDx)298 uint32_t MPULCD_DMABusy(LCD_TypeDef * LCDx)
299 {
300     return (LCDx->START & LCD_START_GO_Msk) ? 1 : 0;
301 }
302