1 #include <drv_lcd.h>
2 #include <stdlib.h>
3
4 #define SPI_PORT spi1
5
6 uint slice_num;
7 LCD_ATTRIBUTES LCD;
8
9 /******************************************************************************
10 function : Hardware reset
11 parameter:
12 ******************************************************************************/
LCD_Reset(void)13 static void LCD_Reset(void)
14 {
15 DEV_Digital_Write(LCD_RST_PIN, 1);
16 rt_thread_mdelay(100);
17 DEV_Digital_Write(LCD_RST_PIN, 0);
18 rt_thread_mdelay(100);
19 DEV_Digital_Write(LCD_RST_PIN, 1);
20 rt_thread_mdelay(100);
21 }
22
23 /******************************************************************************
24 function : send command
25 parameter:
26 Reg : Command register
27 ******************************************************************************/
LCD_SendCommand(UBYTE Reg)28 static void LCD_SendCommand(UBYTE Reg)
29 {
30 DEV_Digital_Write(LCD_DC_PIN, 0);
31 DEV_Digital_Write(LCD_CS_PIN, 0);
32 DEV_SPI_WriteByte(Reg);
33 DEV_Digital_Write(LCD_CS_PIN, 1);
34 }
35
36 /******************************************************************************
37 function : send data
38 parameter:
39 Data : Write data
40 ******************************************************************************/
LCD_SendData_8Bit(UBYTE Data)41 static void LCD_SendData_8Bit(UBYTE Data)
42 {
43 DEV_Digital_Write(LCD_DC_PIN, 1);
44 DEV_Digital_Write(LCD_CS_PIN, 0);
45 DEV_SPI_WriteByte(Data);
46 DEV_Digital_Write(LCD_CS_PIN, 1);
47 }
48
49 /******************************************************************************
50 function : send data
51 parameter:
52 Data : Write data
53 ******************************************************************************/
LCD_SendData_16Bit(UWORD Data)54 static void LCD_SendData_16Bit(UWORD Data)
55 {
56 DEV_Digital_Write(LCD_DC_PIN, 1);
57 DEV_Digital_Write(LCD_CS_PIN, 0);
58 DEV_SPI_WriteByte((Data >> 8) & 0xFF);
59 DEV_SPI_WriteByte(Data & 0xFF);
60 DEV_Digital_Write(LCD_CS_PIN, 1);
61 }
62
63 /******************************************************************************
64 function : Initialize the lcd register
65 parameter:
66 ******************************************************************************/
LCD_InitReg(void)67 static void LCD_InitReg(void)
68 {
69 LCD_SendCommand(0x3A);
70 LCD_SendData_8Bit(0x05);
71
72 LCD_SendCommand(0xB2);
73 LCD_SendData_8Bit(0x0C);
74 LCD_SendData_8Bit(0x0C);
75 LCD_SendData_8Bit(0x00);
76 LCD_SendData_8Bit(0x33);
77 LCD_SendData_8Bit(0x33);
78
79 LCD_SendCommand(0xB7); // Gate Control
80 LCD_SendData_8Bit(0x35);
81
82 LCD_SendCommand(0xBB); // VCOM Setting
83 LCD_SendData_8Bit(0x19);
84
85 LCD_SendCommand(0xC0); // LCM Control
86 LCD_SendData_8Bit(0x2C);
87
88 LCD_SendCommand(0xC2); // VDV and VRH Command Enable
89 LCD_SendData_8Bit(0x01);
90 LCD_SendCommand(0xC3); // VRH Set
91 LCD_SendData_8Bit(0x12);
92 LCD_SendCommand(0xC4); // VDV Set
93 LCD_SendData_8Bit(0x20);
94
95 LCD_SendCommand(0xC6); // Frame Rate Control in Normal Mode
96 LCD_SendData_8Bit(0x01); // 110hz
97
98 LCD_SendCommand(0xD0); // Power Control 1
99 LCD_SendData_8Bit(0xA4);
100 LCD_SendData_8Bit(0xA1);
101
102 LCD_SendCommand(0xE0); // Positive Voltage Gamma Control
103 LCD_SendData_8Bit(0xD0);
104 LCD_SendData_8Bit(0x04);
105 LCD_SendData_8Bit(0x0D);
106 LCD_SendData_8Bit(0x11);
107 LCD_SendData_8Bit(0x13);
108 LCD_SendData_8Bit(0x2B);
109 LCD_SendData_8Bit(0x3F);
110 LCD_SendData_8Bit(0x54);
111 LCD_SendData_8Bit(0x4C);
112 LCD_SendData_8Bit(0x18);
113 LCD_SendData_8Bit(0x0D);
114 LCD_SendData_8Bit(0x0B);
115 LCD_SendData_8Bit(0x1F);
116 LCD_SendData_8Bit(0x23);
117
118 LCD_SendCommand(0xE1); // Negative Voltage Gamma Control
119 LCD_SendData_8Bit(0xD0);
120 LCD_SendData_8Bit(0x04);
121 LCD_SendData_8Bit(0x0C);
122 LCD_SendData_8Bit(0x11);
123 LCD_SendData_8Bit(0x13);
124 LCD_SendData_8Bit(0x2C);
125 LCD_SendData_8Bit(0x3F);
126 LCD_SendData_8Bit(0x44);
127 LCD_SendData_8Bit(0x51);
128 LCD_SendData_8Bit(0x2F);
129 LCD_SendData_8Bit(0x1F);
130 LCD_SendData_8Bit(0x1F);
131 LCD_SendData_8Bit(0x20);
132 LCD_SendData_8Bit(0x23);
133
134 LCD_SendCommand(0x21); // Display Inversion On
135
136 LCD_SendCommand(0x11); // Sleep Out
137
138 LCD_SendCommand(0x29); // Display On
139 }
140
141 /********************************************************************************
142 function: Set the resolution and scanning method of the screen
143 parameter:
144 Scan_dir: Scan direction
145 ********************************************************************************/
LCD_SetAttributes(UBYTE Scan_dir)146 static void LCD_SetAttributes(UBYTE Scan_dir)
147 {
148 // Get the screen scan direction
149 LCD.SCAN_DIR = Scan_dir;
150 UBYTE MemoryAccessReg = 0x00;
151
152 // Get GRAM and LCD width and height
153 if (Scan_dir == HORIZONTAL)
154 {
155 LCD.HEIGHT = LCD_WIDTH;
156 LCD.WIDTH = LCD_HEIGHT;
157 MemoryAccessReg = 0X70;
158 }
159 else
160 {
161 LCD.HEIGHT = LCD_HEIGHT;
162 LCD.WIDTH = LCD_WIDTH;
163 MemoryAccessReg = 0X00;
164 }
165
166 // Set the read / write scan direction of the frame memory
167 LCD_SendCommand(0x36); // MX, MY, RGB mode
168 LCD_SendData_8Bit(MemoryAccessReg); // 0x08 set RGB
169 }
170
171 /********************************************************************************
172 function : Initialize the lcd
173 parameter:
174 ********************************************************************************/
LCD_Init(UBYTE Scan_dir)175 void LCD_Init(UBYTE Scan_dir)
176 {
177 DEV_SET_PWM(50);
178
179 // Hardware reset
180 LCD_Reset();
181
182 // Set the resolution and scanning method of the screen
183 LCD_SetAttributes(Scan_dir);
184
185 // Set the initialization register
186 LCD_InitReg();
187 }
188
LCD_SetWindows(UWORD Xstart,UWORD Ystart,UWORD Xend,UWORD Yend)189 void LCD_SetWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend)
190 {
191 // set the X coordinates
192 LCD_SendCommand(0x2A);
193 LCD_SendData_8Bit((Xstart >> 8) & 0xFF);
194 LCD_SendData_8Bit(Xstart & 0xFF);
195 LCD_SendData_8Bit(((Xend - 1) >> 8) & 0xFF);
196 LCD_SendData_8Bit((Xend - 1) & 0xFF);
197
198 // set the Y coordinates
199 LCD_SendCommand(0x2B);
200 LCD_SendData_8Bit((Ystart >> 8) & 0xFF);
201 LCD_SendData_8Bit(Ystart & 0xFF);
202 LCD_SendData_8Bit(((Yend - 1) >> 8) & 0xFF);
203 LCD_SendData_8Bit((Yend - 1) & 0xFF);
204
205 LCD_SendCommand(0X2C);
206 }
207
208 /******************************************************************************
209 function : Clear screen
210 parameter:
211 ******************************************************************************/
LCD_Clear(UWORD Color)212 void LCD_Clear(UWORD Color)
213 {
214 UWORD j, i;
215 UWORD Image[LCD.WIDTH * LCD.HEIGHT];
216
217 Color = ((Color << 8) & 0xff00) | (Color >> 8);
218
219 for (j = 0; j < LCD.HEIGHT * LCD.WIDTH; j++)
220 {
221 Image[j] = Color;
222 }
223
224 LCD_SetWindows(0, 0, LCD.WIDTH, LCD.HEIGHT);
225 DEV_Digital_Write(LCD_DC_PIN, 1);
226 DEV_Digital_Write(LCD_CS_PIN, 0);
227 for (j = 0; j < LCD.HEIGHT; j++)
228 {
229 DEV_SPI_Write_nByte((uint8_t *) &Image[j * LCD.WIDTH], LCD.WIDTH * 2);
230 }
231 DEV_Digital_Write(LCD_CS_PIN, 1);
232 }
233
234 /******************************************************************************
235 function : Sends the image buffer in RAM to displays
236 parameter:
237 ******************************************************************************/
LCD_Display(UWORD * Image)238 void LCD_Display(UWORD *Image)
239 {
240 UWORD j;
241 LCD_SetWindows(0, 0, LCD.WIDTH, LCD.HEIGHT);
242 DEV_Digital_Write(LCD_DC_PIN, 1);
243 DEV_Digital_Write(LCD_CS_PIN, 0);
244 for (j = 0; j < LCD.HEIGHT; j++)
245 {
246 DEV_SPI_Write_nByte((uint8_t *) &Image[j * LCD.WIDTH], LCD.WIDTH * 2);
247 }
248 DEV_Digital_Write(LCD_CS_PIN, 1);
249 LCD_SendCommand(0x29);
250 }
251
252 /******************************************************************************
253 function : Sends the image buffer in RAM to displays
254 parameter:
255 Xstart : X direction Start coordinates
256 Ystart : Y direction Start coordinates
257 Xend : X direction end coordinates
258 Yend : Y direction end coordinates
259 Image : Written content
260 ******************************************************************************/
LCD_DisplayWindows(UWORD Xstart,UWORD Ystart,UWORD Xend,UWORD Yend,UWORD * Image)261 void LCD_DisplayWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD *Image)
262 {
263 // display
264 UDOUBLE Addr = 0;
265
266 UWORD j;
267 LCD_SetWindows(Xstart, Ystart, Xend, Yend);
268 DEV_Digital_Write(LCD_DC_PIN, 1);
269 DEV_Digital_Write(LCD_CS_PIN, 0);
270 for (j = Ystart; j < Yend - 1; j++)
271 {
272 Addr = Xstart + j * LCD.WIDTH;
273 DEV_SPI_Write_nByte((uint8_t *) &Image[Addr], (Xend - Xstart) * 2);
274 }
275 DEV_Digital_Write(LCD_CS_PIN, 1);
276 }
277
278 /******************************************************************************
279 function : Change the color of a point
280 parameter:
281 X : X coordinates
282 Y : Y coordinates
283 Color : Color
284 ******************************************************************************/
LCD_DisplayPoint(UWORD X,UWORD Y,UWORD Color)285 void LCD_DisplayPoint(UWORD X, UWORD Y, UWORD Color)
286 {
287 LCD_SetWindows(X, Y, X, Y);
288 LCD_SendData_16Bit(Color);
289 }
290
Handler_LCD(int signo)291 void Handler_LCD(int signo)
292 {
293 // System Exit
294 rt_kprintf("\r\nHandler:Program stop\r\n");
295 DEV_Module_Exit();
296 exit(0);
297 }
298
299 /**
300 * GPIO read and write
301 **/
DEV_Digital_Write(UWORD Pin,UBYTE Value)302 void DEV_Digital_Write(UWORD Pin, UBYTE Value)
303 {
304 gpio_put(Pin, Value);
305 }
306
DEV_Digital_Read(UWORD Pin)307 UBYTE DEV_Digital_Read(UWORD Pin)
308 {
309 return gpio_get(Pin);
310 }
311
312 /**
313 * GPIO Mode
314 **/
DEV_GPIO_Mode(UWORD Pin,UWORD Mode)315 void DEV_GPIO_Mode(UWORD Pin, UWORD Mode)
316 {
317 gpio_init(Pin);
318 if (Mode == 0 || Mode == GPIO_IN)
319 {
320 gpio_set_dir(Pin, GPIO_IN);
321 }
322 else
323 {
324 gpio_set_dir(Pin, GPIO_OUT);
325 }
326 }
327
328 /**
329 * SPI
330 **/
DEV_SPI_WriteByte(UBYTE Value)331 void DEV_SPI_WriteByte(UBYTE Value)
332 {
333 spi_write_blocking(SPI_PORT, &Value, 1);
334 }
335
DEV_SPI_Write_nByte(UBYTE pData[],UDOUBLE Len)336 void DEV_SPI_Write_nByte(UBYTE pData[], UDOUBLE Len)
337 {
338 spi_write_blocking(SPI_PORT, pData, Len);
339 }
340
DEV_GPIO_Init(void)341 void DEV_GPIO_Init(void)
342 {
343 DEV_GPIO_Mode(LCD_RST_PIN, 1);
344 DEV_GPIO_Mode(LCD_DC_PIN, 1);
345 DEV_GPIO_Mode(LCD_CS_PIN, 1);
346 DEV_GPIO_Mode(LCD_BL_PIN, 1);
347
348 DEV_Digital_Write(LCD_CS_PIN, 1);
349 DEV_Digital_Write(LCD_DC_PIN, 0);
350 DEV_Digital_Write(LCD_BL_PIN, 1);
351 }
352
353 /******************************************************************************
354 function: Module Initialize, the library and initialize the pins, SPI protocol
355 parameter:
356 Info:
357 ******************************************************************************/
DEV_Module_Init(void)358 UBYTE DEV_Module_Init(void)
359 {
360 // SPI Config
361 spi_init(SPI_PORT, 80000 * 1000);
362 gpio_set_function(LCD_CLK_PIN, GPIO_FUNC_SPI);
363 gpio_set_function(LCD_MOSI_PIN, GPIO_FUNC_SPI);
364
365 // GPIO Config
366 DEV_GPIO_Init();
367
368 // PWM Config
369 gpio_set_function(LCD_BL_PIN, GPIO_FUNC_PWM);
370 slice_num = pwm_gpio_to_slice_num(LCD_BL_PIN);
371 pwm_set_wrap(slice_num, 100);
372 pwm_set_chan_level(slice_num, PWM_CHAN_B, 1);
373 pwm_set_clkdiv(slice_num, 50);
374 pwm_set_enabled(slice_num, true);
375
376 rt_kprintf("DEV_Module_Init OK \r\n");
377
378 return 0;
379 }
380
DEV_SET_PWM(UBYTE Value)381 void DEV_SET_PWM(UBYTE Value)
382 {
383 if (Value < 0 || Value > 100)
384 {
385 rt_kprintf("DEV_SET_PWM Error \r\n");
386 }
387 else
388 {
389 pwm_set_chan_level(slice_num, PWM_CHAN_B, Value);
390 }
391 }
392
SPI_Init(void)393 UBYTE SPI_Init(void)
394 {
395 DEV_Module_Init();
396 return 0;
397 }
398
399 bool _swapBytes;
400 UDOUBLE dma_tx_channel;
401 dma_channel_config dma_tx_config;
402
403 /***************************************************************************************
404 ** Function name: dmaWait
405 ** Description: Wait until DMA is over (blocking!)
406 ***************************************************************************************/
dmaWait(void)407 void dmaWait(void)
408 {
409 while (dma_channel_is_busy(dma_tx_channel))
410 ;
411
412 // For SPI must also wait for FIFO to flush and reset format
413 while (spi_get_hw(SPI_PORT)->sr & SPI_SSPSR_BSY_BITS)
414 {
415 };
416 spi_set_format(SPI_PORT, 16, (spi_cpol_t) 0, (spi_cpha_t) 0, SPI_MSB_FIRST);
417 }
418
419 /***************************************************************************************
420 ** Function name: pushPixelsDMA
421 ** Description: Push pixels to TFT
422 ***************************************************************************************/
pushPixelsDMA(UWORD * image,UDOUBLE len)423 void pushPixelsDMA(UWORD* image, UDOUBLE len)
424 {
425 if ((len == 0))
426 return;
427
428 dmaWait();
429
430 channel_config_set_bswap(&dma_tx_config, !_swapBytes);
431
432 dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_PORT)->dr, (UWORD*) image, len, true);
433 }
434
initDMA(bool ctrl_cs)435 bool initDMA(bool ctrl_cs)
436 {
437 dma_tx_channel = dma_claim_unused_channel(true);
438 dma_tx_config = dma_channel_get_default_config(dma_tx_channel);
439
440 channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_16);
441 channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_PORT) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
442
443 return true;
444 }
445