1 /*!
2 \file gd32l23x_slcd.c
3 \brief SLCD driver
4
5 \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7
8 /*
9 Copyright (c) 2021, GigaDevice Semiconductor Inc.
10
11 Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13
14 1. Redistributions of source code must retain the above copyright notice, this
15 list of conditions and the following disclaimer.
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 3. Neither the name of the copyright holder nor the names of its contributors
20 may be used to endorse or promote products derived from this software without
21 specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34
35 #include "gd32l23x_slcd.h"
36
37 /*!
38 \brief reset SLCD register
39 \param[in] none
40 \param[out] none
41 \retval none
42 */
slcd_deinit(void)43 void slcd_deinit(void)
44 {
45 /* reset PMU */
46 rcu_periph_reset_enable(RCU_SLCDRST);
47 rcu_periph_reset_disable(RCU_SLCDRST);
48 }
49
50 /*!
51 \brief enable SLCD interface
52 \param[in] none
53 \param[out] none
54 \retval none
55 */
slcd_enable(void)56 void slcd_enable(void)
57 {
58 SLCD_CTL |= SLCD_CTL_SLCDON;
59 }
60
61 /*!
62 \brief disable SLCD interface
63 \param[in] none
64 \param[out] none
65 \retval none
66 */
slcd_disable(void)67 void slcd_disable(void)
68 {
69 SLCD_CTL &= ~SLCD_CTL_SLCDON;
70 }
71
72 /*!
73 \brief initialize SLCD interface
74 \param[in] prescaler: the SLCD prescaler
75 only one parameters can be selected which are shown as below:
76 \arg SLCD_PRESCALER_x(x=1,2,4,8...32768)
77 \param[in] divider: the SLCD divider
78 only one parameters can be selected which are shown as below:
79 \arg SLCD_DIVIDER_x(x=16,17,18,19...31)
80 \param[in] duty: the SLCD duty
81 only one parameters can be selected which are shown as below:
82 \arg SLCD_DUTY_STATIC: static duty
83 \arg SLCD_DUTY_1_x(x=2,3,4,8,6): 1/x duty
84 \param[in] bias: the SLCD voltage bias
85 only one parameters can be selected which are shown as below:
86 \arg SLCD_BIAS_1_x(x=2,3,4): 1/x voltage bias
87 \param[out] none
88 \retval none
89 */
slcd_init(uint32_t prescaler,uint32_t divider,uint32_t duty,uint32_t bias)90 void slcd_init(uint32_t prescaler, uint32_t divider, uint32_t duty, uint32_t bias)
91 {
92 uint32_t reg;
93 /* configure SLCD_CFG register */
94 reg = SLCD_CFG;
95 reg &= ~(SLCD_CFG_PSC | SLCD_CFG_DIV);
96 reg |= prescaler | divider;
97 SLCD_CFG = reg;
98 /* configure SLCD_CTL register */
99 reg = SLCD_CTL;
100 reg &= ~(SLCD_CTL_BIAS | SLCD_CTL_DUTY);
101 reg |= duty | bias;
102 SLCD_CTL = reg;
103 }
104
105 /*!
106 \brief enable SLCD enhance mode
107 \param[in] none
108 \param[out] none
109 \retval none
110 */
slcd_enhance_mode_enable(void)111 void slcd_enhance_mode_enable(void)
112 {
113 SLCD_CTL |= SLCD_CTL_VODEN;
114 }
115
116 /*!
117 \brief disable SLCD enhance mode
118 \param[in] none
119 \param[out] none
120 \retval none
121 */
slcd_enhance_mode_disable(void)122 void slcd_enhance_mode_disable(void)
123 {
124 SLCD_CTL &= ~SLCD_CTL_VODEN;
125 }
126
127 /*!
128 \brief select SLCD bias voltage
129 \param[in] bias_voltage: the SLCD voltage bias
130 only one parameter can be selected which is shown as below:
131 \arg SLCD_BIAS_1_4: 1/4 voltage bias
132 \arg SLCD_BIAS_1_2: 1/2 voltage bias
133 \arg SLCD_BIAS_1_3: 1/3 voltage bias
134 \param[out] none
135 \retval none
136 */
slcd_bias_voltage_select(uint32_t bias_voltage)137 void slcd_bias_voltage_select(uint32_t bias_voltage)
138 {
139 SLCD_CTL &= ~(SLCD_CTL_BIAS);
140 SLCD_CTL |= bias_voltage;
141 }
142
143 /*!
144 \brief select SLCD duty
145 \param[in] duty: duty select
146 only one parameter can be selected which is shown as below:
147 \arg SLCD_DUTY_STATIC: static duty
148 \arg SLCD_DUTY_1_2: 1/2 duty
149 \arg SLCD_DUTY_1_3: 1/3 duty
150 \arg SLCD_DUTY_1_4: 1/4 duty
151 \arg SLCD_DUTY_1_6: 1/6 duty
152 \arg SLCD_DUTY_1_8: 1/8 duty
153 \param[out] none
154 \retval none
155 */
slcd_duty_select(uint32_t duty)156 void slcd_duty_select(uint32_t duty)
157 {
158 SLCD_CTL &= ~(SLCD_CTL_DUTY);
159 SLCD_CTL |= duty;
160 }
161
162 /*!
163 \brief configure SLCD input clock
164 fSLCD = finclk/(pow(2, PRE)* DIV)
165 \param[in] prescaler: the prescaler factor
166 only one parameter can be selected which is shown as below:
167 \arg SLCD_PRESCALER_1: PRE = 0
168 \arg SLCD_PRESCALER_2: PRE = 1
169 \arg SLCD_PRESCALER_4: PRE = 2
170 \arg SLCD_PRESCALER_8: PRE = 3
171 \arg SLCD_PRESCALER_16: PRE = 4
172 \arg SLCD_PRESCALER_32: PRE = 5
173 \arg SLCD_PRESCALER_64: PRE = 6
174 \arg SLCD_PRESCALER_128: PRE = 7
175 \arg SLCD_PRESCALER_256: PRE = 8
176 \arg SLCD_PRESCALER_512: PRE = 9
177 \arg SLCD_PRESCALER_1024: PRE = 10
178 \arg SLCD_PRESCALER_2048: PRE = 11
179 \arg SLCD_PRESCALER_4096: PRE = 12
180 \arg SLCD_PRESCALER_8192: PRE = 13
181 \arg SLCD_PRESCALER_16384: PRE = 14
182 \arg SLCD_PRESCALER_32768: PRE = 15
183 \param[in] divider: the divider factor
184 only one parameter can be selected which is shown as below:
185 \arg SLCD_DIVIDER_x: x= 16..31, DIV = 16..31
186 \param[out] none
187 \retval none
188 */
slcd_clock_config(uint32_t prescaler,uint32_t divider)189 void slcd_clock_config(uint32_t prescaler, uint32_t divider)
190 {
191 uint32_t reg;
192
193 /* config the prescaler and the divider */
194 reg = SLCD_CFG;
195 reg &= ~(SLCD_CFG_PSC | SLCD_CFG_DIV);
196 reg |= (prescaler | divider);
197 SLCD_CFG = reg;
198 }
199
200 /*!
201 \brief configure SLCD blink mode
202 \param[in] mode: blink mode
203 only one parameter can be selected which is shown as below:
204 \arg SLCD_BLINKMODE_OFF: blink disabled
205 \arg SLCD_BLINKMODE_SEG0_COM0: blink enabled on SEG[0], COM[0]
206 \arg SLCD_BLINKMODE_SEG0_ALLCOM: blink enabled on SEG[0], all COM
207 \arg SLCD_BLINKMODE_ALLSEG_ALLCOM: blink enabled on all SEG and all COM
208 \param[in] blink_divider: the divider factor
209 only one parameter can be selected which is shown as below:
210 \arg SLCD_BLINK_FREQUENCY_DIV8: blink frequency = fSLCD/8
211 \arg SLCD_BLINK_FREQUENCY_DIV16: blink frequency = fSLCD/16
212 \arg SLCD_BLINK_FREQUENCY_DIV32: blink frequency = fSLCD/32
213 \arg SLCD_BLINK_FREQUENCY_DIV64: blink frequency = fSLCD/64
214 \arg SLCD_BLINK_FREQUENCY_DIV128: blink frequency = fSLCD/128
215 \arg SLCD_BLINK_FREQUENCY_DIV256: blink frequency = fSLCD/256
216 \arg SLCD_BLINK_FREQUENCY_DIV512: blink frequency = fSLCD/512
217 \arg SLCD_BLINK_FREQUENCY_DIV1024: blink frequency = fSLCD/1024
218 \param[out] none
219 \retval none
220 */
slcd_blink_mode_config(uint32_t mode,uint32_t blink_divider)221 void slcd_blink_mode_config(uint32_t mode, uint32_t blink_divider)
222 {
223 uint32_t reg;
224 reg = SLCD_CFG;
225 reg &= ~(SLCD_CFG_BLKMOD | SLCD_CFG_BLKDIV);
226 reg |= mode | blink_divider;
227 SLCD_CFG = reg;
228 }
229
230 /*!
231 \brief configure slcd_contrast_ratio
232 \param[in] contrast: the slcd contrast
233 only one parameters can be selected which are shown as below:
234 \arg SLCD_CONTRAST_LEVEL0:Maximum Voltage = 2.65V
235 \arg SLCD_CONTRAST_LEVEL1:Maximum Voltage = 2.80V
236 \arg SLCD_CONTRAST_LEVEL2:Maximum Voltage = 2.92V
237 \arg SLCD_CONTRAST_LEVEL3:Maximum Voltage = 3.08V
238 \arg SLCD_CONTRAST_LEVEL4:Maximum Voltage = 3.23V
239 \arg SLCD_CONTRAST_LEVEL5:Maximum Voltage = 3.37V
240 \arg SLCD_CONTRAST_LEVEL6:Maximum Voltage = 3.52V
241 \arg SLCD_CONTRAST_LEVEL7:Maximum Voltage = 3.67V
242 \param[out] none
243 \retval none
244 */
slcd_contrast_ratio_config(uint32_t contrast_ratio)245 void slcd_contrast_ratio_config(uint32_t contrast_ratio)
246 {
247 uint32_t reg;
248 reg = SLCD_CFG;
249 reg &= ~SLCD_CFG_CONR;
250 reg |= contrast_ratio;
251 SLCD_CFG = reg;
252 }
253
254 /*!
255 \brief configure SLCD dead time duration
256 \param[in] dead_time: configure the length of the dead time between frames
257 only one parameter can be selected which is shown as below:
258 \arg SLCD_DEADTIME_PERIOD_0: no dead time
259 \arg SLCD_DEADTIME_PERIOD_1: 1 phase inserted between couple of frame
260 \arg SLCD_DEADTIME_PERIOD_2: 2 phase inserted between couple of frame
261 \arg SLCD_DEADTIME_PERIOD_3: 3 phase inserted between couple of frame
262 \arg SLCD_DEADTIME_PERIOD_4: 4 phase inserted between couple of frame
263 \arg SLCD_DEADTIME_PERIOD_5: 5 phase inserted between couple of frame
264 \arg SLCD_DEADTIME_PERIOD_6: 6 phase inserted between couple of frame
265 \arg SLCD_DEADTIME_PERIOD_7: 7 phase inserted between couple of frame
266 \param[out] none
267 \retval none
268 */
slcd_dead_time_config(uint32_t dead_time)269 void slcd_dead_time_config(uint32_t dead_time)
270 {
271 uint32_t reg;
272
273 /* config dead time duration */
274 reg = SLCD_CFG;
275 reg &= ~(SLCD_CFG_DTD);
276 reg |= dead_time;
277 SLCD_CFG = reg;
278 }
279
280 /*!
281 \brief configure SLCD pulse on duration
282 \param[in] pulseonduration: specifies the slcd pulse on duration
283 only one parameters can be selected which are shown as below:
284 \arg SLCD_PULSEON_DURATION_0: pulse on duration = 0
285 \arg SLCD_PULSEON_DURATION_1: pulse on duration = 1*1/fPRE
286 \arg SLCD_PULSEON_DURATION_2: pulse on duration = 2*1/fPRE
287 \arg SLCD_PULSEON_DURATION_3: pulse on duration = 3*1/fPRE
288 \arg SLCD_PULSEON_DURATION_4: pulse on duration = 4*1/fPRE
289 \arg SLCD_PULSEON_DURATION_5: pulse on duration = 5*1/fPRE
290 \arg SLCD_PULSEON_DURATION_6: pulse on duration = 6*1/fPRE
291 \arg SLCD_PULSEON_DURATION_7: pulse on duration = 7*1/fPRE
292 \param[out] none
293 \retval none
294 */
slcd_pulse_on_duration_config(uint32_t duration)295 void slcd_pulse_on_duration_config(uint32_t duration)
296 {
297 uint32_t reg;
298 reg = SLCD_CFG;
299 reg &= ~SLCD_CFG_PULSE;
300 reg |= duration;
301 SLCD_CFG = reg;
302 }
303
304 /*!
305 \brief select SLCD common/segment pad
306 \param[in] NewValue: ENABLE or DISABLE
307 only one parameter can be selected which is shown as below:
308 \arg ENABLE: LCD_COM[7:4] pad select LCD_SEG[31:28]
309 \arg DISABLE: LCD_COM[7:4] pad select LCD_COM[7:4]
310 \param[out] none
311 \retval none
312 */
slcd_com_seg_remap(ControlStatus newvalue)313 void slcd_com_seg_remap(ControlStatus newvalue)
314 {
315 if(ENABLE == newvalue) {
316 SLCD_CTL |= SLCD_CTL_COMS;
317 } else {
318 SLCD_CTL &= ~(SLCD_CTL_COMS);
319 }
320 }
321
322 /*!
323 \brief select SLCD voltage source
324 \param[in] vsrc: specifies the slcd voltage source
325 only one parameters can be selected which are shown as below:
326 \arg SLCD_VOLTAGE_INTERNAL
327 \arg SLCD_VOLTAGE_EXTERNAL
328 \param[out] none
329 \retval none
330 */
slcd_voltage_source_select(uint8_t voltage_source)331 void slcd_voltage_source_select(uint8_t voltage_source)
332 {
333 if(SLCD_VOLTAGE_INTERNAL == voltage_source) {
334 SLCD_CTL &= ~SLCD_CTL_VSRC;
335 } else {
336 SLCD_CTL |= SLCD_CTL_VSRC;
337 }
338 }
339
340 /*!
341 \brief enable or disable permanent high drive
342 \param[in] newvalue: ENABLE or DISABLE
343 only one parameter can be selected which is shown as below:
344 \arg ENBALE: enable permanent high drive
345 \arg DISBALE: disable permanent high drive
346 \param[out] none
347 \retval none
348 */
slcd_high_drive_config(ControlStatus newvalue)349 void slcd_high_drive_config(ControlStatus newvalue)
350 {
351 if(ENABLE == newvalue) {
352 SLCD_CFG |= SLCD_CFG_HDEN;
353 } else {
354 SLCD_CFG &= ~(SLCD_CFG_HDEN);
355 }
356 }
357
358 /*!
359 \brief write SLCD data register
360 \param[in] register_number: refer to slcd_data_register_enum
361 only one parameter can be selected which is shown as below:
362 \arg SLCD_DATA_REG0: SLCD_DATA register 0
363 \arg SLCD_DATA_REG1: SLCD_DATA Register 1
364 \arg SLCD_DATA_REG2: SLCD_DATA register 2
365 \arg SLCD_DATA_REG3: SLCD_DATA Register 3
366 \arg SLCD_DATA_REG4: SLCD_DATA register 4
367 \arg SLCD_DATA_REG5: SLCD_DATA Register 5
368 \arg SLCD_DATA_REG6: SLCD_DATA register 6
369 \arg SLCD_DATA_REG7: SLCD_DATA Register 7
370 \param[in] data: the data write to the register
371 \param[out] none
372 \retval none
373 */
slcd_data_register_write(slcd_data_register_enum register_number,uint32_t data)374 void slcd_data_register_write(slcd_data_register_enum register_number, uint32_t data)
375 {
376 /* wtite data word to DATA register */
377 SLCD_DATA0_7((uint32_t)register_number) = data;
378 }
379
380 /*!
381 \brief update SLCD data request
382 \param[in] none
383 \param[out] none
384 \retval none
385 */
slcd_data_update_request(void)386 void slcd_data_update_request(void)
387 {
388 SLCD_STAT |= SLCD_STAT_UPRF;
389 }
390
391 /*!
392 \brief get SLCD flags
393 \param[in] flag: the slcd flags
394 only one parameter can be selected which is shown as below:
395 \arg SLCD_FLAG_ON: controller on flag
396 \arg SLCD_FLAG_SO: start of frame flag
397 \arg SLCD_FLAG_UPR: update data request flag
398 \arg SLCD_FLAG_UPD: update data done flag
399 \arg SLCD_FLAG_VRDY: voltage ready flag
400 \arg SLCD_FLAG_SYN: SLCD_CFG register synchronization flag
401 \param[out] none
402 \retval FlagStatus: SET or RESET
403 */
slcd_flag_get(uint32_t flag)404 FlagStatus slcd_flag_get(uint32_t flag)
405 {
406 if(RESET != (SLCD_STAT & flag)) {
407 return SET;
408 } else {
409 return RESET;
410 }
411 }
412
413 /*!
414 \brief clear SLCD flags
415 \param[in] flag: the slcd flags
416 one or more parameters can be selected which is shown as below:
417 \arg SLCD_FLAG_SOF: start of frame flag
418 \arg SLCD_FLAG_UPDF: update done flag
419 \param[out] none
420 \retval none
421 */
slcd_flag_clear(uint32_t flag)422 void slcd_flag_clear(uint32_t flag)
423 {
424 SLCD_STATC = flag;
425 }
426
427 /*!
428 \brief enable SLCD interrupt
429 \param[in] interrupt: slcd interrupt source
430 one or more parameters can be selected which is shown as below:
431 \arg SLCD_INT_SOF: start of frame interrupt
432 \arg SLCD_INT_UPD: update done interrupt
433 \param[out] none
434 \retval none
435 */
slcd_interrupt_enable(uint32_t interrupt)436 void slcd_interrupt_enable(uint32_t interrupt)
437 {
438 SLCD_CFG |= interrupt;
439 }
440
441 /*!
442 \brief disable SLCD interrupt
443 \param[in] interrupt: slcd interrupt source
444 one or more parameters can be selected which is shown as below:
445 \arg SLCD_INT_SOF: start of frame interrupt
446 \arg SLCD_INT_UPD: update done interrupt
447 \param[out] none
448 \retval none
449 */
slcd_interrupt_disable(uint32_t interrupt)450 void slcd_interrupt_disable(uint32_t interrupt)
451 {
452 SLCD_CFG &= ~interrupt;
453 }
454
455 /*!
456 \brief get SLCD interrupt flags
457 \param[in] int_flag: the slcd interrupt flag
458 only one parameter can be selected which is shown as below:
459 \arg SLCD_INT_FLAG_SOF: start of frame flag
460 \arg SLCD_INT_FLAG_UPD: update data done flag
461 \param[out] none
462 \retval FlagStatus: SET or RESET
463 */
slcd_interrupt_flag_get(uint32_t int_flag)464 FlagStatus slcd_interrupt_flag_get(uint32_t int_flag)
465 {
466 uint32_t val;
467 val = (SLCD_CFG & int_flag);
468 if((RESET != (SLCD_STAT & int_flag)) && (RESET != val)) {
469 return SET;
470 } else {
471 return RESET;
472 }
473 }
474
475 /*!
476 \brief clear SLCD interrupt flag
477 \param[in] int_flag: the slcd interrupt flag
478 one or more parameters can be selected which is shown as below:
479 \arg SLCD_INT_FLAG_SOF: start of frame flag
480 \arg SLCD_INT_FLAG_UPD: update data done flag
481 \param[out] none
482 \retval none
483 */
slcd_interrupt_flag_clear(uint32_t int_flag)484 void slcd_interrupt_flag_clear(uint32_t int_flag)
485 {
486 SLCD_STATC = int_flag;
487 }
488