Loads bitmaps into QSPI memory for GC500_2_5inch to use.

Dependencies:   DMBasicGUI DMSupport

easyGUIFixed/GuiDisplay.c

Committer:
jmitc91516
Date:
2017-07-31
Revision:
0:a5c253316af6

File content as of revision 0:a5c253316af6:

/* ************************************************************************ */
/*                                                                          */
/*                     (C)2004-2014 IBIS Solutions ApS                      */
/*                            sales@easyGUI.com                             */
/*                             www.easyGUI.com                              */
/*                                                                          */
/*                       easyGUI display driver unit                        */
/*                               v6.0.23.002                                */
/*                                                                          */
/* ************************************************************************ */

#include "GuiConst.h"
#include "GuiDisplay.h"
#include "GuiLib.h"
#include <stdlib.h>

#define WANT_DOUBLE_BUFFERING // Also in GuiGraph16.h, GuiLib.c - *** all three must match ***

#define USE_WAIT_MS
#ifdef USE_WAIT_MS
extern void EasyGUIWaitMs(GuiConst_INT32U msec); // in main.cpp
#endif

extern void SetupQSPIBitmapArray(int stageNumber); // In main.cpp

// Make FRAME_ADDRESS able to be set at runtime, not hardcoded
static unsigned long frameAddress = 0L;
// Global function (actually called from the main function, in main.cpp) 
// to set the frame address at startup
void GuiDisplay_SetFrameAddress(void *newFrameAddress)
{
    // C/C++ is not happy copying a pointer value direct to an unsigned long
    union {
        void *ptrValue;
        unsigned long ulValue;
    } frameAddressUnion;
    
    frameAddressUnion.ptrValue = newFrameAddress;
    
    frameAddress = frameAddressUnion.ulValue;
}

