1 //*****************************************************************************
\r
3 // formike128x128x16.c - Display driver for the Formike Electronic
\r
4 // KWH015C04-F01 CSTN panel with an ST7637 controller.
\r
6 // Copyright (c) 2008 Luminary Micro, Inc. All rights reserved.
\r
8 // Software License Agreement
\r
10 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
\r
11 // exclusively on LMI's microcontroller products.
\r
13 // The software is owned by LMI and/or its suppliers, and is protected under
\r
14 // applicable copyright laws. All rights are reserved. You may not combine
\r
15 // this software with "viral" open-source software in order to form a larger
\r
16 // program. Any use in violation of the foregoing restrictions may subject
\r
17 // the user to criminal sanctions under applicable laws, as well as to civil
\r
18 // liability for the breach of the terms and conditions of this license.
\r
20 // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
21 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
23 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
24 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
26 // This is part of revision 2523 of the Stellaris Peripheral Driver Library.
\r
28 //*****************************************************************************
\r
30 //*****************************************************************************
\r
32 //! \addtogroup ek_lm3s3748_api
\r
35 //*****************************************************************************
\r
37 #include "hw_gpio.h"
\r
38 #include "hw_memmap.h"
\r
39 #include "hw_types.h"
\r
44 #include "formike128x128x16.h"
\r
47 //*****************************************************************************
\r
49 // Defines for the pins that are used to communicate with the ST7637.
\r
51 //*****************************************************************************
\r
52 #define LCD_A0_BASE GPIO_PORTB_BASE
\r
53 #define LCD_A0_PIN GPIO_PIN_2
\r
54 #define LCD_WR_BASE GPIO_PORTC_BASE
\r
55 #define LCD_WR_PIN GPIO_PIN_4
\r
56 #define LCD_RD_BASE GPIO_PORTC_BASE
\r
57 #define LCD_RD_PIN GPIO_PIN_5
\r
58 #define LCD_BL_BASE GPIO_PORTF_BASE
\r
59 #define LCD_BL_PIN GPIO_PIN_1
\r
60 #define LCD_DATA_BASE GPIO_PORTG_BASE
\r
62 //*****************************************************************************
\r
64 // Translates a 24-bit RGB color to a display driver-specific color.
\r
66 // \param c is the 24-bit RGB color. The least-significant byte is the blue
\r
67 // channel, the next byte is the green channel, and the third byte is the red
\r
70 // This macro translates a 24-bit RGB color into a value that can be written
\r
71 // into the display's frame buffer in order to reproduce that color, or the
\r
72 // closest possible approximation of that color.
\r
74 // \return Returns the display-driver specific color.
\r
76 //*****************************************************************************
\r
77 #define DPYCOLORTRANSLATE(c) ((((c) & 0x00ff0000) >> 19) | \
\r
78 ((((c) & 0x0000ff00) >> 5) & 0x000007e0) | \
\r
79 ((((c) & 0x000000ff) << 8) & 0x0000f800))
\r
81 //*****************************************************************************
\r
83 // Writes a data word to the ST7637.
\r
85 //*****************************************************************************
\r
87 WriteData(unsigned char ucData)
\r
90 // Write the data to the data bus.
\r
92 HWREG(LCD_DATA_BASE + GPIO_O_DATA + (0xff << 2)) = ucData;
\r
95 // Assert the write enable signal.
\r
97 HWREG(LCD_WR_BASE + GPIO_O_DATA + (LCD_WR_PIN << 2)) = 0;
\r
100 // Deassert the write enable signal.
\r
102 HWREG(LCD_WR_BASE + GPIO_O_DATA + (LCD_WR_PIN << 2)) = LCD_WR_PIN;
\r
105 //*****************************************************************************
\r
107 // Writes a command to the ST7637.
\r
109 //*****************************************************************************
\r
111 WriteCommand(unsigned char ucData)
\r
114 // Write the command to the data bus.
\r
116 HWREG(LCD_DATA_BASE + GPIO_O_DATA + (0xff << 2)) = ucData;
\r
119 // Set the A0 signal low, indicating a command.
\r
121 HWREG(LCD_A0_BASE + GPIO_O_DATA + (LCD_A0_PIN << 2)) = 0;
\r
124 // Assert the write enable signal.
\r
126 HWREG(LCD_WR_BASE + GPIO_O_DATA + (LCD_WR_PIN << 2)) = 0;
\r
129 // Deassert the write enable signal.
\r
131 HWREG(LCD_WR_BASE + GPIO_O_DATA + (LCD_WR_PIN << 2)) = LCD_WR_PIN;
\r
134 // Set the A0 signal high, indicating that following writes are data.
\r
136 HWREG(LCD_A0_BASE + GPIO_O_DATA + (LCD_A0_PIN << 2)) = LCD_A0_PIN;
\r
139 //*****************************************************************************
\r
141 //! Initializes the display driver.
\r
143 //! This function initializes the ST7637 display controller on the panel,
\r
144 //! preparing it to display data.
\r
148 //*****************************************************************************
\r
150 Formike128x128x16Init(void)
\r
152 unsigned long ulClockMS, ulCount;
\r
155 // Get the value to pass to SysCtlDelay() in order to delay for 1 ms.
\r
157 ulClockMS = SysCtlClockGet() / (3 * 1000);
\r
160 // Enable the GPIO peripherals used to interface to the ST7637.
\r
162 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
\r
163 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
\r
164 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
\r
165 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
\r
168 // Configure the pins that connect to the LCD as GPIO outputs.
\r
170 GPIOPinTypeGPIOOutput(LCD_A0_BASE, LCD_A0_PIN);
\r
171 GPIOPinTypeGPIOOutput(LCD_WR_BASE, LCD_WR_PIN);
\r
172 GPIOPinTypeGPIOOutput(LCD_RD_BASE, LCD_RD_PIN);
\r
173 GPIOPinTypeGPIOOutput(LCD_BL_BASE, LCD_BL_PIN);
\r
174 GPIOPinTypeGPIOOutput(LCD_DATA_BASE, 0xff);
\r
177 // Set the LCD control pins to their default values.
\r
179 GPIOPinWrite(LCD_A0_BASE, LCD_A0_PIN, LCD_A0_PIN);
\r
180 GPIOPinWrite(LCD_WR_BASE, LCD_WR_PIN | LCD_RD_PIN,
\r
181 LCD_WR_PIN | LCD_RD_PIN);
\r
182 GPIOPinWrite(LCD_BL_BASE, LCD_BL_PIN, 0);
\r
183 GPIOPinWrite(LCD_DATA_BASE, 0xff, 0x00);
\r
186 // Perform a software reset of the ST7637.
\r
188 WriteCommand(0x01);
\r
191 // Delay for 120ms.
\r
193 SysCtlDelay(ulClockMS * 120);
\r
196 // Disable auto-load of mask rom data.
\r
198 WriteCommand(0xD7);
\r
202 // Set the OTP control mode to read.
\r
204 WriteCommand(0xE0);
\r
210 SysCtlDelay(ulClockMS * 10);
\r
213 // Start the OTP read.
\r
215 WriteCommand(0xE3);
\r
220 SysCtlDelay(ulClockMS * 20);
\r
223 // Cancel the OTP read (it should have finished by now).
\r
225 WriteCommand(0xE1);
\r
228 // Turn off the display.
\r
230 WriteCommand(0x28);
\r
233 // Exit sleep mode.
\r
235 WriteCommand(0x11);
\r
240 SysCtlDelay(ulClockMS * 50);
\r
243 // Program the LCD supply voltage V0 to 14V.
\r
245 WriteCommand(0xC0);
\r
250 // Select an LCD bias voltage ratio of 1/12.
\r
252 WriteCommand(0xC3);
\r
256 // Enable the x8 booster circuit.
\r
258 WriteCommand(0xC4);
\r
262 // Invert the column scan direction for the panel.
\r
264 WriteCommand(0xB7);
\r
268 // Select 16bpp, 5-6-5 data input mode.
\r
270 WriteCommand(0x3A);
\r
274 // Select the memory scanning direction. The scanning mode does not matter
\r
275 // for this driver since the row/column selects will constrain the writes
\r
276 // to the desired area of the display.
\r
278 WriteCommand(0x36);
\r
282 // Turn on the display.
\r
284 WriteCommand(0x29);
\r
287 // Clear the contents of the display buffer.
\r
289 WriteCommand(0x2A);
\r
292 WriteCommand(0x2B);
\r
295 WriteCommand(0x2c);
\r
296 for(ulCount = 0; ulCount < (128 * 128); ulCount++)
\r
303 // Enable normal operation of the LCD.
\r
305 WriteCommand(0x13);
\r
308 //*****************************************************************************
\r
310 //! Turns on the backlight.
\r
312 //! This function turns on the backlight on the display.
\r
316 //*****************************************************************************
\r
318 Formike128x128x16BacklightOn(void)
\r
321 // Assert the signal that turns on the backlight.
\r
323 HWREG(LCD_BL_BASE + GPIO_O_DATA + (LCD_BL_PIN << 2)) = LCD_BL_PIN;
\r
326 //*****************************************************************************
\r
328 //! Turns off the backlight.
\r
330 //! This function turns off the backlight on the display.
\r
334 //*****************************************************************************
\r
336 Formike128x128x16BacklightOff(void)
\r
339 // Deassert the signal that turns on the backlight.
\r
341 HWREG(LCD_BL_BASE + GPIO_O_DATA + (LCD_BL_PIN << 2)) = 0;
\r
344 //*****************************************************************************
\r
346 //! Draws a pixel on the screen.
\r
348 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
349 //! display driver.
\r
350 //! \param lX is the X coordinate of the pixel.
\r
351 //! \param lY is the Y coordinate of the pixel.
\r
352 //! \param ulValue is the color of the pixel.
\r
354 //! This function sets the given pixel to a particular color. The coordinates
\r
355 //! of the pixel are assumed to be within the extents of the display.
\r
359 //*****************************************************************************
\r
361 Formike128x128x16PixelDraw(void *pvDisplayData, long lX, long lY,
\r
362 unsigned long ulValue)
\r
365 // Set the X address of the display cursor.
\r
367 WriteCommand(0x2a);
\r
372 // Set the Y address of the display cursor.
\r
374 WriteCommand(0x2b);
\r
379 // Write the pixel value.
\r
381 WriteCommand(0x2c);
\r
382 WriteData(ulValue >> 8);
\r
383 WriteData(ulValue);
\r
386 //*****************************************************************************
\r
388 //! Draws a horizontal sequence of pixels on the screen.
\r
390 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
391 //! display driver.
\r
392 //! \param lX is the X coordinate of the first pixel.
\r
393 //! \param lY is the Y coordinate of the first pixel.
\r
394 //! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1
\r
395 //! or 4 bit per pixel formats.
\r
396 //! \param lCount is the number of pixels to draw.
\r
397 //! \param lBPP is the number of bits per pixel; must be 1, 4, or 8.
\r
398 //! \param pucData is a pointer to the pixel data. For 1 and 4 bit per pixel
\r
399 //! formats, the most significant bit(s) represent the left-most pixel.
\r
400 //! \param pucPalette is a pointer to the palette used to draw the pixels.
\r
402 //! This function draws a horizontal sequence of pixels on the screen, using
\r
403 //! the supplied palette. For 1 bit per pixel format, the palette contains
\r
404 //! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
\r
405 //! contains 24-bit RGB values that must be translated before being written to
\r
410 //*****************************************************************************
\r
412 Formike128x128x16PixelDrawMultiple(void *pvDisplayData, long lX, long lY,
\r
413 long lX0, long lCount, long lBPP,
\r
414 const unsigned char *pucData,
\r
415 const unsigned char *pucPalette)
\r
417 unsigned long ulByte;
\r
420 // Set the extent of the line along the X axis.
\r
422 WriteCommand(0x2a);
\r
424 WriteData(lX + lCount - 1);
\r
427 // Set the Y address of the display cursor.
\r
429 WriteCommand(0x2b);
\r
434 // Write the data RAM write command.
\r
436 WriteCommand(0x2c);
\r
439 // Determine how to interpret the pixel data based on the number of bits
\r
445 // The pixel data is in 1 bit per pixel format.
\r
450 // Loop while there are more pixels to draw.
\r
455 // Get the next byte of image data.
\r
457 ulByte = *pucData++;
\r
460 // Loop through the pixels in this byte of image data.
\r
462 for(; (lX0 < 8) && lCount; lX0++, lCount--)
\r
465 // Draw this pixel in the appropriate color.
\r
467 lBPP = ((unsigned long *)pucPalette)[(ulByte >>
\r
469 WriteData(lBPP >> 8);
\r
474 // Start at the beginning of the next byte of image data.
\r
480 // The image data has been drawn.
\r
486 // The pixel data is in 4 bit per pixel format.
\r
491 // Loop while there are more pixels to draw. "Duff's device" is
\r
492 // used to jump into the middle of the loop if the first nibble of
\r
493 // the pixel data should not be used. Duff's device makes use of
\r
494 // the fact that a case statement is legal anywhere within a
\r
495 // sub-block of a switch statement. See
\r
496 // http://en.wikipedia.org/wiki/Duff's_device for detailed
\r
497 // information about Duff's device.
\r
505 // Get the upper nibble of the next byte of pixel data
\r
506 // and extract the corresponding entry from the
\r
509 ulByte = (*pucData >> 4) * 3;
\r
510 ulByte = (*(unsigned long *)(pucPalette + ulByte) &
\r
514 // Translate this palette entry and write it to the
\r
517 ulByte = DPYCOLORTRANSLATE(ulByte);
\r
518 WriteData(ulByte >> 8);
\r
522 // Decrement the count of pixels to draw.
\r
527 // See if there is another pixel to draw.
\r
533 // Get the lower nibble of the next byte of pixel
\r
534 // data and extract the corresponding entry from
\r
537 ulByte = (*pucData++ & 15) * 3;
\r
538 ulByte = (*(unsigned long *)(pucPalette + ulByte) &
\r
542 // Translate this palette entry and write it to the
\r
545 ulByte = DPYCOLORTRANSLATE(ulByte);
\r
546 WriteData(ulByte >> 8);
\r
550 // Decrement the count of pixels to draw.
\r
558 // The image data has been drawn.
\r
564 // The pixel data is in 8 bit per pixel format.
\r
569 // Loop while there are more pixels to draw.
\r
574 // Get the next byte of pixel data and extract the
\r
575 // corresponding entry from the palette.
\r
577 ulByte = *pucData++ * 3;
\r
578 ulByte = *(unsigned long *)(pucPalette + ulByte) & 0x00ffffff;
\r
581 // Translate this palette entry and write it to the screen.
\r
583 ulByte = DPYCOLORTRANSLATE(ulByte);
\r
584 WriteData(ulByte >> 8);
\r
589 // The image data has been drawn.
\r
596 //*****************************************************************************
\r
598 //! Flushes any cached drawing operations.
\r
600 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
601 //! display driver.
\r
603 //! This functions flushes any cached drawing operations to the display. This
\r
604 //! is useful when a local frame buffer is used for drawing operations, and the
\r
605 //! flush would copy the local frame buffer to the display. For the ST7637
\r
606 //! driver, the flush is a no operation.
\r
610 //*****************************************************************************
\r
612 Formike128x128x16Flush(void *pvDisplayData)
\r
615 // There is nothing to be done.
\r
619 //*****************************************************************************
\r
621 //! Draws a horizontal line.
\r
623 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
624 //! display driver.
\r
625 //! \param lX1 is the X coordinate of the start of the line.
\r
626 //! \param lX2 is the X coordinate of the end of the line.
\r
627 //! \param lY is the Y coordinate of the line.
\r
628 //! \param ulValue is the color of the line.
\r
630 //! This function draws a horizontal line on the display. The coordinates of
\r
631 //! the line are assumed to be within the extents of the display.
\r
635 //*****************************************************************************
\r
637 Formike128x128x16LineDrawH(void *pvDisplayData, long lX1, long lX2, long lY,
\r
638 unsigned long ulValue)
\r
641 // Set the extent of the line along the X axis.
\r
643 WriteCommand(0x2a);
\r
648 // Set the Y address of the display cursor.
\r
650 WriteCommand(0x2b);
\r
655 // Write the data RAM write command.
\r
657 WriteCommand(0x2c);
\r
660 // Loop through the pixels of this horizontal line.
\r
662 while(lX1++ <= lX2)
\r
665 // Write the pixel value.
\r
667 WriteData(ulValue >> 8);
\r
668 WriteData(ulValue);
\r
672 //*****************************************************************************
\r
674 //! Draws a vertical line.
\r
676 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
677 //! display driver.
\r
678 //! \param lX is the X coordinate of the line.
\r
679 //! \param lY1 is the Y coordinate of the start of the line.
\r
680 //! \param lY2 is the Y coordinate of the end of the line.
\r
681 //! \param ulValue is the color of the line.
\r
683 //! This function draws a vertical line on the display. The coordinates of the
\r
684 //! line are assumed to be within the extents of the display.
\r
688 //*****************************************************************************
\r
690 Formike128x128x16LineDrawV(void *pvDisplayData, long lX, long lY1, long lY2,
\r
691 unsigned long ulValue)
\r
694 // Set the X address of the display cursor.
\r
696 WriteCommand(0x2a);
\r
701 // Set the extent of the line along the Y axis.
\r
703 WriteCommand(0x2b);
\r
704 WriteData(lY1 + 1);
\r
705 WriteData(lY2 + 1);
\r
708 // Write the data RAM write command.
\r
710 WriteCommand(0x2c);
\r
713 // Loop through the pixels of this vertical line.
\r
715 while(lY1++ <= lY2)
\r
718 // Write the pixel value.
\r
720 WriteData(ulValue >> 8);
\r
721 WriteData(ulValue);
\r
725 //*****************************************************************************
\r
727 //! Fills a rectangle.
\r
729 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
730 //! display driver.
\r
731 //! \param pRect is a pointer to the structure describing the rectangle.
\r
732 //! \param ulValue is the color of the rectangle.
\r
734 //! This function fills a rectangle on the display. The coordinates of the
\r
735 //! rectangle are assumed to be within the extents of the display, and the
\r
736 //! rectangle specification is fully inclusive (i.e. both sXMin and sXMax are
\r
737 //! drawn, along with sYMin and sYMax).
\r
741 //*****************************************************************************
\r
743 Formike128x128x16RectFill(void *pvDisplayData, const tRectangle *pRect,
\r
744 unsigned long ulValue)
\r
749 // Set the extent of the rectangle along the X axis.
\r
751 WriteCommand(0x2a);
\r
752 WriteData(pRect->sXMin);
\r
753 WriteData(pRect->sXMax);
\r
756 // Set the extent of the rectangle along the Y axis.
\r
758 WriteCommand(0x2b);
\r
759 WriteData(pRect->sYMin + 1);
\r
760 WriteData(pRect->sYMax + 1);
\r
763 // Write the data RAM write command.
\r
765 WriteCommand(0x2c);
\r
768 // Loop through the pixels in this rectangle.
\r
770 for(lCount = ((pRect->sXMax - pRect->sXMin + 1) *
\r
771 (pRect->sYMax - pRect->sYMin + 1)); lCount > 0; lCount--)
\r
774 // Write the pixel value.
\r
776 WriteData(ulValue >> 8);
\r
777 WriteData(ulValue);
\r
781 //*****************************************************************************
\r
783 //! Translates a 24-bit RGB color to a display driver-specific color.
\r
785 //! \param pvDisplayData is a pointer to the driver-specific data for this
\r
786 //! display driver.
\r
787 //! \param ulValue is the 24-bit RGB color. The least-significant byte is the
\r
788 //! blue channel, the next byte is the green channel, and the third byte is the
\r
791 //! This function translates a 24-bit RGB color into a value that can be
\r
792 //! written into the display's frame buffer in order to reproduce that color,
\r
793 //! or the closest possible approximation of that color.
\r
795 //! \return Returns the display-driver specific color.
\r
797 //*****************************************************************************
\r
798 static unsigned long
\r
799 Formike128x128x16ColorTranslate(void *pvDisplayData, unsigned long ulValue)
\r
802 // Translate from a 24-bit RGB color to a 5-6-5 RGB color.
\r
804 return(DPYCOLORTRANSLATE(ulValue));
\r
807 //*****************************************************************************
\r
809 //! The display structure that describes the driver for the Formike Electronic
\r
810 //! KWH015C04-F01 CSTN panel with an ST7637 controller.
\r
812 //*****************************************************************************
\r
813 const tDisplay g_sFormike128x128x16 =
\r
819 Formike128x128x16PixelDraw,
\r
820 Formike128x128x16PixelDrawMultiple,
\r
821 Formike128x128x16LineDrawH,
\r
822 Formike128x128x16LineDrawV,
\r
823 Formike128x128x16RectFill,
\r
824 Formike128x128x16ColorTranslate,
\r
825 Formike128x128x16Flush
\r
828 //*****************************************************************************
\r
830 // Close the Doxygen group.
\r
833 //*****************************************************************************
\r
850 /* FreeRTOS.org demo wrappers. These are required so the prototypes for the
\r
851 functions are the same as for the display drivers used by other evaluation
\r
854 static tContext sContext;
\r
856 void vFormike128x128x16Clear( void )
\r
858 const tRectangle xRectangle = { 0, 0, 127, 127 };
\r
860 GrContextForegroundSet( &sContext, ClrBlack );
\r
861 GrRectFill( &sContext, &xRectangle );
\r
862 GrContextForegroundSet(&sContext, ClrWhite);
\r
864 /*-----------------------------------------------------------*/
\r
866 void vFormike128x128x16StringDraw( const char *pcString, unsigned long lX, unsigned long lY, unsigned char ucColor )
\r
868 GrContextForegroundSet(&sContext, ClrWhite);
\r
869 GrStringDraw( &sContext, pcString, strlen( pcString ), lX, lY, false );
\r
871 /*-----------------------------------------------------------*/
\r
873 void vFormike128x128x16Init( unsigned long ul )
\r
875 tRectangle rectScreen;
\r
876 const unsigned char *pcAppName = "www.FreeRTOS.org";
\r
880 Formike128x128x16Init();
\r
881 Formike128x128x16BacklightOn();
\r
882 GrContextInit(&sContext, &g_sFormike128x128x16);
\r
883 GrContextFontSet(&sContext, &g_sFontCmss12);
\r
884 rectScreen.sXMin = 0;
\r
886 /* Fill the screen with a black rectangle. */
\r
887 rectScreen.sYMin = 0;
\r
888 rectScreen.sXMax = g_sFormike128x128x16.usWidth - 1;
\r
889 rectScreen.sYMax = g_sFormike128x128x16.usHeight - 1;
\r
890 GrContextForegroundSet(&sContext, ClrBlack);
\r
891 GrRectFill(&sContext, &rectScreen);
\r
893 /*-----------------------------------------------------------*/
\r
895 void vFormike128x128x16ImageDraw( const unsigned char *pucImage, unsigned long ulX, unsigned long ulY, unsigned long ulWidth, unsigned long ulHeight )
\r
897 GrImageDraw( &sContext, pucImage, ( long ) ulX, ( long ) ulY);
\r