1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http:// www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lcd_hardware_init.h"
17
18 #define LCD_SPI_CS(a) \
19 do { \
20 if (a) { \
21 gpio_bit_set(LCD_CS_GPIO_PORT, LCD_CS_PIN); \
22 } else { \
23 gpio_bit_reset(LCD_CS_GPIO_PORT, LCD_CS_PIN); \
24 } \
25 } while (0)
26 #define SPI_DCLK(a) \
27 do { \
28 if (a) { \
29 gpio_bit_set(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_PIN); \
30 } else { \
31 gpio_bit_reset(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_PIN); \
32 } \
33 } while (0)
34 #define SPI_SDA(a) \
35 do { \
36 if (a) { \
37 gpio_bit_set(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_PIN); \
38 } else { \
39 gpio_bit_reset(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_PIN); \
40 } \
41 } while (0)
42
43 #define DELAY_120_MS 120
44 #define DELAY_20_MS 20
45 #define WRITE_OFFSET 8
46 static void delay(uint32_t count);
47
48 /*!
49 \brief enable the LCD
50 \param[in] none
51 \param[out] none
52 \retval none
53 */
lcdEnable(void)54 void lcdEnable(void)
55 {
56 gpio_bit_set(LCD_CS_GPIO_PORT, LCD_CS_PIN);
57 }
58
59 /*!
60 \brief disable the LCD
61 \param[in] none
62 \param[out] none
63 \retval none
64 */
lcdDisable(void)65 void lcdDisable(void)
66 {
67 gpio_bit_reset(LCD_CS_GPIO_PORT, LCD_CS_PIN);
68 }
69
70 /*!
71 \brief configure the LCD control line
72 \param[in] none
73 \param[out] none
74 \retval none
75 */
lcdCtrlGpioConfig(void)76 void lcdCtrlGpioConfig(void)
77 {
78 /* enable GPIOs clock */
79 rcu_periph_clock_enable(LCD_CS_GPIO_CLK);
80 rcu_periph_clock_enable(LCD_RS_GPIO_CLK);
81
82 /* configure LCD_CS_GPIO_PORT(PD11) and LCD_RS_GPIO_PORT(PE3) */
83 gpio_mode_set(LCD_CS_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_CS_PIN);
84 gpio_output_options_set(LCD_CS_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_CS_PIN);
85
86 gpio_mode_set(LCD_RS_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_RS_PIN);
87 gpio_output_options_set(LCD_RS_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_RS_PIN);
88
89 /* set the chip select pin */
90 lcdCtrlLineSet(LCD_CS_GPIO_PORT, LCD_CS_PIN);
91 }
92
93 /*!
94 \brief set the LCD control line
95 \param[in] gpiox: control line GPIO
96 \arg LCD_CS_GPIO_PORT: LCD chip select GPIO
97 \arg LCD_RS_GPIO_PORT: LCD register/RAM selection GPIO
98 \param[in] gpiopin: control line pin
99 \arg LCD_CS_PIN: LCD chip select pin
100 \arg LCD_RS_PIN: LCD register/RAM selection pin
101 \param[out] none
102 \retval none
103 */
lcdCtrlLineSet(uint32_t gpiox,uint16_t gpiopin)104 void lcdCtrlLineSet(uint32_t gpiox, uint16_t gpiopin)
105 {
106 gpio_bit_set(gpiox, gpiopin);
107 }
108
109 /*!
110 \brief reset the LCD control line
111 \param[in] gpiox: control line GPIO
112 \arg LCD_CS_GPIO_PORT: LCD chip select GPIO
113 \arg LCD_RS_GPIO_PORT: LCD register/RAM selection GPIO
114 \param[in] gpiopin: control line pin
115 \arg LCD_CS_PIN: LCD chip select pin
116 \arg LCD_RS_PIN: LCD register/RAM selection pin
117 \param[out] none
118 \retval none
119 */
lcdCtrlLineReset(uint32_t gpiox,uint16_t gpiopin)120 void lcdCtrlLineReset(uint32_t gpiox, uint16_t gpiopin)
121 {
122 gpio_bit_reset(gpiox, gpiopin);
123 }
124
125 /*!
126 \brief configure the LCD SPI and it's GPIOs
127 \param[in] none
128 \param[out] none
129 \retval none
130 */
InitLcdSpiGpio(void)131 void InitLcdSpiGpio(void)
132 {
133 /* GPIO clock enable */
134 rcu_periph_clock_enable(LCD_SPI_SCK_GPIO_CLK);
135 rcu_periph_clock_enable(LCD_SPI_MOSI_GPIO_CLK);
136
137 /* configure the LCD SPI pins */
138 gpio_mode_set(LCD_SPI_SCK_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SPI_SCK_PIN);
139 gpio_output_options_set(LCD_SPI_SCK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SPI_SCK_PIN);
140 gpio_mode_set(LCD_SPI_MOSI_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SPI_MOSI_PIN);
141 gpio_output_options_set(LCD_SPI_MOSI_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SPI_MOSI_PIN);
142 }
143
144 /*!
145 \brief write command to select LCD register
146 \param[in] lcd_register: the address of the selected register
147 \param[out] none
148 \retval none
149 */
lcdCommandWrite(uint8_t lcd_register)150 void lcdCommandWrite(uint8_t lcd_register)
151 {
152 /* reset LCD_RS to send command */
153 lcdCtrlLineReset(LCD_RS_GPIO_PORT, LCD_RS_PIN);
154
155 /* reset LCD control line and send command */
156 lcdDisable();
157 while (RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TBE)) { }
158 spi_i2s_data_transmit(LCD_SPI, lcd_register);
159
160 /* wait until a data is sent */
161 while (RESET != spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TRANS)) { }
162
163 lcdEnable();
164 }
165
166 /*!
167 \brief write data to select LCD register
168 \param[in] value: the value that will be written to the selected register
169 \param[out] none
170 \retval none
171 */
lcdDateWrite(uint8_t value)172 void lcdDateWrite(uint8_t value)
173 {
174 /* set LCD_RS to send data */
175 lcdCtrlLineSet(LCD_RS_GPIO_PORT, LCD_RS_PIN);
176
177 /* reset LCD control line and send data */
178 lcdDisable();
179 while (RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TBE)) { }
180
181 spi_i2s_data_transmit(LCD_SPI, value);
182
183 /* wait until a data is sent */
184 while (RESET != spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TRANS)) { }
185
186 lcdEnable();
187 }
188
189 /*!
190 \brief GPIO emulated SPI byte write
191 \param[in] byte: data to be sent
192 \param[out] none
193 \retval none
194 */
spiIOByteWrite(unsigned char byteIn)195 void spiIOByteWrite(unsigned char byteIn)
196 {
197 unsigned char n;
198 unsigned char byte = byteIn;
199 for (n = 0; n < WRITE_OFFSET; n++) {
200 if (byte & 0x80) {
201 SPI_SDA(1);
202 } else {
203 SPI_SDA(0);
204 }
205 byte <<= 1;
206
207 SPI_DCLK(0);
208 SPI_DCLK(1);
209 }
210 }
211
212 /*!
213 \brief GPIO emulated SPI write command
214 \param[in] cmd: command to be sent
215 \param[out] none
216 \retval none
217 */
spiIOCommandWrite(uint8_t cmd)218 void spiIOCommandWrite(uint8_t cmd)
219 {
220 LCD_SPI_CS(0);
221 SPI_SDA(0);
222 SPI_DCLK(0);
223 SPI_DCLK(1);
224 spiIOByteWrite(cmd);
225
226 LCD_SPI_CS(1);
227 }
228
229 /*!
230 \brief GPIO emulated SPI write data
231 \param[in] tem_data: data to be sent
232 \param[out] none
233 \retval none
234 */
spiIODateWrite(uint8_t tem_data)235 void spiIODateWrite(uint8_t tem_data)
236 {
237 LCD_SPI_CS(0);
238 SPI_SDA(1);
239 SPI_DCLK(0);
240 SPI_DCLK(1);
241 spiIOByteWrite(tem_data);
242 LCD_SPI_CS(1);
243 }
244
InitLcdRegisterBefore(void)245 void InitLcdRegisterBefore(void)
246 {
247 delay(DELAY_120_MS);
248
249 LCD_SPI_CS(1);
250 delay(DELAY_20_MS);
251 LCD_SPI_CS(0);
252
253 spiIOCommandWrite(0xE0); // P-Gamma
254 spiIODateWrite(0x00);
255 spiIODateWrite(0x10);
256 spiIODateWrite(0x14);
257 spiIODateWrite(0x03);
258 spiIODateWrite(0x0E);
259 spiIODateWrite(0x04);
260 spiIODateWrite(0x36);
261 spiIODateWrite(0x56);
262 spiIODateWrite(0x4B);
263 spiIODateWrite(0x04);
264 spiIODateWrite(0x0C);
265 spiIODateWrite(0x0A);
266 spiIODateWrite(0x30);
267 spiIODateWrite(0x34);
268 spiIODateWrite(0x0F);
269
270 spiIOCommandWrite(0XE1); // N-Gamma
271 spiIODateWrite(0x00);
272 spiIODateWrite(0x0E);
273 spiIODateWrite(0x13);
274 spiIODateWrite(0x03);
275 spiIODateWrite(0x10);
276 spiIODateWrite(0x06);
277 spiIODateWrite(0x3E);
278 spiIODateWrite(0x34);
279 spiIODateWrite(0x55);
280 spiIODateWrite(0x05);
281 spiIODateWrite(0x0F);
282 spiIODateWrite(0x0E);
283 spiIODateWrite(0x3A);
284 spiIODateWrite(0x3E);
285 spiIODateWrite(0x0F);
286 }
InitLcdRegister(void)287 void InitLcdRegister(void)
288 {
289 InitLcdRegisterBefore();
290 spiIOCommandWrite(0XC0); // Power Control 1
291 spiIODateWrite(0x0F); // Vreg1out
292 spiIODateWrite(0x0C); // Verg2out
293
294 spiIOCommandWrite(0xC1); // Power Control 2
295 spiIODateWrite(0x41); // VGH,VGL
296
297 spiIOCommandWrite(0xC5); // Power Control 3
298 spiIODateWrite(0x00);
299 spiIODateWrite(0x21); // Vcom
300 spiIODateWrite(0x80);
301
302 spiIOCommandWrite(0x2a);
303 spiIODateWrite(0 >> WRITE_OFFSET);
304 spiIODateWrite(0);
305 spiIODateWrite(LCD_PIXEL_WIDTH >> WRITE_OFFSET);
306 spiIODateWrite((uint8_t)LCD_PIXEL_WIDTH);
307
308 spiIOCommandWrite(0x2b);
309 spiIODateWrite(0 >> WRITE_OFFSET);
310 spiIODateWrite(0);
311 spiIODateWrite(LCD_PIXEL_HEIGHT >> WRITE_OFFSET);
312 spiIODateWrite((uint8_t)LCD_PIXEL_HEIGHT);
313
314 spiIOCommandWrite(0x36); // Memory Access
315 spiIODateWrite(0x48);
316
317 spiIOCommandWrite(0x3A); // Interface Pixel Format
318 spiIODateWrite(0x66); // 18bit
319 // spiIODateWrite(0x55); // 16bit
320
321 spiIOCommandWrite(0XB0); // Interface Mode Control
322 spiIODateWrite(0x00);
323
324 spiIOCommandWrite(0xB1); // Frame rate
325 spiIODateWrite(0xA0); // 60Hz
326
327 spiIOCommandWrite(0xB4); // Display Inversion Control
328 spiIODateWrite(0x02); // 2-dot
329
330 spiIOCommandWrite(0XB6); // RGB/MCU Interface Control
331 spiIODateWrite(0x22); // MCU
332 spiIODateWrite(0x02); // Source,Gate scan dieection
333
334 spiIOCommandWrite(0XE9); // Set Image Function
335 spiIODateWrite(0x00); // disable 24 bit data input
336
337 spiIOCommandWrite(0xF7); // Adjust Control
338 spiIODateWrite(0xA9);
339 spiIODateWrite(0x51);
340 spiIODateWrite(0x2C);
341 spiIODateWrite(0x82); // D7 stream, loose
342
343 spiIOCommandWrite(0x21); // Normal Black
344
345 spiIOCommandWrite(0x11); // Sleep out
346 delay(DELAY_120_MS);
347 spiIOCommandWrite(0x29); // Display on
348
349 delay(DELAY_120_MS);
350 }
351
352 /*!
353 \brief insert a delay time
354 \param[in] count: delay time
355 \param[out] none
356 \retval none
357 */
delay(__IO uint32_t count)358 static void delay(__IO uint32_t count)
359 {
360 __IO uint32_t index = 0;
361 for (index = count; index != 0; index--) { }
362 }
363