// Select LCD controller type by removing double slashes
//
// Many of the drivers listed here supports more than one display controller.
// To find your driver simply make a text search in this file. Omit eventual
// letters after the display controller type number. Example: For an NJU6450A
// display controller make a search for "NJU6450" - make sure it is a plain
// text search, not a word search.
//
// If your display controller is not found you can contact support at
// sales@ibissolutions.com. We will then quickly supply a driver for it.
//
// You only need to use the relevant display driver, all others may be deleted.
// Make a copy of this file before modifying it.
//
// -----------------------------------------------------------------------------
// #define LCD_CONTROLLER_TYPE_AT32AP7000
// #define LCD_CONTROLLER_TYPE_AT91RM9200_ST7565
// #define LCD_CONTROLLER_TYPE_AT91SAM9263
// #define LCD_CONTROLLER_TYPE_BVGP
// #define LCD_CONTROLLER_TYPE_D51E5TA7601
// #define LCD_CONTROLLER_TYPE_F5529
// #define LCD_CONTROLLER_TYPE_FLEVIPER
// #define LCD_CONTROLLER_TYPE_FSA506
// #define LCD_CONTROLLER_TYPE_H8S2378
// #define LCD_CONTROLLER_TYPE_HD61202_2H
// #define LCD_CONTROLLER_TYPE_HD61202_4H
// #define LCD_CONTROLLER_TYPE_HD61202_2H2V
// #define LCD_CONTROLLER_TYPE_HX8238_AT32AP7000
// #define LCD_CONTROLLER_TYPE_HX8238_TMP92CH21
// #define LCD_CONTROLLER_TYPE_HX8312
// #define LCD_CONTROLLER_TYPE_HX8345
// #define LCD_CONTROLLER_TYPE_HX8346
// #define LCD_CONTROLLER_TYPE_HX8347
// #define LCD_CONTROLLER_TYPE_HX8347G
// #define LCD_CONTROLLER_TYPE_HX8352A
// #define LCD_CONTROLLER_TYPE_ILI9341
// #define LCD_CONTROLLER_TYPE_K70
// #define LCD_CONTROLLER_TYPE_LC7981
// #define LCD_CONTROLLER_TYPE_LS027
// #define LCD_CONTROLLER_TYPE_LS044
// #define LCD_CONTROLLER_TYPE_LH155BA
// #define LCD_CONTROLLER_TYPE_LH75401
// #define LCD_CONTROLLER_TYPE_LH7A400
// #define LCD_CONTROLLER_TYPE_LPC1788
// #define LCD_CONTROLLER_TYPE_LPC1850
// #define LCD_CONTROLLER_TYPE_LPC2478
// #define LCD_CONTROLLER_TYPE_LPC3230
#define LCD_CONTROLLER_TYPE_LPC408X
// #define LCD_CONTROLLER_TYPE_MPC5606S
// #define LCD_CONTROLLER_TYPE_MX257
// #define LCD_CONTROLLER_TYPE_NJU6450A
// #define LCD_CONTROLLER_TYPE_NT39016D
// #define LCD_CONTROLLER_TYPE_NT75451
// #define LCD_CONTROLLER_TYPE_OTM2201A
// #define LCD_CONTROLLER_TYPE_PCF8548
// #define LCD_CONTROLLER_TYPE_PCF8813
// #define LCD_CONTROLLER_TYPE_PIC24FJ256
// #define LCD_CONTROLLER_TYPE_PXA320
// #define LCD_CONTROLLER_TYPE_R61509
// #define LCD_CONTROLLER_TYPE_R61526
// #define LCD_CONTROLLER_TYPE_R61580
// #define LCD_CONTROLLER_TYPE_RA8822
// #define LCD_CONTROLLER_TYPE_RA8875
// #define LCD_CONTROLLER_TYPE_S1D13505
// #define LCD_CONTROLLER_TYPE_S1D13506
// #define LCD_CONTROLLER_TYPE_S1D13700
// #define LCD_CONTROLLER_TYPE_S1D13705
// #define LCD_CONTROLLER_TYPE_S1D13706
// #define LCD_CONTROLLER_TYPE_S1D13715
// #define LCD_CONTROLLER_TYPE_S1D13743
// #define LCD_CONTROLLER_TYPE_S1D13748
// #define LCD_CONTROLLER_TYPE_S1D13781
// #define LCD_CONTROLLER_TYPE_S1D13781_DIRECT
// #define LCD_CONTROLLER_TYPE_S1D13A04
// #define LCD_CONTROLLER_TYPE_S1D13A05
// #define LCD_CONTROLLER_TYPE_S1D15721
// #define LCD_CONTROLLER_TYPE_S6B0741
// #define LCD_CONTROLLER_TYPE_S6B33BL
// #define LCD_CONTROLLER_TYPE_S6D0139
// #define LCD_CONTROLLER_TYPE_S6E63D6
// #define LCD_CONTROLLER_TYPE_SBN1661_2H_SBN0080
// #define LCD_CONTROLLER_TYPE_SED1335
// #define LCD_CONTROLLER_TYPE_SEPS525
// #define LCD_CONTROLLER_TYPE_SH1101A
// #define LCD_CONTROLLER_TYPE_SH1123
// #define LCD_CONTROLLER_TYPE_SPFD5408
// #define LCD_CONTROLLER_TYPE_SPLC502
// #define LCD_CONTROLLER_TYPE_SSD0323
// #define LCD_CONTROLLER_TYPE_SSD1289
// #define LCD_CONTROLLER_TYPE_SSD1305
// #define LCD_CONTROLLER_TYPE_SSD1322
// #define LCD_CONTROLLER_TYPE_SSD1339
// #define LCD_CONTROLLER_TYPE_SSD1815
// #define LCD_CONTROLLER_TYPE_SSD1815_2H
// #define LCD_CONTROLLER_TYPE_SSD1848
// #define LCD_CONTROLLER_TYPE_SSD1858
// #define LCD_CONTROLLER_TYPE_SSD1926
// #define LCD_CONTROLLER_TYPE_SSD1963
// #define LCD_CONTROLLER_TYPE_SSD2119
// #define LCD_CONTROLLER_TYPE_ST7529
// #define LCD_CONTROLLER_TYPE_ST7541
// #define LCD_CONTROLLER_TYPE_ST7561
// #define LCD_CONTROLLER_TYPE_ST7565
// #define LCD_CONTROLLER_TYPE_ST7586
// #define LCD_CONTROLLER_TYPE_ST7637
// #define LCD_CONTROLLER_TYPE_ST7715
// #define LCD_CONTROLLER_TYPE_ST7920
// #define LCD_CONTROLLER_TYPE_STM32F429
// #define LCD_CONTROLLER_TYPE_T6963
// #define LCD_CONTROLLER_TYPE_TLS8201
// #define LCD_CONTROLLER_TYPE_TMPA900
// #define LCD_CONTROLLER_TYPE_TS7390
// #define LCD_CONTROLLER_TYPE_UC1608
// #define LCD_CONTROLLER_TYPE_UC1610
// #define LCD_CONTROLLER_TYPE_UC1611
// #define LCD_CONTROLLER_TYPE_UC1617
// #define LCD_CONTROLLER_TYPE_UC1698
// #define LCD_CONTROLLER_TYPE_UPD161607
// #define LCD_CONTROLLER_TYPE_UC1701

