Hello. I'm trying to interface an ILI9341-based TFT display with an MSP430F5529 using TI's graphics library and modified versions of the template drivers included in it. Unfortunately, the screen will only reset (turn off/on) and then display nothing but a white background when attempting to run TI's example files (in both debug and release mode. I have uploaded the code for the entire CCS Project and have posted the source for Template_Driver.h, Template_Driver.c, and main.c here (everything else is still the same as in the GRLIB provided by TI for their QVGA example).
Any advice on solving this problem would be greatly appreciated. Thanks!
EDIT: I added some more comments for the LCD's initialization sequence and what LCD pin is being sent high or low by my PxDIR and PxOUT commands within the posted template_driver.c file. These comments still need to be added to the zip file.
main.c:
/* --COPYRIGHT--,BSD
* Copyright (c) 2013, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
#include <stdint.h>
#include "hw_memmap.h"
#include "driverlibHeaders.h"
#include "grlib.h"
#include "LcdDriver/Template_Driver.h"
#include "Images/images.h"
#define MCLKFREQUENCY 25
uint16_t timeoutCounter;
tContext g_sContext;
tRectangle g_sRect;
int32_t stringWidth = 0;
void Board_init(void);
void Clock_init(void);
void Delay(void);
void main(void)
{
tRectangle myRectangle1 = { 5, 10, 60, 50};
tRectangle myRectangle2 = { 30, 20, 100, 60};
tRectangle myRectangle3 = { 0, 0, 101, 63};
// Stop WDT
WDT_A_hold(WDT_A_BASE);
// Basic GPIO initialization
Board_init();
Clock_init();
// Set up LCD
Template_DriverInit();
GrContextInit(&g_sContext, &g_sTemplate_Driver);
GrContextForegroundSet(&g_sContext, ClrBlack);
GrContextBackgroundSet(&g_sContext, ClrWhite);
GrContextFontSet(&g_sContext, &g_sFontFixed6x8);
GrClearDisplay(&g_sContext);
// Intro Screen
GrStringDrawCentered(&g_sContext,
"How to use MSP430",
AUTO_STRING_LENGTH,
51,
16,
TRANSPARENT_TEXT);
GrStringDrawCentered(&g_sContext,
"Graphics Library",
AUTO_STRING_LENGTH,
51,
32,
TRANSPARENT_TEXT);
GrStringDrawCentered(&g_sContext,
"Primitives",
AUTO_STRING_LENGTH,
51,
48,
TRANSPARENT_TEXT);
Delay();
GrClearDisplay(&g_sContext);
// Draw pixels and lines on the display
GrStringDraw(&g_sContext,
"Draw Pixels",
AUTO_STRING_LENGTH,
20,
0,
TRANSPARENT_TEXT);
GrStringDraw(&g_sContext,
"& Lines",
AUTO_STRING_LENGTH,
30,
10,
TRANSPARENT_TEXT);
GrPixelDraw(&g_sContext, 10, 10);
GrPixelDraw(&g_sContext, 10, 12);
GrPixelDraw(&g_sContext, 12, 12);
GrPixelDraw(&g_sContext, 12, 10);
GrLineDraw(&g_sContext, 15, 15, 60, 60);
GrLineDraw(&g_sContext, 10, 50, 90, 10);
GrLineDraw(&g_sContext,
0,
GrContextDpyHeightGet(&g_sContext) - 1,
GrContextDpyWidthGet(&g_sContext) - 1,
GrContextDpyHeightGet(&g_sContext) - 1);
Delay();
GrClearDisplay(&g_sContext);
// Draw circles on the display
GrStringDrawCentered(&g_sContext,
"Draw Circles",
AUTO_STRING_LENGTH,
51,
5,
TRANSPARENT_TEXT);
GrCircleDraw(&g_sContext, 30, 50, 10);
GrCircleFill(&g_sContext, 65, 37, 23);
Delay();
GrClearDisplay(&g_sContext);
// Draw rectangles on the display
GrStringDrawCentered(&g_sContext,
"Draw Rectangles",
AUTO_STRING_LENGTH,
51,
5,
TRANSPARENT_TEXT);
GrRectDraw(&g_sContext, &myRectangle1);
GrRectFill(&g_sContext, &myRectangle2);
// Text won't be visible on screen due to transparency
GrStringDrawCentered(&g_sContext,
"Normal Text",
AUTO_STRING_LENGTH,
65,
30,
TRANSPARENT_TEXT);
// Text draws foreground and background for opacity
GrStringDrawCentered(&g_sContext,
"Opaque Text",
AUTO_STRING_LENGTH,
65,
40,
OPAQUE_TEXT);
GrContextForegroundSet(&g_sContext, ClrWhite);
GrContextBackgroundSet(&g_sContext, ClrBlack);
// Text draws with inverted color to become visible
GrStringDrawCentered(&g_sContext,
"Invert Text",
AUTO_STRING_LENGTH,
65,
50,
TRANSPARENT_TEXT);
Delay();
GrClearDisplay(&g_sContext);
// Invert the foreground and background colors
GrContextForegroundSet(&g_sContext, ClrBlack);
GrContextBackgroundSet(&g_sContext, ClrWhite);
GrRectFill(&g_sContext, &myRectangle3);
GrContextForegroundSet(&g_sContext, ClrWhite);
GrContextBackgroundSet(&g_sContext, ClrBlack);
GrStringDrawCentered(&g_sContext,
"Invert Colors",
AUTO_STRING_LENGTH,
51,
5,
TRANSPARENT_TEXT);
GrRectDraw(&g_sContext, &myRectangle1);
GrRectFill(&g_sContext, &myRectangle2);
// Text won't be visible on screen due to transparency
GrStringDrawCentered(&g_sContext,
"Normal Text",
AUTO_STRING_LENGTH,
65,
30,
TRANSPARENT_TEXT);
// Text draws foreground and background for opacity
GrStringDrawCentered(&g_sContext,
"Opaque Text",
AUTO_STRING_LENGTH,
65,
40,
OPAQUE_TEXT);
GrContextForegroundSet(&g_sContext, ClrBlack);
GrContextBackgroundSet(&g_sContext, ClrWhite);
// Text draws with inverted color to become visible
GrStringDrawCentered(&g_sContext,
"Invert Text",
AUTO_STRING_LENGTH,
65,
50,
TRANSPARENT_TEXT);
Delay();
GrContextForegroundSet(&g_sContext, ClrBlack);
GrContextBackgroundSet(&g_sContext, ClrWhite);
GrClearDisplay(&g_sContext);
// Draw Images on the display
GrImageDraw(&g_sContext, &LPRocket_96x37_1BPP_UNCOMP, 3, 13);
Delay();
GrClearDisplay(&g_sContext);
GrImageDraw(&g_sContext, &TI_Logo_69x64_1BPP_UNCOMP, 16, 0);
while(1)
{
}
}
void Board_init(void)
{
// Setup XT1 and XT2
GPIO_setAsPeripheralModuleFunctionInputPin(
GPIO_PORT_P5,
GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN4 + GPIO_PIN5
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P1,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 +
GPIO_PIN3 + GPIO_PIN4 + GPIO_PIN5
);
// Configure LED ports
GPIO_setAsOutputPin(
GPIO_PORT_P1,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 +
GPIO_PIN3 + GPIO_PIN4 + GPIO_PIN5
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P8,
GPIO_PIN1 + GPIO_PIN2
);
GPIO_setAsOutputPin(
GPIO_PORT_P8,
GPIO_PIN1 + GPIO_PIN2
);
// Configure button ports
// Buttons on P1.7/P2.2 are inputs
/* GPIO_setAsInputPin(
GPIO_PORT_PA,
GPIO_PIN7 + GPIO_PIN10
);*/
// Configure CapTouch ports
/*GPIO_setOutputLowOnPin(
GPIO_PORT_P1,
GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6
);
GPIO_setAsOutputPin(
GPIO_PORT_P1,
GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P6,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6 + GPIO_PIN7
);
GPIO_setAsInputPin(
GPIO_PORT_P6,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6 + GPIO_PIN7
);
*/
// Configure Cma3000 ports
// ACCEL_INT pin is input
/* GPIO_setAsInputPin(
GPIO_PORT_P2,
GPIO_PIN5
);
// SCK
GPIO_setOutputLowOnPin(
GPIO_PORT_P2,
GPIO_PIN7
);
GPIO_setAsOutputPin(
GPIO_PORT_P2,
GPIO_PIN7
);
// ACCEL_SIMO, ACCEL_CS, ACCEL_PWR to low
GPIO_setOutputLowOnPin(
GPIO_PORT_P3,
GPIO_PIN3 + GPIO_PIN5 + GPIO_PIN6
);
// ACCEL_SOMI pin is input
GPIO_setAsInputPin(
GPIO_PORT_P3,
GPIO_PIN4
);
// ACCEL_SIMO, ACCEL_CS, ACCEL_PWR as outp
GPIO_setAsOutputPin(
GPIO_PORT_P3,
GPIO_PIN3 + GPIO_PIN5 + GPIO_PIN6
);
*/
// Configure Dogs102x6 ports
// LCD_C/D, LCD_RST
GPIO_setOutputLowOnPin(
GPIO_PORT_P6,
GPIO_PIN1 + GPIO_PIN3
);
GPIO_setAsOutputPin(
GPIO_PORT_P6,
GPIO_PIN1 + GPIO_PIN3
);
// LCD_CS, LCD_BL_EN
GPIO_setOutputLowOnPin(
GPIO_PORT_P6,
GPIO_PIN0 + GPIO_PIN6
);
GPIO_setAsOutputPin(
GPIO_PORT_P6,
GPIO_PIN0 + GPIO_PIN6
);
// SIMO, SCK
GPIO_setOutputLowOnPin(
GPIO_PORT_P2,
GPIO_PIN4 + GPIO_PIN5
);
// SOMI pin is input
GPIO_setAsInputPin(
GPIO_PORT_P4,
GPIO_PIN2
);
GPIO_setAsOutputPin(
GPIO_PORT_P4,
GPIO_PIN1 + GPIO_PIN3
);
// Configure SDCard ports
// SD_CS to high
GPIO_setOutputHighOnPin(
GPIO_PORT_P3,
GPIO_PIN7
);
GPIO_setAsOutputPin(
GPIO_PORT_P3,
GPIO_PIN7
);
// Configure Wheel ports
// A5 ADC input
GPIO_setAsInputPin(
GPIO_PORT_P6,
GPIO_PIN5
);
// POT_PWR
GPIO_setOutputLowOnPin(
GPIO_PORT_P8,
GPIO_PIN0
);
GPIO_setAsOutputPin(
GPIO_PORT_P8,
GPIO_PIN0
);
// Configure unused ports for low power
GPIO_setOutputLowOnPin(
GPIO_PORT_P2,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 +
GPIO_PIN6 + GPIO_PIN7
);
GPIO_setAsOutputPin(
GPIO_PORT_P2,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 +
GPIO_PIN3 + GPIO_PIN6 +GPIO_PIN7
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P1,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 + GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6
);
GPIO_setAsOutputPin(
GPIO_PORT_P1,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN3 + GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P4,
GPIO_PIN0 + GPIO_PIN3
);
GPIO_setAsOutputPin(
GPIO_PORT_P4,
GPIO_PIN0 + GPIO_PIN3
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P6,
GPIO_PIN4 + GPIO_PIN5
);
GPIO_setAsOutputPin(
GPIO_PORT_P6,
GPIO_PIN4 + GPIO_PIN5
);
GPIO_setOutputLowOnPin(
GPIO_PORT_P7,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 +
GPIO_PIN3 + GPIO_PIN5+ GPIO_PIN7
);
GPIO_setAsOutputPin(
GPIO_PORT_P7,
GPIO_PIN0 + GPIO_PIN1 + GPIO_PIN2 +
GPIO_PIN3 + GPIO_PIN5+ GPIO_PIN7
);
}
void Clock_init(void)
{
UCS_setExternalClockSource(UCS_BASE,
32768,
0);
// Set Vcore to accomodate for max. allowed system speed
PMM_setVCore(PMM_BASE,
PMM_CORE_LEVEL_3
);
// Use 32.768kHz XTAL as reference
UCS_LFXT1Start(
UCS_BASE,
UCS_XT1_DRIVE0,
UCS_XCAP_3
);
// Set system clock to max (25MHz)
UCS_initFLLSettle(
UCS_BASE,
25000,
762
);
SFR_enableInterrupt(SFR_BASE,
SFR_OSCILLATOR_FAULT_INTERRUPT
);
// Globally enable interrupts
__enable_interrupt();
}
void Delay(void)
{
__delay_cycles(MCLKFREQUENCY * 4);
}
template_driver.h
/* --COPYRIGHT--,BSD
* Copyright (c) 2013, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//*****************************************************************************
//
// Template_Driver.h - Prototypes for the Hitachi138x110 LCD
// display driver with a HD66753
// controller.
//
//*****************************************************************************
#ifndef __Template_Driver_H__
#define __Template_Driver_H__
//*****************************************************************************
//
// Include Files
//
//*****************************************************************************
/*Put any necessary include files here*/
//*****************************************************************************
//
// User Configuration for the LCD Driver
//
//*****************************************************************************
// Number of pixels on LCD X-axis
#define LCD_X_SIZE 320
// Number of pixels on LCD Y-axis
#define LCD_Y_SIZE 240
// Number of bits required to draw one pixel on the LCD screen
#define BPP 8
#define LCD_BUS_WIDTH 8
// Define LCD Screen Orientation Here
#define LANDSCAPE
//#define LANDSCAPE_FLIP
//#define PORTRAIT
//#define PORTRAIT_FLIP
#define LCD_DATAH_PINS 0xFF
#define LCD_DATAH_BASE GPIO_PORT3_BASE
// Data register addresses of Ports on MSP430
#define GPIO_PORTA_BASE 0x0200 // GPIO Port A
#define GPIO_PORTB_BASE 0x0220 // GPIO Port B
#define GPIO_PORTC_BASE 0x0240 // GPIO Port C
#define GPIO_PORTD_BASE 0x0260 // GPIO Port D
// Data register offsets into Ports on MSP430
#define GPIO_P1_DATA 0x0002 // GPIO Data
#define GPIO_P2_DATA 0x0003 // GPIO Data
#define GPIO_P3_DATA 0x0002 // GPIO Data
#define GPIO_P4_DATA 0x0003 // GPIO Data
#define GPIO_P5_DATA 0x0002 // GPIO Data
#define GPIO_P6_DATA 0x0003 // GPIO Data
#define GPIO_P7_DATA 0x0002 // GPIO Data
#define GPIO_P8_DATA 0x0003 // GPIO Data
// Control Pins
#define LCD_RST_BASE GPIO_PORT6_BASE
#define LCD_RST_PIN GPIO_PIN_3
#define LCD_RD_BASE GPIO_PORT6_BASE
#define LCD_RD_PIN GPIO_PIN_1
#define LCD_WR_BASE GPIO_PORT6_BASE
#define LCD_WR_PIN GPIO_PIN_0
#define LCD_DC_BASE GPIO_PORT6_BASE
#define LCD_DC_PIN GPIO_PIN_2
// Backlight Pins
#define LCD_BL_BASE GPIO_PORT6_BASE
#define LCD_BL_PIN GPIO_PIN_6
// GPIO Pin values
#define GPIO_PIN_0 0x0001 // GPIO pin 0
#define GPIO_PIN_1 0x0002 // GPIO pin 1
#define GPIO_PIN_2 0x0004 // GPIO pin 2
#define GPIO_PIN_3 0x0008 // GPIO pin 3
#define GPIO_PIN_4 0x0010 // GPIO pin 4
#define GPIO_PIN_5 0x0020 // GPIO pin 5
#define GPIO_PIN_6 0x0040 // GPIO pin 6
#define GPIO_PIN_7 0x0080 // GPIO pin 7
//*****************************************************************************
//
// Defines for the pins that are used to communicate with the LCD Driver
//
//*****************************************************************************
/*Define Pin Names here i.e. #define LCD_RESET_OUT P6OUT*/
//*****************************************************************************
//
// Defines for LCD driver configuration
//
//*****************************************************************************
/* Defines for pixels, colors, masks, etc. Anything Template_Driver.c needs*/
//*****************************************************************************
//
// This driver operates in four different screen orientations. They are:
//
// * Portrait - The screen is taller than it is wide. This is selected by defining
// PORTRAIT.
//
// * Landscape - The screen is wider than it is tall. This is selected by defining
// LANDSCAPE.
//
// * Portrait flip - The screen is taller than it is wide. This is
// selected by defining PORTRAIT_FLIP.
//
// * Landscape flip - The screen is wider than it is tall. This is
// selected by defining LANDSCAPE_FLIP.
//
// These can also be imagined in terms of screen rotation; if landscape mode is
// 0 degrees of screen rotation, portrait flip is 90 degrees of clockwise
// rotation, landscape flip is 180 degrees of rotation, and portrait is
// 270 degress of clockwise rotation.
//
// If no screen orientation is selected, "landscape" mode will be used.
//
//*****************************************************************************
#if ! defined(PORTRAIT) && ! defined(PORTRAIT_FLIP) && \
! defined(LANDSCAPE) && ! defined(LANDSCAPE_FLIP)
#define LANDSCAPE
#endif
//*****************************************************************************
//
// Various definitions controlling coordinate space mapping and drawing
// direction in the four supported orientations.
//
//*****************************************************************************
#ifdef PORTRAIT
#define MAPPED_X(x, y) (LCD_X_SIZE - (y) - 1)
#define MAPPED_Y(x, y) (x)
#endif
#ifdef LANDSCAPE
#define MAPPED_X(x, y) (x)
#define MAPPED_Y(x, y) (y)
#endif
#ifdef PORTRAIT_FLIP
#define MAPPED_X(x, y) (y)
#define MAPPED_Y(x, y) (LCD_Y_SIZE - (x) - 1)
#endif
#ifdef LANDSCAPE_FLIP
#define MAPPED_X(x, y) (LCD_X_SIZE - (x) - 1)
#define MAPPED_Y(x, y) (LCD_Y_SIZE - (y) - 1)
#endif
//*****************************************************************************
//
// Various LCD Controller command name labels and associated control bits
//
//*****************************************************************************
//*****************************************************************************
//
// Macros for the Display Driver
//
//*****************************************************************************
/* All macros can go here. This is typically the color translation function (example below)
and could also include Set_Address(), Write_Data(), etc. */
//
// Translates a 24-bit RGB color to a display driver-specific color.
//
// \param c is the 24-bit RGB color. The least-significant byte is the blue
// channel, the next byte is the green channel, and the third byte is the red
// channel.
//
// This macro translates a 24-bit RGB color into a value that can be written
// into the display's frame buffer in order to reproduce that color, or the
// closest possible approximation of that color. This particular example
// requires the 8-8-8 24 bit RGB color to convert into 5-6-5 16 bit RGB Color
// Your conversion should be made to fit your LCD settings.
//
// \return Returns the display-driver specific color
#define DPYCOLORTRANSLATE(c) ((((c) & 0x00f80000) >> 8) | \
(((c) & 0x0000fc00) >> 5) | \
(((c) & 0x000000f8) >> 3))
//*****************************************************************************
//
// Prototypes for the globals exported by this driver.
//
//*****************************************************************************
extern void Template_DriverInit(void);
extern const tDisplay g_sTemplate_Driver;
extern uint8_t Template_Memory[];
#define HWREG(x) \
(*((volatile unsigned int *)(x)))
#define HWREGH(x) \
(*((volatile unsigned short *)(x)))
#define HWREGB(x) \
(*((volatile unsigned char *)(x)))
#endif // __Template_Driver_H__
template_driver.c
/* --COPYRIGHT--,BSD
* Copyright (c) 2013, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --/COPYRIGHT--*/
//*****************************************************************************
//
// Template_Driver.c - Display driver for any LCD Controller. This file serves as
// a template for creating new LCD driver files
//
//*****************************************************************************
//
//! \addtogroup display_api
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
// READ ME
//
// This template driver is intended to be modified for creating new LCD drivers
// It is setup so that only Template_DriverPixelDraw() and DPYCOLORTRANSLATE()
// and some LCD size configuration settings in the header file Template_Driver.h
// are REQUIRED to be written. These functions are marked with the string
// "TemplateDisplayFix" in the comments so that a search through Template_Driver.c and
// Template_Driver.h can quickly identify the necessary areas of change.
//
// Template_DriverPixelDraw() is the base function to write to the LCD
// display. Functions like WriteData(), WriteCommand(), and SetAddress()
// are suggested to be used to help implement the Template_DriverPixelDraw()
// function, but are not required. SetAddress() should be used by other pixel
// level functions to help optimize them.
//
// This is not an optimized driver however and will significantly impact
// performance. It is highly recommended to first get the prototypes working
// with the single pixel writes, and then go back and optimize the driver.
// Please see application note www.ti.com/lit/pdf/slaa548 for more information
// on how to fully optimize LCD driver files. In int16_t, driver optimizations
// should take advantage of the auto-incrementing of the LCD controller.
// This should be utilized so that a loop of WriteData() can be used instead
// of a loop of Template_DriverPixelDraw(). The pixel draw loop contains both a
// SetAddress() + WriteData() compared to WriteData() alone. This is a big time
// saver especially for the line draws and Template_DriverPixelDrawMultiple.
// More optimization can be done by reducing function calls by writing macros,
// eliminating unnecessary instructions, and of course taking advantage of other
// features offered by the LCD controller. With so many pixels on an LCD screen
// each instruction can have a large impact on total drawing time.
//
//*****************************************************************************
//*****************************************************************************
//
// Include Files
//
//*****************************************************************************
#include <msp430.h>
#include "grlib.h"
#include "Template_Driver.h"
#define MCLK_FREQUENCY 25
#define MCLKFREQUENCY 25
//*****************************************************************************
//
// Global Variables
//
//*****************************************************************************
/* Global buffer for the display. This is especially useful on 1BPP, 2BPP, and 4BPP
displays. This allows you to update pixels while reading the neighboring pixels
from the buffer instead of a read from the LCD controller. A buffer is not required
as a read followed by a write can be used instead.*/
uint8_t Template_Memory[(LCD_X_SIZE * LCD_Y_SIZE * BPP + 7) / 8];
//*****************************************************************************
//
// Suggested functions to help facilitate writing the required functions below
//
//*****************************************************************************
// Writes data to the LCD controller
static void
WriteData(unsigned char usData)
{
/* Write data to the LCD controller. For instance this can be bit banged
with 6800 or 8080 protocol or this could be the SPI routine for a SPI LCD */
//P6DIR = BIT1;
//P6OUT |= BIT1; //RD HIGH
P6DIR = BIT0;
P6OUT &= ~BIT0; //CS LOW
P6DIR = BIT2;
P6OUT |= BIT2; //RS High
P3DIR = 0xFF; //D0-D7 are 3.0-3.7
P3OUT = usData;
_delay_cycles(MCLKFREQUENCY * 100000);
P6DIR = BIT0;
P6OUT |= BIT0; //CS HIGH
P6DIR = BIT1;
P6OUT |= BIT1; //RD HIGH
//COMMAND_MODE;
}
// Writes a command to the LCD controller
static void
WriteCommand(unsigned char ucCommand)
{
/* This function is typically very similar (sometimes the same) as WriteData()
The difference is that this is for the LCD to interpret commands instead of pixel
data. For instance in 8080 protocol, this means pulling the DC line low.*/
//P6DIR = BIT1;
//P6OUT |= BIT1; //RD HIGH
//COMMAND_MODE;
P7DIR = BIT4;
P7OUT &= BIT4;//CS LOW;
P6DIR = BIT1;
P6OUT |= BIT1; //RD HIGH
//COMMAND_MODE;
P6DIR = BIT2;
P6OUT |= BIT2; //RS High
P6DIR = BIT0;
P6OUT &= ~BIT0; //WR LOW
P3DIR = 0xFF;
P3OUT |= ucCommand; //D0-D7 are P3.0-P3.7
_delay_cycles(MCLKFREQUENCY * 100000);
P6DIR = BIT0;
P6OUT |= BIT0; //WR HIGH
}
// Sets the pixel address of the LCD driver
void SetAddress(int16_t lX, int16_t lY, int16_t mX, int16_t mY)
{
/* This function typically writes commands (using WriteCommand()) to the
LCD to tell it where to move the cursor for the next pixel to be drawn. */
WriteCommand(0x2A); //column set command
WriteData((lX >> 8) & 0xFF);
WriteData(lX & 0xFF);
WriteData((lY >> 8) & 0xFF);
WriteData(lY & 0xFF);
WriteData(1);
WriteData(0xDF);
P7DIR = BIT4;
P7OUT |= BIT4;//CS HIGH
WriteCommand(0x2B); // Page Set Command
WriteData((mX >> 8) & 0xFF);
WriteData(mX & 0xFF);
WriteData((mY >> 8) & 0xFF);
WriteData(mY & 0xFF);
WriteData(1);
WriteData(0x3F);// Partial Area D0-D7
P7DIR = BIT4;
P7OUT |= BIT4;//CS HIGH
WriteCommand(0x2C); // Memory Write
P7DIR = BIT4;
P7OUT |= BIT4;//CS High
}
// Initializes the pins required for the GPIO-based LCD interface.
// This function configures the GPIO pins used to control the LCD display
// when the basic GPIO interface is in use. On exit, the LCD controller
// has been reset and is ready to receive command and data writes.
static void
InitGPIOLCDInterface(void)
{
/* Initialize the hardware to configure the ports properly for communication */
volatile unsigned int i;
//
// Configure the pins that connect to the LCD as GPIO outputs.
//
P1DIR = 0xFF; // Set Port 1 as outputs
P1OUT = 0x00; // Set Port 1 outputs low
P2DIR = 0xFF; // Set Port 2 as outputs
P2OUT = 0x00; // Set Port 2 outputs low
P3DIR = 0xFF; // Set Port 3 as outputs
P3OUT = 0x00; // Set Port 3 outputs low
P4DIR = 0xFF; // Set Port 4 as outputs
P4OUT = 0x00; // Set Port 4 outputs low
//P5 used with XT2, User buttons, User LEDs, and LCD Backlight
P6DIR = 0xFF; // Set Port 6 as outputs
P6OUT = 0x00; // Set Port 6 outputs low
//P7 is touch screen (P7.0-P7.3) and RGB control (P7.4-P7.7) -- TI Comment
//
// Set the LCD Backlight on. P5.6 set high to enable
// TPS61165 Boost converter supports using P5.6 as PWM to dim backlight
//
P4DIR = BIT1;
P4OUT |= BIT1;
//
// Set the LCD control pins to their default values. This also asserts the
// LCD reset signal.
//
P6DIR = BIT1 + BIT0;
P6OUT |= BIT1 + BIT0; // Set WRn and RDn high (P6.0/P6.1)
//
// Delay for 1ms.
//
__delay_cycles(MCLKFREQUENCY * 1000);
//
// Deassert the LCD reset signal.
//
P6DIR = BIT2;
P6OUT |= BIT2; //RS High???? Should this be on RESET PIN?
//
// Delay for 1ms while the LCD comes out of reset.
//
__delay_cycles(MCLK_FREQUENCY * 1000);
}
// Initialize DisplayBuffer.
// This function initializes the display buffer and discards any cached data.
static void
InitLCDDisplayBuffer(void *pvDisplayData, uint16_t ulValue)
{
uint16_t i=0,j=0;
for(i =0; i< LCD_Y_SIZE; i++)
for(j =0; j< (LCD_X_SIZE * BPP + 7) / 8; j++)
Template_Memory[i * LCD_Y_SIZE + j] = ulValue;
}
// Initializes the display driver.
// This function initializes the LCD controller
//
// TemplateDisplayFix
void
Template_DriverInit(void)
{
/*Initialize the LCD controller.
This typically looks like:
InitGPIOLCDInterface();
InitLCDDisplayBuffer();
// Init LCD controller parameters
// Enable LCD
// Init Backlight
// Clear Screen
*/
InitGPIOLCDInterface();
InitLCDDisplayBuffer(&g_sTemplate_Driver, 0xFF);
P6DIR = BIT3;
P6OUT |= BIT3; //RESET High
_delay_cycles(1000);
P6DIR = BIT3;
P6OUT &= ~BIT3;//RESET Low
_delay_cycles(1000);
P6DIR = BIT3;
P6OUT |= BIT3;
_delay_cycles(1000);
WriteCommand(0x01);//Software reset
P7DIR = BIT4;
P7OUT |= BIT4;//CS High
__delay_cycles(MCLK_FREQUENCY * 1000);
WriteCommand(0x28);//Display off
WriteCommand(0xCF);//Power Control B
WriteData(0x00);
WriteData(0x81);//was 83
WriteData(0x30);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xED);//Power on Sequence Control
WriteData(0x64);
WriteData(0x03);
WriteData(0x12);
WriteData(0x81);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xCB);//Power Control A
WriteData(0x39);
WriteData(0x2C);
WriteData(0x00);
WriteData(0x34);
WriteData(0x02);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xCF);//Power Control B
WriteData(0x00);
WriteData(0xC1);
WriteData(0x30);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xE8);//Driver Timing Control A
WriteData(0x85);
WriteData(0x00);
WriteData(0x78);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xEA);//Driver Timing Control B
WriteData(0x00);
WriteData(0x00);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xED);//Power on Sequence Control
WriteData(0x64);
WriteData(0x03);
WriteData(0x12);
WriteData(0x81);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xF7);//Pump Ratio Control
WriteData(0x20);
P7DIR = BIT4;
P7OUT |= BIT4;//CS High
WriteCommand(0xC0);//Power Control 1
WriteData(0x23);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xC1);// Power Control 2
WriteData(0x10);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xC5);//VCOM Control 1
WriteData(0x2B);
WriteData(0x2B);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0x36);//Memory Access Control
WriteData(0x48);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xB1);//Frame Rate Control (in normal/full colors)
WriteData(0x00);
WriteData(0x1B);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xB6);//Display Function Control
WriteData(0x0A);
WriteData(0x02);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xF2);//Enable 3 Gamma
WriteData(0x02);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0x3A);//Pixel Format Set
WriteData(0x05);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0x26);//Gamma Set
WriteData(0x01);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xE0);//Positive Gamma Correction
WriteData(0x0f);
WriteData(0x31);
WriteData(0x2B);
WriteData(0x0C);
WriteData(0x0E);
WriteData(0x08);
WriteData(0x4E);
WriteData(0xF1);
WriteData(0x37);
WriteData(0x07);
WriteData(0x10);
WriteData(0x03);
WriteData(0x0E);
WriteData(0x09);
WriteData(0x00);
P7DIR = BIT4;
P7OUT |= BIT4;
WriteCommand(0xE1);//Negative Gamma Correction
WriteData(0x00);
WriteData(0x0E);
WriteData(0x14);
WriteData(0x03);
WriteData(0x11);
WriteData(0x07);
WriteData(0x31);
WriteData(0xC1);
WriteData(0x48);
WriteData(0x08);
WriteData(0x0F);
WriteData(0x0C);
WriteData(0x31);
WriteData(0x36);
WriteData(0x0F);
P7DIR = BIT4;
P7OUT |= BIT4;
/*
WriteCommand(0x2a);
WriteData(0x00);
WriteData(0x00);
WriteData(0x00);
WriteData(0xEF);
WriteCommand(0x2b);
WriteData(0x00);
WriteData(0x00);
WriteData(0x01);
WriteData(0x3F);
WriteCommand(0xb7);
WriteData(0x07);
WriteCommand(0xb6);
WriteData(0x0a);
WriteData(0x82);
WriteData(0x27);
WriteData(0x00);
*/
WriteCommand(0x11);//Sleep OUT
P7DIR = BIT4;
P7OUT |= BIT4;
__delay_cycles(MCLK_FREQUENCY * 120);
WriteCommand(0x29);//Display ON
P7DIR = BIT4;
P7OUT |= BIT4;
}
//*****************************************************************************
//
// All the following functions (below) for the LCD driver are required by grlib
//
//*****************************************************************************
//*****************************************************************************
//
//! Draws a pixel on the screen.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param lX is the X coordinate of the pixel.
//! \param lY is the Y coordinate of the pixel.
//! \param ulValue is the color of the pixel.
//!
//! This function sets the given pixel to a particular color. The coordinates
//! of the pixel are assumed to be within the extents of the display.
//!
//! \return None.
//
//*****************************************************************************
// TemplateDisplayFix
static void
Template_DriverPixelDraw(void *pvDisplayData, int16_t lX, int16_t lY,
uint16_t ulValue)
{
/* This function already has checked that the pixel is within the extents of
the LCD screen and the color ulValue has already been translated to the LCD.
This function typically looks like:
// Interpret pixel data (if needed)
// Update buffer (if applicable)
// Template_Memory[lY * LCD_Y_SIZE + (lX * BPP / 8)] = , |= , &= ...
// Template memory must be modified at the bit level for 1/2/4BPP displays
// SetAddress(MAPPED_X(lX, lY), MAPPED_Y(lX, lY));
// WriteData(ulValue);
*/
SetAddress(lX, lX, lY,lY);
WriteData((unsigned char )((ulValue>>8)&0xff));
WriteData((unsigned char )(ulValue&0xff));
P6DIR = BIT0;
P6OUT |= BIT0;
}
//*****************************************************************************
//
//! Draws a horizontal sequence of pixels on the screen.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param lX is the X coordinate of the first pixel.
//! \param lY is the Y coordinate of the first pixel.
//! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1
//! or 4 bit per pixel formats.
//! \param lCount is the number of pixels to draw.
//! \param lBPP is the number of bits per pixel; must be 1, 4, or 8.
//! \param pucData is a pointer to the pixel data. For 1 and 4 bit per pixel
//! formats, the most significant bit(s) represent the left-most pixel.
//! \param pucPalette is a pointer to the palette used to draw the pixels.
//!
//! This function draws a horizontal sequence of pixels on the screen, using
//! the supplied palette. For 1 bit per pixel format, the palette contains
//! pre-translated colors; for 4 and 8 bit per pixel formats, the palette
//! contains 24-bit RGB values that must be translated before being written to
//! the display.
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverPixelDrawMultiple(void *pvDisplayData, int16_t lX,
int16_t lY, int16_t lX0, int16_t lCount,
int16_t lBPP,
const uint8_t *pucData,
const uint16_t *pucPalette)
{
uint16_t ulByte;
//
// Determine how to interpret the pixel data based on the number of bits
// per pixel.
//
switch(lBPP)
{
// The pixel data is in 1 bit per pixel format
case 1:
{
// Loop while there are more pixels to draw
while(lCount > 0)
{
// Get the next byte of image data
ulByte = *pucData++;
// Loop through the pixels in this byte of image data
for(; (lX0 < 8) && lCount; lX0++, lCount--)
{
// Draw this pixel in the appropriate color
Template_DriverPixelDraw(pvDisplayData, lX++, lY,
((uint16_t *)pucPalette)[(ulByte >> (7 - lX0)) & 1]);
}
// Start at the beginning of the next byte of image data
lX0 = 0;
}
// The image data has been drawn
break;
}
// The pixel data is in 2 bit per pixel format
case 2:
{
// Loop while there are more pixels to draw
while(lCount > 0)
{
// Get the next byte of image data
ulByte = *pucData++;
// Loop through the pixels in this byte of image data
for(; (lX0 < 4) && lCount; lX0++, lCount--)
{
// Draw this pixel in the appropriate color
Template_DriverPixelDraw(pvDisplayData, lX++, lY,
((uint16_t *)pucPalette)[(ulByte >> (6 - (lX0 << 1))) & 3]);
}
// Start at the beginning of the next byte of image data
lX0 = 0;
}
// The image data has been drawn
break;
}
// The pixel data is in 4 bit per pixel format
case 4:
{
// Loop while there are more pixels to draw. "Duff's device" is
// used to jump into the middle of the loop if the first nibble of
// the pixel data should not be used. Duff's device makes use of
// the fact that a case statement is legal anywhere within a
// sub-block of a switch statement. See
// http://en.wikipedia.org/wiki/Duff's_device for detailed
// information about Duff's device.
switch(lX0 & 1)
{
case 0:
while(lCount)
{
// Get the upper nibble of the next byte of pixel data
// and extract the corresponding entry from the palette
ulByte = (*pucData >> 4);
ulByte = (*(uint16_t *)(pucPalette + ulByte));
// Write to LCD screen
Template_DriverPixelDraw(pvDisplayData, lX++, lY, ulByte);
// Decrement the count of pixels to draw
lCount--;
// See if there is another pixel to draw
if(lCount)
{
case 1:
// Get the lower nibble of the next byte of pixel
// data and extract the corresponding entry from
// the palette
ulByte = (*pucData++ & 15);
ulByte = (*(uint16_t *)(pucPalette + ulByte));
// Write to LCD screen
Template_DriverPixelDraw(pvDisplayData, lX++, lY, ulByte);
// Decrement the count of pixels to draw
lCount--;
}
}
}
// The image data has been drawn.
break;
}
// The pixel data is in 8 bit per pixel format
case 8:
{
// Loop while there are more pixels to draw
while(lCount--)
{
// Get the next byte of pixel data and extract the
// corresponding entry from the palette
ulByte = *pucData++;
ulByte = (*(uint16_t *)(pucPalette + ulByte));
// Write to LCD screen
Template_DriverPixelDraw(pvDisplayData, lX++, lY, ulByte);
}
// The image data has been drawn
break;
}
}
}
//*****************************************************************************
//
//! Draws a horizontal line.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param lX1 is the X coordinate of the start of the line.
//! \param lX2 is the X coordinate of the end of the line.
//! \param lY is the Y coordinate of the line.
//! \param ulValue is the color of the line.
//!
//! This function draws a horizontal line on the display. The coordinates of
//! the line are assumed to be within the extents of the display.
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverLineDrawH(void *pvDisplayData, int16_t lX1, int16_t lX2,
int16_t lY, uint16_t ulValue)
{
/* Ideally this function shouldn't call pixel draw. It should have it's own
definition using the built in auto-incrementing of the LCD controller and its
own calls to SetAddress() and WriteData(). Better yet, SetAddress() and WriteData()
can be made into macros as well to eliminate function call overhead. */
do
{
Template_DriverPixelDraw(pvDisplayData, lX1, lY, ulValue);
}
while(lX1++ < lX2);
}
//*****************************************************************************
//
//! Draws a vertical line.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param lX is the X coordinate of the line.
//! \param lY1 is the Y coordinate of the start of the line.
//! \param lY2 is the Y coordinate of the end of the line.
//! \param ulValue is the color of the line.
//!
//! This function draws a vertical line on the display. The coordinates of the
//! line are assumed to be within the extents of the display.
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverLineDrawV(void *pvDisplayData, int16_t lX, int16_t lY1,
int16_t lY2, uint16_t ulValue)
{
do
{
Template_DriverPixelDraw(pvDisplayData, lX, lY1, ulValue);
}
while(lY1++ < lY2);
}
//*****************************************************************************
//
//! Fills a rectangle.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param pRect is a pointer to the structure describing the rectangle.
//! \param ulValue is the color of the rectangle.
//!
//! This function fills a rectangle on the display. The coordinates of the
//! rectangle are assumed to be within the extents of the display, and the
//! rectangle specification is fully inclusive (in other words, both sXMin and
//! sXMax are drawn, along with sYMin and sYMax).
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverRectFill(void *pvDisplayData, const tRectangle *pRect,
uint16_t ulValue)
{
int16_t x0 = pRect->sXMin;
int16_t x1 = pRect->sXMax;
int16_t y0 = pRect->sYMin;
int16_t y1 = pRect->sYMax;
while(y0++ <= y1)
{
Template_DriverLineDrawH(pvDisplayData, x0, x1, y0, ulValue);
}
}
//*****************************************************************************
//
//! Translates a 24-bit RGB color to a display driver-specific color.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//! \param ulValue is the 24-bit RGB color. The least-significant byte is the
//! blue channel, the next byte is the green channel, and the third byte is the
//! red channel.
//!
//! This function translates a 24-bit RGB color into a value that can be
//! written into the display's frame buffer in order to reproduce that color,
//! or the closest possible approximation of that color.
//!
//! \return Returns the display-driver specific color.
//
//*****************************************************************************
static uint16_t
Template_DriverColorTranslate(void *pvDisplayData,
uint32_t ulValue)
{
/* The DPYCOLORTRANSLATE macro should be defined in TemplateDriver.h */
//
// Translate from a 24-bit RGB color to a color accepted by the LCD.
//
return(DPYCOLORTRANSLATE(ulValue));
}
//*****************************************************************************
//
//! Flushes any cached drawing operations.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//!
//! This functions flushes any cached drawing operations to the display. This
//! is useful when a local frame buffer is used for drawing operations, and the
//! flush would copy the local frame buffer to the display.
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverFlush(void *pvDisplayData)
{
// Flush Buffer here. This function is not needed if a buffer is not used,
// or if the buffer is always updated with the screen writes.
int16_t i=0,j=0;
for(i =0; i< LCD_Y_SIZE; i++)
for(j =0; j< (LCD_X_SIZE * BPP + 7) / 8; j++)
Template_DriverPixelDraw(pvDisplayData, j, i, Template_Memory[i * LCD_Y_SIZE + j]);
}
//*****************************************************************************
//
//! Send command to clear screen.
//!
//! \param pvDisplayData is a pointer to the driver-specific data for this
//! display driver.
//!
//! This function does a clear screen and the Display Buffer contents
//! are initialized to the current background color.
//!
//! \return None.
//
//*****************************************************************************
static void
Template_DriverClearScreen (void *pvDisplayData, uint16_t ulValue)
{
// This fills the entire display to clear it
// Some LCD drivers support a simple command to clear the display
int16_t y0 = 0;
while(y0++ <= (LCD_Y_SIZE - 1))
{
Template_DriverLineDrawH(pvDisplayData, 0, LCD_X_SIZE - 1, y0, ulValue);
}
}
//*****************************************************************************
//
//! The display structure that describes the driver for the blank template.
//
//*****************************************************************************
const tDisplay g_sTemplate_Driver =
{
sizeof(tDisplay),
Template_Memory,
#if defined(PORTRAIT) || defined(PORTRAIT_FLIP)
LCD_Y_SIZE,
LCD_X_SIZE,
#else
LCD_X_SIZE,
LCD_Y_SIZE,
#endif
Template_DriverPixelDraw,
Template_DriverPixelDrawMultiple,
Template_DriverLineDrawH,
Template_DriverLineDrawV,
Template_DriverRectFill,
Template_DriverColorTranslate,
Template_DriverFlush,
Template_DriverClearScreen
};
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************