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