// ============================================================================
//
// COMMON PART - NOT DEPENDENT ON DISPLAY CONTROLLER TYPE
//
// Do not delete this part of the GuiDisplay.c file.
//
// If your operating system uses pre-emptive execution, i.e. it interrupts tasks
// at random instances, and transfers control to other tasks, display writing
// must be protected from this, by writing code for the two protection
// functions:
//
//   o  GuiDisplay_Lock     Prevent the OS from switching tasks
//   o  GuiDisplay_Unlock   Open up normal task execution again
//
// If your operating system does not use pre-emptive execution, i.e. if you
// must specifically release control in one tasks in order for other tasks to
// be serviced, or if you don't employ an operating system at all, you can just
// leave the two protection functions empty. Failing to write proper code for
// the protection functions will result in a system with unpredictable
// behavior.
//
// ============================================================================

void GuiDisplay_Lock (void)
{
}

void GuiDisplay_Unlock (void)
{
}

// ============================================================================
//
// DISPLAY DRIVER PART
//
// You only need to use the relevant display driver, all others may be deleted.
// Modify the driver so that it fits your specific hardware.
// Make a copy of this file before modifying it.
//
// ============================================================================

#ifdef LCD_CONTROLLER_TYPE_LPC408X

// ============================================================================
//
// LPC408x MICROCONTROLLER WITH BUILT-IN DISPLAY CONTROLLER
//
// This driver uses internal LCD controller of LPC408x microcontroller.
// LCD driver of LPC408x in 24 bit RGB parallel interface for TFT type
// display or 4bit parallel interface for STN type display.
// Graphic modes up to 1024x768 pixels.
//
// Compatible display controllers:
//   None
//
// easyGUI setup should be (Parameters window, Display controller tab page):
//   Horizontal bytes
//   Bit 0 at right
//   Number of color planes: 1
//   Color mode: Grayscale, palette or RGB
//   Color depth: 1 bit (B/W), 8 bits, 16 bits, 24 bits
//   Display orientation: Normal, Upside down, 90 degrees left, 90 degrees right
//   Display words with reversed bytes: Off
//   Number of display controllers, horizontally: 1
//   Number of display controllers, vertically: 1
//
// Port addresses (Px.x) must be altered to correspond to your microcontroller
// hardware and compiler syntax.
//
// ============================================================================

// Hardware connection for TFT display
// LPC408x                        generic TFT display
// LCD_FP               -         VSYNC
// LCD_LP               -         HSYNC
// LCD_LE               -         Line End
// LCD_DCLK             -         Pixel CLK
// LCD_ENAB_M           -         DATA_ENABLE
// LCD_VD[0-7]          -         R0-R7 (for 16bit RGB mode connect R0,R1,R2 to 0)
// LCD_VD[8-15]         -         G0-G7 (for 16bit RGB mode connect G0,G1 to 0)
// LCD_VD[16-23]        -         B0-B7 (for 16bit RGB mode connect B0,B1,B2 to 0)

// Hardware connection for STN display
// LCD_PWR              -         DISP
// LCD_DCLK             -         CL2
// LCD_FP               -         Frame Pulse
// LCD_LP               -         Line Sync Pulse
// LCD_LE               -         Line End
// LCD_VD[3:0]          -         UD[3:0]

// Power Control registers
#define PCONP          (*(volatile unsigned long *)0x400FC0C4)
// LCD controller power control bit
#define PCLCD          0

