1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2014, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
33 * Implementation of ILI9488 driver.
\r
37 /*----------------------------------------------------------------------------
\r
39 *----------------------------------------------------------------------------*/
\r
45 #ifdef BOARD_LCD_ILI9488
\r
47 /*----------------------------------------------------------------------------
\r
49 *----------------------------------------------------------------------------*/
\r
51 #define ILI9488 SPI0
\r
52 #define ILI9488_ID ID_SPI0
\r
54 /** Pio pins to configure. */
\r
55 static const Pin ILI9488_Reset[] = LCD_PIN_RESET;
\r
57 static const Pin ILI9488_Pwm[] = BOARD_LCD_BACKLIGHT_PIN;
\r
59 /** Pins to configure for the application. */
\r
60 static const Pin spi_pins[] = BOARD_LCD_PINS;
\r
63 /*----------------------------------------------------------------------------
\r
65 *----------------------------------------------------------------------------*/
\r
70 static void ILI9488_InitInterface(void)
\r
73 PIO_Configure(ILI9488_Reset, PIO_LISTSIZE(ILI9488_Reset));
\r
74 PIO_Configure(spi_pins, PIO_LISTSIZE(spi_pins));
\r
77 PIO_Configure(ILI9488_Pwm, PIO_LISTSIZE(ILI9488_Pwm));
\r
78 /* Enable PWM peripheral clock */
\r
79 PMC_EnablePeripheral(ID_PWM0);
\r
81 /* Set clock A and clock B */
\r
82 // set for 14.11 KHz for CABC control
\r
83 // mode = PWM_CLK_PREB(0x0A) | (PWM_CLK_DIVB(110)) |
\r
84 // PWM_CLK_PREA(0x0A) | (PWM_CLK_DIVA(110));
\r
85 PWMC_ConfigureClocks(PWM0, 14200, 0, BOARD_MCK);
\r
87 /* Configure PWM channel 1 for LED0 */
\r
88 PWMC_DisableChannel(PWM0, CHANNEL_PWM_LCD);
\r
90 PWMC_ConfigureChannel(PWM0, CHANNEL_PWM_LCD, PWM_CMR_CPRE_CLKA,0,PWM_CMR_CPOL);
\r
91 PWMC_SetPeriod(PWM0, CHANNEL_PWM_LCD, 16);
\r
92 PWMC_SetDutyCycle(PWM0, CHANNEL_PWM_LCD, 8);
\r
93 PWMC_EnableChannel(PWM0, CHANNEL_PWM_LCD);
\r
95 SPI_Configure(ILI9488, ILI9488_ID, (SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_PCS( ILI9488_cs )));
\r
96 SPI_ConfigureNPCS( ILI9488, ILI9488_cs,
\r
97 SPI_CSR_CPOL | SPI_CSR_BITS_9_BIT |
\r
98 SPI_DLYBS(100, BOARD_MCK) | SPI_DLYBCT(100, BOARD_MCK) |
\r
99 SPI_SCBR( 35000000, BOARD_MCK) ) ;
\r
101 SPI_Enable(ILI9488);
\r
106 * \brief Send Command to ILI9488.
\r
108 * \param reg Command Register address.
\r
111 static void ILI9488_SendCmd( uint8_t reg )
\r
113 SPI_Write(ILI9488, ILI9488_cs, ILI9488_CMD(reg));
\r
119 * \brief Write Parameter to ILI9488 Register.
\r
121 * \param data Data to be written.
\r
123 static void ILI9488_WriteReg( uint8_t data )
\r
125 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data));
\r
129 * \brief Write 16 bit Parameter to ILI9488 Register.
\r
131 * \param data Data to be written.
\r
133 static void ILI9488_WriteReg16( uint16_t data )
\r
135 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(((data & 0xFF00) >> 0x08)));
\r
136 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM((data & 0xFF)));
\r
140 * \brief Write 24 bit Parameter to ILI9488 Register.
\r
142 * \param data Data to be written.
\r
144 static void ILI9488_WriteReg24( uint32_t data )
\r
146 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(((data & 0xFF0000) >> 0x10)));
\r
147 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(((data & 0xFF00) >> 0x08)));
\r
148 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM((data & 0xFF)));
\r
152 * \brief Write 32 bit Parameter to ILI9488 Register.
\r
154 * \param data Data to be written.
\r
156 static void ILI9488_WriteReg32( uint32_t data )
\r
158 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM((data >> 0x18) & 0xFF));
\r
159 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(((data >> 0x10) & 0x00FF)));
\r
160 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(((data >> 0x08) & 0x0000FF)));
\r
161 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM((data & 0x000000FF)));
\r
165 * \brief Read data from ILI9488 Register.
\r
167 * \param reg Register address.
\r
169 * \return Readed data.
\r
171 static uint8_t ILI9488_ReadReg( uint8_t reg)
\r
175 SPI_Write(ILI9488, ILI9488_cs, ILI9488_CMD(reg));
\r
176 while(SPI_IsFinished(ILI9488) !=1);
\r
178 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(0xFF));
\r
179 while(SPI_IsFinished(ILI9488) !=1);
\r
180 value = (uint8_t)SPI_Read(ILI9488);
\r
182 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
183 ILI9488_WriteReg(0);
\r
189 * \brief Read data from ILI9488 Register.
\r
191 * \param reg Register address.
\r
193 * \return Readed data.
\r
195 static uint16_t ILI9488_ReadReg16( uint8_t reg)
\r
198 uint8_t SPI_CNT = 0x81;
\r
200 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
201 ILI9488_WriteReg(SPI_CNT);
\r
202 value = (ILI9488_ReadReg(reg) << 0x08);
\r
205 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
206 ILI9488_WriteReg(SPI_CNT);
\r
207 value |= ILI9488_ReadReg(reg);
\r
209 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
210 ILI9488_WriteReg(0);
\r
217 * \brief Read data from ILI9488 Register.
\r
219 * \param reg Register address.
\r
221 * \return Readed data.
\r
223 static uint32_t ILI9488_ReadReg24( uint8_t reg)
\r
226 uint8_t SPI_CNT = 0x81;
\r
228 //Set ILI9488 count to 0
\r
229 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
230 ILI9488_WriteReg(SPI_CNT);
\r
233 value = (ILI9488_ReadReg(reg) << 0x10);
\r
236 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
237 ILI9488_WriteReg(SPI_CNT);
\r
239 value |= (ILI9488_ReadReg(reg) << 0x08);
\r
242 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
243 ILI9488_WriteReg(SPI_CNT);
\r
244 value |= ILI9488_ReadReg(reg);
\r
246 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
247 ILI9488_WriteReg(0);
\r
256 * \brief Read data from ILI9488 Register.
\r
258 * \param reg Register address.
\r
260 * \return Readed data.
\r
262 static uint32_t ILI9488_ReadReg32( uint8_t reg)
\r
265 uint8_t SPI_CNT = 0x81;
\r
267 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
268 ILI9488_WriteReg(SPI_CNT);
\r
269 value = ILI9488_ReadReg(reg) ;
\r
273 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
274 ILI9488_WriteReg(SPI_CNT);
\r
275 value |= (ILI9488_ReadReg(reg) << 16);
\r
278 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
279 ILI9488_WriteReg(SPI_CNT);
\r
280 value |= (ILI9488_ReadReg(reg) << 8);
\r
283 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
284 ILI9488_WriteReg(SPI_CNT);
\r
285 value |= ILI9488_ReadReg(reg);
\r
287 ILI9488_SendCmd(ILI9488_CMD_SPI_READ_SETTINGS);
\r
288 ILI9488_WriteReg(0);
\r
293 static void ILI9488_NOP(void)
\r
295 ILI9488_SendCmd(ILI9488_CMD_NOP);
\r
303 * \brief Write data to ILI9488 Register.
\r
305 * \param reg Register address.
\r
306 * \param data Data to be written.
\r
308 void ILI9488_WriteSingle( LcdColor_t data )
\r
312 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
313 ILI9488_WriteReg24(data);
\r
318 * \brief Prpare to write data to ILI9488 Register.
\r
321 void ILI9488_WriteRAM_Prepare(void)
\r
323 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
327 * \brief Prpare to write data to ILI9488 Register.
\r
330 void ILI9488_ReadRAM_Prepare(void)
\r
332 ILI9488_SendCmd(ILI9488_CMD_MEMORY_READ);
\r
336 * \brief Write data to ILI9488 Register.
\r
338 * \param reg Register address.
\r
339 * \param data Data to be written.
\r
341 void ILI9488_WriteRAM( LcdColor_t data )
\r
343 ILI9488_WriteReg24(data);
\r
348 * \brief Write data to ILI9488 Register.
\r
350 * \param reg Register address.
\r
351 * \param data Data to be written.
\r
353 void ILI9488_WriteRAMBuffer( const LcdColor_t *pBuf, uint32_t size)
\r
358 for ( addr = 0 ; addr < size ; addr++ )
\r
360 ILI9488_WriteRAM(pBuf[addr]);
\r
364 void ILI9488_SetCursor(uint16_t x, uint16_t y)
\r
366 /* Set Horizontal Address Start Position */
\r
367 ILI9488_SendCmd(ILI9488_CMD_COLUMN_ADDRESS_SET);
\r
368 ILI9488_WriteReg16(x);
\r
369 ILI9488_WriteReg16(x+1);
\r
373 /* Set Horizontal Address End Position */
\r
374 ILI9488_SendCmd(ILI9488_CMD_PAGE_ADDRESS_SET);
\r
375 ILI9488_WriteReg16(y);
\r
376 ILI9488_WriteReg16(y+1);
\r
383 * \brief Initialize the ILI9488 controller.
\r
385 extern uint32_t ILI9488_Initialize( void )
\r
389 ILI9488_InitInterface();
\r
391 ILI9488_SendCmd(ILI9488_CMD_SOFTWARE_RESET);
\r
394 ILI9488_SendCmd(ILI9488_CMD_SLEEP_OUT);
\r
397 // make it tRGB and reverse the column order
\r
398 ILI9488_SendCmd(ILI9488_CMD_MEMORY_ACCESS_CONTROL);
\r
399 ILI9488_WriteReg(0x48);
\r
402 ILI9488_SendCmd(ILI9488_CMD_CABC_CONTROL_9); // set PWm to 14.11 KHz
\r
403 ILI9488_WriteReg(0x04);
\r
405 // ILI9488_SendCmd(ILI9488_CMD_COLMOD_PIXEL_FORMAT_SET); // set 16bit/pixel
\r
406 // ILI9488_WriteReg(0x05);
\r
408 /* Check ILI9488 chipid */
\r
409 chipid = ILI9488_ReadReg24(ILI9488_CMD_READ_ID4); /* Driver Code Read */
\r
410 if ( chipid != ILI9488_DEVICE_CODE )
\r
412 printf( "Read ILI9488 chip ID (0x%04x) error, skip initialization.\r\n", chipid ) ;
\r
417 ILI9488_SendCmd(ILI9488_CMD_NORMAL_DISP_MODE_ON);
\r
418 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_ON);
\r
427 * \brief Turn on the ILI9488.
\r
429 extern void ILI9488_On( void )
\r
431 ILI9488_SendCmd(ILI9488_CMD_PIXEL_OFF);
\r
432 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_ON);
\r
433 ILI9488_SendCmd(ILI9488_CMD_NORMAL_DISP_MODE_ON);
\r
438 * \brief Turn off the ILI9488.
\r
440 extern void ILI9488_Off( void )
\r
442 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_OFF);
\r
443 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_OFF);
\r
447 * \brief Power down the ILI9488.
\r
449 extern void ILI9488_PowerDown( void )
\r
458 * \brief Set a partial display window
\r
460 * Initialize a partial window on ILI9488
\r
461 * \param Start Starting address of window.
\r
462 * \param End End address of window.
\r
463 * \return 0 for successfull operation.
\r
465 extern void ILI9488_SetPartialWindow( uint16_t Start, uint16_t End)
\r
468 ILI9488_SendCmd(ILI9488_CMD_POWER_CONTROL_PARTIAL_5);
\r
469 ILI9488_WriteReg(0x44 ) ;
\r
471 ILI9488_SendCmd(ILI9488_CMD_PARTIAL_AREA);
\r
472 ILI9488_WriteReg16(Start ) ;
\r
473 ILI9488_WriteReg16(End) ;
\r
475 ILI9488_SendCmd(ILI9488_CMD_PARTIAL_MODE_ON);
\r
483 extern void ILI9488_SetWindow( uint16_t dwX, uint16_t dwY, uint16_t dwWidth, uint16_t dwHeight )
\r
485 uint16_t ColStart, ColEnd, RowStart, RowEnd;
\r
493 if ( ( ColEnd > (ILI9488_LCD_WIDTH)) || ( RowEnd > (ILI9488_LCD_HEIGHT)))
\r
495 printf("\n\rWindow too large\n\r");
\r
499 if ( ( ColEnd < ColStart) || ( RowEnd < RowStart) )
\r
501 printf("\n\rWindow's hight or width is not large enough\n\r");
\r
504 /* Set Horizontal Address Start Position */
\r
505 ILI9488_SendCmd(ILI9488_CMD_COLUMN_ADDRESS_SET);
\r
506 ILI9488_WriteReg16(ColStart);
\r
507 ILI9488_WriteReg16(ColEnd);
\r
511 /* Set Horizontal Address End Position */
\r
512 ILI9488_SendCmd(ILI9488_CMD_PAGE_ADDRESS_SET);
\r
513 ILI9488_WriteReg16(RowStart);
\r
514 ILI9488_WriteReg16(RowEnd);
\r
519 extern void ILI9488_SetDisplayLandscape( uint8_t dwRGB, uint8_t LandscaprMode )
\r
544 // make it tRGB and reverse the column order
\r
545 ILI9488_SendCmd(ILI9488_CMD_MEMORY_ACCESS_CONTROL);
\r
546 ILI9488_WriteReg(Value);
\r
549 ILI9488_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;
\r
552 extern void ILI9488_SetDisplayPortrait( uint8_t dwRGB )
\r
563 // make it tRGB and reverse the column order
\r
564 ILI9488_SendCmd(ILI9488_CMD_MEMORY_ACCESS_CONTROL);
\r
565 ILI9488_WriteReg(Value);
\r
568 ILI9488_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT) ;
\r
572 extern void ILI9488_SetVerticalScrollWindow( uint16_t dwStartAdd, uint16_t dwHeight )
\r
574 ILI9488_SendCmd(ILI9488_CMD_VERT_SCROLL_DEFINITION);
\r
575 ILI9488_WriteReg16(dwStartAdd-1);
\r
576 ILI9488_WriteReg16(dwStartAdd);
\r
577 ILI9488_WriteReg16((dwStartAdd + dwHeight + 1));
\r
581 extern void ILI9488_VerticalScroll( uint16_t wY )
\r
583 ILI9488_SendCmd(ILI9488_CMD_VERT_SCROLL_START_ADDRESS);
\r
584 ILI9488_WriteReg16(wY);
\r
589 extern void ILI9488_ExitScrollMode(void )
\r
591 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_OFF);
\r
592 ILI9488_SendCmd(ILI9488_CMD_NORMAL_DISP_MODE_ON);
\r
593 ILI9488_SendCmd(ILI9488_CMD_DISPLAY_ON);
\r
597 extern void ILI9488_TestPattern(void)
\r
601 ILI9488_SetWindow( 0, 0, 319, 479 ) ;
\r
603 data = COLOR_WHITE;
\r
604 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
605 for(i = 0; i< (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++)
\r
607 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 16));
\r
608 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 8));
\r
609 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data & 0xFF));
\r
612 ILI9488_SetWindow( 50, 50, 300, 300 ) ;
\r
614 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
615 for(i = 0; i< (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++)
\r
617 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 16));
\r
618 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 8));
\r
619 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data & 0xFF));
\r
622 ILI9488_SetWindow( 150, 150, 300, 300 ) ;
\r
623 data = COLOR_GREEN;
\r
624 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
625 for(i = 0; i< (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++)
\r
627 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 16));
\r
628 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 8));
\r
629 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data & 0xFF));
\r
632 ILI9488_SetWindow(200, 200, 300, 300 ) ;
\r
634 ILI9488_SendCmd(ILI9488_CMD_MEMORY_WRITE);
\r
635 for(i = 0; i< (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++)
\r
637 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 16));
\r
638 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data >> 8));
\r
639 SPI_Write(ILI9488, ILI9488_cs, ILI9488_PARAM(data & 0xFF));
\r