// Pin setup registers (IOCON)
#define IOCON_P0_4         (*(volatile unsigned long *)0x4002C010)
#define IOCON_P0_5         (*(volatile unsigned long *)0x4002C014)
#define IOCON_P0_6         (*(volatile unsigned long *)0x4002C018)
#define IOCON_P0_7         (*(volatile unsigned long *)0x4002C01C)
#define IOCON_P0_8         (*(volatile unsigned long *)0x4002C020)
#define IOCON_P0_9         (*(volatile unsigned long *)0x4002C024)
#define IOCON_P1_20        (*(volatile unsigned long *)0x4002C0D0)
#define IOCON_P1_21        (*(volatile unsigned long *)0x4002C0D4)
#define IOCON_P1_22        (*(volatile unsigned long *)0x4002C0D8)
#define IOCON_P1_23        (*(volatile unsigned long *)0x4002C0DC)
#define IOCON_P1_24        (*(volatile unsigned long *)0x4002C0E0)
#define IOCON_P1_25        (*(volatile unsigned long *)0x4002C0E4)
#define IOCON_P1_26        (*(volatile unsigned long *)0x4002C0E8)
#define IOCON_P1_27        (*(volatile unsigned long *)0x4002C0EC)
#define IOCON_P1_28        (*(volatile unsigned long *)0x4002C0F0)
#define IOCON_P1_29        (*(volatile unsigned long *)0x4002C0F4)
#define IOCON_P2_0         (*(volatile unsigned long *)0x4002C100)
#define IOCON_P2_1         (*(volatile unsigned long *)0x4002C104)
#define IOCON_P2_2         (*(volatile unsigned long *)0x4002C108)
#define IOCON_P2_3         (*(volatile unsigned long *)0x4002C10C)
#define IOCON_P2_4         (*(volatile unsigned long *)0x4002C110)
#define IOCON_P2_5         (*(volatile unsigned long *)0x4002C114)
#define IOCON_P2_6         (*(volatile unsigned long *)0x4002C118)
#define IOCON_P2_7         (*(volatile unsigned long *)0x4002C11C)
#define IOCON_P2_8         (*(volatile unsigned long *)0x4002C120)
#define IOCON_P2_9         (*(volatile unsigned long *)0x4002C124)
#define IOCON_P2_11        (*(volatile unsigned long *)0x4002C12C)
#define IOCON_P2_12        (*(volatile unsigned long *)0x4002C130)
#define IOCON_P2_13        (*(volatile unsigned long *)0x4002C134)
#define IOCON_P4_28        (*(volatile unsigned long *)0x4002C270)
#define IOCON_P4_29        (*(volatile unsigned long *)0x4002C274)

// LCD Port Enable
#define LCDPE           1

// LCD controller registers
// LCD configuration register
#define LCD_CFG         (*(volatile unsigned long *)0x400FC1B8)

// LCD Controller Base Address
#define LCD_BASE       0x20088000

// Horizontal Timing Control
#define LCD_TIMH       (*(volatile unsigned long *)(LCD_BASE+0x000))
// Vertical Timing Control
#define LCD_TIMV       (*(volatile unsigned long *)(LCD_BASE+0x004))
// Clock and Signal Polarity Control register
#define LCD_POL        (*(volatile unsigned long *)(LCD_BASE+0x008))
// Line End Control register
#define LCD_LE         (*(volatile unsigned long *)(LCD_BASE+0x00C))
// Upper Panel Frame Base Address register
#define LCD_UPBASE     (*(volatile unsigned long *)(LCD_BASE+0x010))
// Lower Panel Frame Base Address register
#define LCD_LPBASE     (*(volatile unsigned long *)(LCD_BASE+0x014))
// LCD Control register
#define LCD_CTRL       (*(volatile unsigned long *)(LCD_BASE+0x018))
// Interrupt Mask register
#define LCD_INTMSK     (*(volatile unsigned long *)(LCD_BASE+0x01C))
// Raw Interrupt Status register
#define LCD_INTRAW     (*(volatile unsigned long *)(LCD_BASE+0x020))
// Masked Interrupt Status register
#define LCD_INTSTAT    (*(volatile unsigned long *)(LCD_BASE+0x024))
// Interrupt Clear register
#define LCD_INTCLR     (*(volatile unsigned long *)(LCD_BASE+0x028))
// Upper Panel Current Address Value register
#define LCD_UPCURR     (*(volatile unsigned long *)(LCD_BASE+0x02C))
// Lower Panel Current Address Value register
#define LCD_LPCURR     (*(volatile unsigned long *)(LCD_BASE+0x030))
// 256x16-bit Color Palette registers
#define LCD_PAL        (*(volatile unsigned long *)(LCD_BASE+0x200))
// Cursor Image registers
#define CRSR_IMG       (*(volatile unsigned long *)(LCD_BASE+0x800))
// Cursor Control register
#define CRSR_CTRL      (*(volatile unsigned long *)(LCD_BASE+0xC00))

// LCD controller enable bit
#define LCDEN          0
// LCD controller power bit
#define LCDPWR         11
// Bypass pixel clock divider - for TFT display must be 1
#ifdef GuiConst_COLOR_DEPTH_1
#define BCD            0
#else
#define BCD            1
#endif
// Adjust these values according your display
// PLL clock prescaler selection - only odd numbers 0,1,3,5,..255
// 0 - PLL/1, 1 - PLL/2, 3 - PLL/4
#define PLLDIV         0
// LCD panel clock prescaler selection,  range 0 - 31
// LCD freq = MCU freq /(CLKDIV+1)
#define CLKDIV         7
// Horizontal back porch in pixels, range 3 - 256
#ifdef GuiConst_COLOR_DEPTH_1
#define HBP            5
#else
#define HBP            40
#endif
// Horizontal front porch in pixels, range 3 - 256
#ifdef GuiConst_COLOR_DEPTH_1
#define HFP            5
#else
#define HFP            79
#endif
// Horizontal synchronization pulse width in pixels, range 3 - 256
#ifdef GuiConst_COLOR_DEPTH_1
#define HSW            3
#else
#define HSW            48
#endif
// Pixels-per-line in pixels, must be multiple of 16
#define PPL            GuiConst_DISPLAY_WIDTH_HW
// Vertical back porch in lines, range 1 - 256
#ifdef GuiConst_COLOR_DEPTH_1
#define VBP            2
#else
#define VBP            29
#endif
// Vertical front porch in lines, range 1 - 256
#ifdef GuiConst_COLOR_DEPTH_1
#define VFP            2
#else
#define VFP            40
#endif
// Vertical synchronization pulse width in lines, range 1 - 31
#ifdef GuiConst_COLOR_DEPTH_1
#define VSW            1
#else
#define VSW            3
#endif
// Lines per panel
#define LPP            GuiConst_BYTE_LINES
// Clocks per line
#ifdef GuiConst_COLOR_DEPTH_1
#define CPL            GuiConst_DISPLAY_WIDTH_HW/4
#else
#define CPL            GuiConst_DISPLAY_WIDTH_HW
#endif
// Invert output enable
// 0 = LCDENAB output pin is active HIGH in TFT mode
// 1 = LCDENAB output pin is active LOW in TFT mode
#define IOE            0
// Invert panel clock
// 0 = Data is driven on the LCD data lines on the rising edge of LCDDCLK
// 1 = Data is driven on the LCD data lines on the falling edge of LCDDCLK
#define IPC            0
// Invert horizontal synchronization
// 0 = LCDLP pin is active HIGH and inactive LOW
// 1 = LCDLP pin is active LOW and inactive HIGH
#ifdef GuiConst_COLOR_DEPTH_1
#define IHS            0
#else
#define IHS            1
#endif
// IVS Invert vertical synchronization
// 0 = LCDFP pin is active HIGH and inactive LOW
// 1 = LCDFP pin is active LOW and inactive HIGH
#ifdef GuiConst_COLOR_DEPTH_1
#define IVS            0
#else
#define IVS            1
#endif
// Lower five bits of panel clock divisor
#define PCD_LO         2
// CLKSEL Clock Select
// 0 = the clock source for the LCD block is CCLK
// 1 = the clock source for the LCD block is LCD_DCLK
#define CLKSEL         0

/****************************************************************************/
/* IMPORTANT!!!                                                             */
/****************************************************************************/
// Set start address of frame buffer in RAM memory
// 0x4000 0000 - 0x4000 FFFF RAM (64 kB)
// 0x8000 0000 - 0x80FF FFFF Static memory bank 0 (16 MB)
// 0x8100 0000 - 0x81FF FFFF Static memory bank 1 (16 MB)
// 0xA000 0000 - 0xAFFF FFFF Dynamic memory bank 0 (256 MB)
// 0xB000 0000 - 0xBFFF FFFF Dynamic memory bank 1 (256 MB)
//#define FRAME_ADDRESS  0xA0000008
//#define FRAME_ADDRESS  0xA00017D8 // As of 26 Oct 2016
#define FRAME_ADDRESS (frameAddress) // Use the static variable set at the top of this file
/****************************************************************************/

// Address of pallete registers
#define PALETTE_RAM_ADDR LCD_PAL

// Delay routine
// This constant must be adjusted according to speed of microcontroller
#define ONE_MS               100
// Param msec is delay in miliseconds
void millisecond_delay(GuiConst_INT32U msec)
{
#ifdef USE_WAIT_MS
  EasyGUIWaitMs(msec);
#else
  GuiConst_INT32U j;

  for (j = 0; j < (ONE_MS * msec) ; j++);
#endif
}

// Initialises the module and the display
void GuiDisplay_Init (void)
{
//  return; // Test - do we need any display initialisation here? Let the BIOS do it?
          // No flickering - but red and blue reversed (again)
// So - can we reinstate some of the code in this function, and get the red and blue 
// the correct way round without flickering?
//#define ALLOW_LPC4088_INIT
// Now allowing initialisation of the LCD control register even with ALLOW_LPC4088_INIT not #defined.
// This appears to have eliminated the flickering while keeping the red and blue components 
// the correct way round.
  
  GuiConst_INT32U i;
#ifdef GuiConst_COLOR_DEPTH_24
  GuiConst_INT32U *framePtr;
#else
#ifdef GuiConst_COLOR_DEPTH_16
  GuiConst_INT16U *framePtr;
#else
  GuiConst_INT32U PaletteData;
  GuiConst_INT8U *framePtr;
  GuiConst_INT32U * pDst;
#endif
#endif

//  SetupQSPIBitmapArray(1);

/**************************************************/
/* Carefully adjust the IO pins for your system   */
/* Following settings for TFT panel 16/24 bit     */
/**************************************************/

/* *** DEBUG *** COMMENT OUT THIS BLOCK OF CODE - WHAT HAPPENS?
// PI         SETTING     RGB888      RGB565
  IOCON_P1_29  |= 7;   // BLUE7       BLUE4
  IOCON_P1_28  |= 7;   // BLUE6       BLUE3
  IOCON_P1_27  |= 7;   // BLUE5       BLUE2
  IOCON_P1_26  |= 7;   // BLUE4       BLUE1
  IOCON_P2_13  |= 7;   // BLUE3       BLUE0
  //IOCON_P2_12  |= 7;   // BLUE2       -       !! Comment out for RGB565
  //IOCON_P0_9   |= 7;   // BLUE1       -       !! Comment out for RGB565
  //IOCON_P0_8   |= 7;   // BLUE0       -       !! Comment out for RGB565
  IOCON_P1_25  |= 7;   // GREEN7      GREEN5
  IOCON_P1_24  |= 7;   // GREEN6      GREEN4
  IOCON_P1_23  |= 7;   // GREEN5      GREEN3
  IOCON_P1_22  |= 7;   // GREEN4      GREEN2
  IOCON_P1_21  |= 7;   // GREEN3      GREEN1
  IOCON_P1_20  |= 7;   // GREEN2      GREEN0
  //IOCON_P0_7   |= 7;   // GREEN1      -       !! Comment out for RGB565
  //IOCON_P0_6   |= 7;   // GREEN0      -       !! Comment out for RGB565
  IOCON_P2_9   |= 7;   // RED7        RED4
  IOCON_P2_8   |= 7;   // RED6        RED3
  IOCON_P2_7   |= 7;   // RED5        RED2
  IOCON_P2_6   |= 7;   // RED4        RED1
  //IOCON_P4_29  |= 7;   // RED3        -       !! Comment out for RGB565
  IOCON_P2_12  |= 5;   // -           RED0  !! Comment out for RGB888 !!
  //IOCON_P4_28  |= 7;   // RED2        -       !! Comment out for RGB565
  //IOCON_P0_5   |= 7;   // RED1        -       !! Comment out for RGB565
  //IOCON_P0_4   |= 7;   // RED0        -       !! Comment out for RGB565
  IOCON_P2_5   |= 7;   // LCD_LP      LCD_LP
  IOCON_P2_4   |= 7;   // LCD_ENAB_M  LCD_ENAB_M
  IOCON_P2_3   |= 7;   // LCD_FP      LCD_FP
  IOCON_P2_2   |= 7;   // LCD_DCLK    LCD_DCLK
  IOCON_P2_1   |= 7;   // LCD_LE      LCD_LE
  IOCON_P2_0   |= 7;   // LCD_PWR     LCD_PWR
  IOCON_P2_11  |= 7;   // LCD_CLKIN   LCD_CLKIN
*/ // DEBUG - ANSWER - *** EVERYTHING STILL APPEARS TO WORK ***

/**************************************************/

//  SetupQSPIBitmapArray(2);
  
#ifdef ALLOW_LPC4088_INIT
  // Disable power
  LCD_CTRL &= ~(1 << LCDEN);
  millisecond_delay(100);
  LCD_CTRL &= ~(1 << LCDPWR);
  
  // ====================================
  // Initialize Clock(PLL),EMC and SDRAM!
  // ====================================

  // Enable LCD controller
  PCONP |= 1<<PCLCD;

  // LCD Configuration init pixel clock
  LCD_CFG |= (CLKDIV);

  // Horizontal Timing register
  LCD_TIMH |= ((HBP-1) << 24)|((HFP-1) << 16)|((HSW-1) << 8)|((PPL/16-1) << 2);

  // Vertical Timing register
  LCD_TIMV |= (VBP << 24)|(VFP << 16)|((VSW-1) << 10)|(LPP-1);

  // Clock and Signal Polarity register
  LCD_POL |= (BCD << 26)|((CPL-1) << 16)|(IOE << 14)|(IPC << 13)|
             (IHS << 12)|(IVS << 11)|(CLKSEL << 5)| PCD_LO;

  LCD_LE = 0;
  LCD_INTMSK = 0;

#endif // ALLOW_LPC4088_INIT
// If we include the initialisation of the LCD control register,
// does this get red and blue the correct way round without flickering?

  // LCD Control register
#ifdef GuiConst_COLOR_DEPTH_24
  // TFT single panel,24bit, normal output
  LCD_CTRL = 0x0000002A;
#else
#ifdef GuiConst_COLOR_DEPTH_16
  // TFT single panel,16bit, normal output (BGR)
  LCD_CTRL = 0x0000102C;
#else
#ifdef GuiConst_COLOR_DEPTH_8
  // TFT single panel,8bit, normal output
  LCD_CTRL = 0x00000026;
#else
  // STN single panel, monochrome, 4bit bus, normal output
  LCD_CTRL = 0x00000010;
#endif
#endif
#endif


#ifdef GuiConst_COLOR_DEPTH_24
  framePtr = (GuiConst_INT32U *)FRAME_ADDRESS;
#else
#ifdef GuiConst_COLOR_DEPTH_16
  framePtr = (GuiConst_INT16U *)FRAME_ADDRESS;
#else
  framePtr = (GuiConst_INT8U *)FRAME_ADDRESS;
  pDst = (GuiConst_INT32U *)PALETTE_RAM_ADDR;
  for (i = 0; i < 128; i++)
  {
#ifdef GuiConst_COLOR_DEPTH_1
    PaletteData = 0xFFFF0000;
#else
    PaletteData = GuiStruct_Palette[2*i][0];
    PaletteData |= (GuiConst_INT32U)GuiStruct_Palette[2*i][1]<<8;
    PaletteData |= (GuiConst_INT32U)GuiStruct_Palette[2*i+1][0]<<16;
    PaletteData |= (GuiConst_INT32U)GuiStruct_Palette[2*i+1][1]<<24;
#endif
    *pDst++ = PaletteData;
  }
#endif
#endif

  // Clear frame buffer by copying the data into frame buffer
#ifdef GuiConst_COLOR_DEPTH_24
  for (i = 0; i < GuiConst_DISPLAY_BYTES/3; i++)
    *framePtr++ = 0x00000000; // Color
#else
#ifdef GuiConst_COLOR_DEPTH_16
    for (i = 0; i < GuiConst_DISPLAY_BYTES/2; i++)
    *framePtr++ = 0x0000; // Color
#else
  for (i = 0; i < GuiConst_DISPLAY_BYTES; i++)
    *framePtr++ = 0x00;  // Color
#endif
#endif

//  LCD_CFG = 0;

  millisecond_delay(100);
  // Power-up sequence
  LCD_CTRL |= 1<<LCDEN;
  // Apply contrast voltage to LCD panel
  // (not controlled or supplied by the LCD controller)
  millisecond_delay(100);
  LCD_CTRL |= 1<<LCDPWR;

  // Set start address of frame buffer in RAM memory
  LCD_LPBASE = FRAME_ADDRESS;
  LCD_UPBASE = FRAME_ADDRESS;
}

#ifdef WANT_DOUBLE_BUFFERING
// *** Need complete GuiDisplay_Refresh ***

// Refreshes display buffer to display
void GuiDisplay_Refresh (void)
{
  GuiConst_INT32U Pixel, X, Y, LastByte;
#ifdef GuiConst_COLOR_DEPTH_24
  GuiConst_INT32U *framePtr;
#else
#ifdef GuiConst_COLOR_DEPTH_16
  GuiConst_INT16U *framePtr;
#else
  // Valid also for monochrome STN display
  GuiConst_INT8U *framePtr;
#endif
#endif

  GuiDisplay_Lock ();

  // Walk through all lines
  for (Y = 0; Y < GuiConst_BYTE_LINES; Y++)
  {
    if (GuiLib_DisplayRepaint[Y].ByteEnd >= 0)
    // Something to redraw in this line
    {
#ifdef GuiConst_COLOR_DEPTH_24
      // Set video ram base address
      framePtr = (GuiConst_INT32U *)FRAME_ADDRESS;
      // Pointer offset calculation
      framePtr += Y * GuiConst_BYTES_PR_LINE/3 +
                  GuiLib_DisplayRepaint[Y].ByteBegin;
      // Set amount of data to be changed
      LastByte = GuiConst_BYTES_PR_LINE/3 - 1;
#else
#ifdef GuiConst_COLOR_DEPTH_16
      // Set video ram base address
      framePtr = (GuiConst_INT16U *)FRAME_ADDRESS;
      // Pointer offset calculation
      framePtr += Y * GuiConst_BYTES_PR_LINE/2 +
                  GuiLib_DisplayRepaint[Y].ByteBegin;
      // Set amount of data to be changed
      LastByte = GuiConst_BYTES_PR_LINE/2 - 1;
#else
      // Valid also for monochrome STN display
      // Set video ram base address
      framePtr = (GuiConst_INT8U *)FRAME_ADDRESS;
      // Pointer offset calculation
      framePtr += Y * GuiConst_BYTES_PR_LINE +
                  GuiLib_DisplayRepaint[Y].ByteBegin;
      // Set amount of data to be changed
      LastByte = GuiConst_BYTES_PR_LINE - 1;
#endif
#endif
      if (GuiLib_DisplayRepaint[Y].ByteEnd < LastByte)
        LastByte = GuiLib_DisplayRepaint[Y].ByteEnd;

      // Write data for one line to framebuffer from GuiLib_DisplayBuf
#ifdef GuiConst_COLOR_DEPTH_24
      for (X = GuiLib_DisplayRepaint[Y].ByteBegin * 3;
               X <= (LastByte * 3 + 2);
               X = X + 3)
      {
        Pixel = GuiLib_DisplayBuf[Y][X];
        Pixel |= (GuiConst_INT32U)GuiLib_DisplayBuf[Y][X+1]<<8;
        Pixel |= (GuiConst_INT32U)GuiLib_DisplayBuf[Y][X+2]<<16;
        *framePtr++ = Pixel;
      }
#else
#ifdef GuiConst_COLOR_DEPTH_16
      for (X = GuiLib_DisplayRepaint[Y].ByteBegin; X <= LastByte; X++)
      {
        *framePtr++ = GuiLib_DisplayBuf.Words[Y][X];
      }
#else
      // Valid also for monochrome STN display
      for (X = GuiLib_DisplayRepaint[Y].ByteBegin; X <= LastByte; X++)
        *framePtr++ = GuiLib_DisplayBuf[Y][X];
#endif
#endif
      // Reset repaint parameters
      GuiLib_DisplayRepaint[Y].ByteEnd = -1;
    }
  }
  GuiDisplay_Unlock ();
}

#else // WANT_DOUBLE_BUFFERING

// We are already writing direct to the display - 
// GuiDisplay_Refresh does not need to do anything
// (but other code still expects it to exist)
void GuiDisplay_Refresh (void)
{
}

#endif // WANT_DOUBLE_BUFFERING

#endif // LCD_CONTROLLER_TYPE_LPC408X

// ============================================================================
//
// DISPLAY DRIVER PART ENDS
//
// ============================================================================