AnsweredAssumed Answered

STM32f4 Discovery + SSD1963, FSMC

Question asked by VoltarenSpecht on Nov 4, 2014
Latest reply on Nov 5, 2014 by VoltarenSpecht
Hi,
i try to use the STM32f4 Discovery Board with a 7" LCD Display (AT070TN92 ) driven by a SSD1963 controller. I try to just clear the screen with blue color, but instead i just get varios coloured lines on the screen.

Probably somebody can help me find the mistake in my code.

Here some Code:

FSMC:

#include "fsmc.h"

void FSMC_LCD_Config(void)
{
  FSMC_NORSRAMInitTypeDef  FSMC_LCDInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  LCD_Timing;

 //-- LCD GPIOs Configuration ---------------------------------------------------//
 //
 //+-------------------+-------------------+
 //| PD14 <-> FSMC_D0  | PE14 <-> FSMC_D11 |
 //| PD15 <-> FSMC_D1  | PE15 <-> FSMC_D12 |
 //| PD0  <-> FSMC_D2  | PD8  <-> FSMC_D13 |
 //| PD1  <-> FSMC_D3  | PD9  <-> FSMC_D14 |
 //| PE7  <-> FSMC_D4  | PD10 <-> FSMC_D15 |
 //| PE8  <-> FSMC_D5  | PD7  <-> FSMC_NE1 | LCD CS        //changed PG10 -> PD7
 //| PE9  <-> FSMC_D6  | PD4  <-> FSMC_NOE | LCD RD
 //| PE10 <-> FSMC_D7  | PD5  <-> FSMC_NWE | LCD WR
 //| PE11 <-> FSMC_D8  | PE3  <-> FSMC_A19 | LCD RS        //changed PF0 -> PE3
 //| PE12 <-> FSMC_D9  | PB0  <->          | LCD Reset
 //| PE13 <-> FSMC_D10 | PC7  <->          | LCD Back Light
 //+-------------------+-------------------+
 //
 // GPIO

  GPIO_InitTypeDef LCD_GPIO_init;
  GPIO_InitTypeDef GPIO_InitStruct; //added 27.10.2014 for LED use

  FSMC_NORSRAMDeInit(FSMC_Bank1_NORSRAM1); //changed FSMC_Bank1_NORSRAM3 to FSMC_Bank1_NORSRAM1 03.11.2014
 
  // Enable GPIOs clock //
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
                          RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG , ENABLE);

  // Enable FSMC clock //
  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);

  // LCD RESET //
  LCD_GPIO_init.GPIO_Pin=GPIO_Pin_0;
  LCD_GPIO_init.GPIO_Mode=GPIO_Mode_OUT;
  LCD_GPIO_init.GPIO_Speed=GPIO_Speed_50MHz; //changed from 100 to 50 04.11.2014
  GPIO_Init(GPIOB,&LCD_GPIO_init);
    // ****************************************

  // LCD Back Light //
  LCD_GPIO_init.GPIO_Pin=GPIO_Pin_7;
  LCD_GPIO_init.GPIO_Mode=GPIO_Mode_OUT;
  LCD_GPIO_init.GPIO_Speed=GPIO_Speed_100MHz;
  GPIO_Init(GPIOC,&LCD_GPIO_init);
    // ****************************************

  // GPIOD configuration //
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);     //FSMC_D2
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);     //FSMC_D3
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);     //FSMC_NOE (LCD -> RD)
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);     //FSMC_NWE (LCD -> WR)
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource7 , GPIO_AF_FSMC);    //FSMC_NE1 (LCD -> CS) //added 03.11.2014
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);     //FSMC_D13
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);     //FSMC_D14
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);    //FSMC_D15
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);    //FSMC_D0
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);    //FSMC_D1
  LCD_GPIO_init.GPIO_Pin = GPIO_Pin_0  | GPIO_Pin_1  | GPIO_Pin_4  | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8  |
                                                     GPIO_Pin_9  | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
                       
  LCD_GPIO_init.GPIO_Mode = GPIO_Mode_AF;
  LCD_GPIO_init.GPIO_Speed = GPIO_Speed_2MHz;
  LCD_GPIO_init.GPIO_OType = GPIO_OType_PP;
  LCD_GPIO_init.GPIO_PuPd  = GPIO_PuPd_UP;

/************added 27.10.2014 for LED use****************************/

  //GPIO_InitStruct.GPIO_Pin configures the pins that will be used.
  //In this case we will use the LED's off of the discovery board which are on
  //PortD pins 12, 13, 14 and 15
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_12; //GPIO_Pin_15 | GPIO_Pin_14 | removed due to FSMC use 03.11.2014
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

 /************added 27.10.2014 for LED use****************************/

  //This finally passes all the values to the GPIO_Init function
  //which takes care of setting the corresponding bits.

  GPIO_Init(GPIOD, &LCD_GPIO_init);
  GPIO_Init(GPIOD, &GPIO_InitStruct);

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


  // GPIOE configuration //
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource3 , GPIO_AF_FSMC);    //FSMC_A19 // changed 03.11.2014 //FSMC_A19  (LCD-> RS)
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FSMC);    //FSMC_D4
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FSMC);    //FSMC_D5
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FSMC);    //FSMC_D6
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FSMC);    //FSMC_D7
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FSMC);    //FSMC_D8
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FSMC);    //FSMC_D9
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FSMC);    //FSMC_D10
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FSMC);    //FSMC_D11
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FSMC);    //FSMC_D12
  LCD_GPIO_init.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8  | GPIO_Pin_9  | GPIO_Pin_10 |
                                                     GPIO_Pin_11| GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
                                                     GPIO_Pin_15;
  GPIO_Init(GPIOE, &LCD_GPIO_init);
    // ****************************************

  // GPIOF configuration LCD RS Pin //
//  GPIO_PinAFConfig(GPIOF, GPIO_PinSource0 , GPIO_AF_FSMC);    //FSMC_A0  (LCD-> RS)
//  LCD_GPIO_init.GPIO_Pin = GPIO_Pin_0;
//    GPIO_Init(GPIOF, &LCD_GPIO_init);
    // ****************************************

  // GPIOG configuration LCD CS Pin //
//  GPIO_PinAFConfig(GPIOG, GPIO_PinSource10 , GPIO_AF_FSMC);    //FSMC_NE3 (LCD -> CS)
//  LCD_GPIO_init.GPIO_Pin = GPIO_Pin_10;
//    GPIO_Init(GPIOG, &LCD_GPIO_init);
    // ****************************************
    
  //-- LCD FSMC Configuration ------------------------------------------------------//
  // FSMC_Bank1_NORSRAM1 configuration //
  LCD_Timing.FSMC_AddressSetupTime = 3;//3 changed to
  LCD_Timing.FSMC_AddressHoldTime = 1;//1 changed to
  LCD_Timing.FSMC_DataSetupTime = 5;//6 changed to
  LCD_Timing.FSMC_BusTurnAroundDuration = 0;
  LCD_Timing.FSMC_CLKDivision = 1;
  LCD_Timing.FSMC_DataLatency = 0;
  LCD_Timing.FSMC_AccessMode = FSMC_AccessMode_D; // changed to
  // Color LCD configuration ------------------------------------
  //     LCD configured as follow:
  //        - Data/Address MUX = Disable
  //        - Memory Type = SRAM
  //        - Data Width = 16bit
  //        - Write Operation = Enable
  //        - Extended Mode = Disable
  //        - Asynchronous Wait = Disable
  FSMC_LCDInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;  //changed FSMC_Bank1_NORSRAM3 to FSMC_Bank1_NORSRAM1 03.11.2014
  FSMC_LCDInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_LCDInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
  FSMC_LCDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_LCDInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  FSMC_LCDInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
  FSMC_LCDInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_LCDInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_LCDInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_LCDInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  FSMC_LCDInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_LCDInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_LCDInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

  FSMC_LCDInitStructure.FSMC_ReadWriteTimingStruct = &LCD_Timing;
  FSMC_LCDInitStructure.FSMC_WriteTimingStruct = &LCD_Timing;
  FSMC_NORSRAMInit(&FSMC_LCDInitStructure);  
  // NE1 on LCD CS //
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); //changed FSMC_Bank1_NORSRAM3 to FSMC_Bank1_NORSRAM1 03.11.2014
}

// void FSMC_PSRAM_Config(void) deleted 27.10.2014


LCD:

/* Includes ------------------------------------------------------------------*/
#include "LCD.h"
#include "sram.h"
#include "functions.h"

/* The timings need to follow the datasheet for your particular TFT/LCD screen (the actual screen, not the controller)
*** Datasheets normally use a specific set of timings and acronyms, their value refers to the number of pixel clocks
** Non-display periods refer to pulses/timings that occur before or after the timings that actually put pixels on the screen
** Display periods refer to pulses/timings that directly put pixels on the screen
**
HDP: Horizontal Display Period, normally the width - 1
HT: Horizontal Total period (display + non-display)
HPS: non-display period between the start of the horizontal sync (LLINE) signal and the first display data
LPS: horizontal sync pulse (LLINE) start location in pixel clocks
HPW: Horizontal sync Pulse Width
VDP: Vertical Display period, normally height - 1
VT: Vertical Total period (display + non-display)
VPS: non-display period in lines between the start of the frame and the first display data in number of lines
FPS: vertical sync pulse (LFRAME) start location in lines.
VPW: Vertical sync Pulse Width

*** Here's how to convert them:
HPS = SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH
HT - HPS = GDISP_SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH
=>    SCREEN_HSYNC_FRONT_PORCH = ( HT - HPS ) - GDISP_SCREEN_WIDTH
   SCREEN_HSYNC_PULSE = HPW
   SCREEN_HSYNC_BACK_PORCH = HPS - HPW
   SCREEN_HSYNC_PERIOD = HT

VPS = SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH
VT - VPS = GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH
=>   SCREEN_VSYNC_FRONT_PORCH = ( VT - VPS ) - GDISP_SCREEN_HEIGHT
   SCREEN_VSYNC_PULSE = VPW
   SCREEN_VSYNC_BACK_PORCH = VPS - LPS
   SCREEN_VSYNC_PERIOD = VT
*/


/* Private define ------------------------------------------------------------*/
 /* Using FSMC A19 as RS */

#define LCD_REG              (*((volatile unsigned short *) 0x60000000))     /* RS = 0 */ //changed 0x68000000 to 0x60000000 03.11.2014
#define LCD_RAM              (*((volatile unsigned short *) 0x60020000))     /* RS = 1 */ //changed 0x68000002 to 0x60100000 03.11.2014

#define MAX_POLY_CORNERS   200
#define POLY_Y(Z)          ((int32_t)((Points + Z)->X))
#define POLY_X(Z)          ((int32_t)((Points + Z)->Y))
#define ABS(X)  ((X) > 0 ? (X) : -(X))     

#define SCREEN_FPS 60ULL


/* Private variables ---------------------------------------------------------*/
static sFONT *Current_Font;

static __IO uint32_t TimingDelay; // added 27.10.2014
static uint16_t LCD_HT=DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH;
static uint16_t LCD_HPS=DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH;
static uint16_t LCD_VT=DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH+DISP_VER_FRONT_PORCH+DISP_VER_RESOLUTION;
static uint16_t LCD_VPS=DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH;

/*******************************************************************************
* Function Name  : LCD_Initializtion
* Description    : SSD1963 Resets
* Input          : None
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/

void LCD_Init(void)
{
        // Reset
        GPIO_ResetBits(GPIOB , GPIO_Pin_0);
        Delay_ms(30);    //changed 300 to 30 04.11.2014
        GPIO_SetBits(GPIOB , GPIO_Pin_0);
        Delay_ms(10);    //changed 300 to 10 04.11.2014

        LCD_WriteIndex(SSD1963_SOFT_RESET);     //Software Reset
        LCD_WriteIndex(SSD1963_SOFT_RESET);     //Software Reset
        LCD_WriteIndex(SSD1963_SOFT_RESET);     //Software Reset

        //Delay_ms(5); deleted 04.1.2014
        
        //Set_PLL

        LCD_WriteIndex(SSD1963_SET_PLL);  //START PLL changed from WriteReg to index
        LCD_WriteData(0x01);              //added 04.11.2014
        Delay_ms(1000);                      //required delay
        LCD_WriteData(0x03);                //LOCK PLL
        //Delay_ms(5);
        //LCD_WriteIndex(SSD1963_SOFT_RESET);     //Soft replacement
        //Delay_ms(20);

        // Back Light
                GPIO_SetBits(GPIOC , GPIO_Pin_7);
        
        Delay_ms(10);
    
        
        //Set LCD mode, varies from individual manufacturer
        LCD_WriteIndex(SSD1963_SET_GDISP_MODE);
        LCD_WriteData(0x20);            // set 24-bit for  AT070TN92 7" panel
        LCD_WriteData(0x00);             // set Hsync+Vsync mode
        LCD_WriteData((DISP_HOR_RESOLUTION-1)>>8); // Set LCD panel size(DISP_HOR_RESOLUTION = 800) H Changed 480 to 800 03.11.2014
        LCD_WriteData(DISP_HOR_RESOLUTION-1); // Set LCD panel size(DISP_HOR_RESOLUTION = 800) L Changed 480 to 800 03.11.2014
        LCD_WriteData((DISP_VER_RESOLUTION-1)>>8); // Set LCD panel size(DISP_VER_RESOLUTION = 480) H Changed 272 to 480 03.11.2014
        LCD_WriteData(DISP_VER_RESOLUTION-1); // Set LCD panel size(DISP_VER_RESOLUTION = 480) L Changed 272 to 480 03.11.2014
        LCD_WriteData(0x00);            //0x00 // RGB sequence
        Delay_ms(5);
        
        /* added 03.11.2014
         * For a 10MHz reference clock to obtain 115MHz PLL frequency, user cannot program N = 23 and M = 2.  The closet
        setting in this situation is setting N=34 and M=3, where 10 x 34 / 3 = 113.33MHz.

        WRITE COMMAND “0xE2”
        WRITE DATA “0x21”      (N=34)
        WRITE DATA “0x02”      (M=3)
        WRITE DATA “0x54” (Dummy Byte)
         */
        LCD_WriteIndex(SSD1963_SET_PLL_MN);     //Set PLL with OSC = 10MHz (hardware), Multiplier N = 35,
                                                            //250MHz < VCO < 800MHz = OSC*(N+1), VCO = 360MHz
        LCD_WriteData(0x22);            //OSC = 10MHz (hardware),// Parameter 1 changed from 0x23 to 0x22 03.11.2014
        LCD_WriteData(0x02);            //Parameter 2 Divider M = 2, PLL = 360/(M+1) = 120MHz
        LCD_WriteData(0x54);            //Parameter 3 Validate M and N values
        Delay_ms(5);



//        LCD_WriteIndex(0xE6);  // SET PCLK freq=6.5MHz/19MHz, pixel clk freq added03.11.2014
//        LCD_WriteData(0x00);
//        LCD_WriteData(0xEA);
//        LCD_WriteData(0xEC);

        //Set horizontal period
        LCD_WriteIndex(SSD1963_SET_HORI_PERIOD);
        LCD_WriteData((LCD_HT-1)>>8); //Set HT
        LCD_WriteData(LCD_HT-1);
        LCD_WriteData((LCD_HPS-1)>>8); //Set HPS
        LCD_WriteData(LCD_HPS-1);
        LCD_WriteData(DISP_HOR_PULSE_WIDTH-1); //Set HPW
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        Delay_ms(5);

        //Set vertical period
        LCD_WriteIndex(SSD1963_SET_VERT_PERIOD);
        LCD_WriteData((LCD_VT-1)>>8); //Set VT
        LCD_WriteData(LCD_VT-1);
        LCD_WriteData((LCD_VPS-1)>>8); //Set VPS
        LCD_WriteData(LCD_VPS-1);
        LCD_WriteData(DISP_VER_PULSE_WIDTH-1); //Set VPW
        LCD_WriteData(0x00); //Set FPS
        LCD_WriteData(0x00);
        Delay_ms(5);

        //Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
        //To obtain PCLK = 5.3MHz with PLL Frequency = 120MHz,
        //5.3MHz = 120MHz * LCDC_FPR / 2^20
        //LCDC_FPR = 46312

        LCD_WriteIndex(SSD1963_SET_LSHIFT_FREQ);
        LCD_WriteData(0x00);    //changed from 0x01 to 0x00 according to Display Datasheet 03.11.2014
        LCD_WriteData(0xB4);    //changed from 0x33 to 0xB4 according to Display Datasheet 03.11.2014
        LCD_WriteData(0xE7);    //changed from 0x32 to 0xE7 according to Display Datasheet 03.11.2014
        Delay_ms(5);
        
        LCD_WriteIndex(SSD1963_SET_PIXEL_FORMAT); //Set pixel format, i.e. the bpp
        LCD_WriteData(0x50); // set 16bpp --> 101
        Delay_ms(5);

        LCD_WriteIndex(SSD1963_SET_PIXEL_DATA_INTERFACE); // Set pixel data interface
        LCD_WriteData(SSD1963_PDI_16BIT565); //16-bit(565 format) data for 16bpp

        Delay_ms(5);

        LCD_WriteIndex(SSD1963_ENTER_NORMAL_MODE);  // SET normal mode added 03.11.2014

        LCD_WriteIndex(SSD1963_SET_ADDRESS_MODE); //added 03.11.2014
        LCD_WriteData(0x00);                      //changed from 2 to 0x00 04.11.2014

        LCD_WriteIndex(SSD1963_SET_COLUMN_ADDRESS);    // Set column address added 04.11.2014
        LCD_WriteData(0x00);    //SET start column address=0
        LCD_WriteData(0x00);
        LCD_WriteData(0x03);    //SET end column address=800
        LCD_WriteData(0x1F);

        LCD_WriteIndex(SSD1963_SET_PAGE_ADDRESS);    //SET page address added 04.11.2014
        LCD_WriteData(0x00);    //SET start page address=0
        LCD_WriteData(0x00);
        LCD_WriteData(0x01);    //SET end page address=480
        LCD_WriteData(0xDF);

        LCD_WriteIndex(SSD1963_SET_DISPLAY_ON); // Turn on display

        LCD_WriteIndex(SSD1963_WRITE_MEMORY_START); //added 04.11.2014

    //Delay_ms(5);   /* delay 50 ms */
}


/*
 * Sets the text font.
 */

void Set_Font(sFONT *fonts)
{
  Current_Font = fonts;
}


/*******************************************************************************
* Function Name  : LCD_WriteReg
* Description    :
* Input          : - index:
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/
__inline void LCD_WriteIndex(uint16_t index)
{
    LCD_REG    = index;
}

/*******************************************************************************
* Function Name  : LCD_WriteData
* Description    :
* Input          : - index:
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/
__inline void LCD_WriteData(uint16_t data)
{
        LCD_RAM = data;
}

/*******************************************************************************
* Function Name  : LCD_ReadData
* Description    :
* Input          : None
* Output         : None
* Return         :
* Attention         : None
*******************************************************************************/
__inline uint16_t LCD_ReadData(void)
{
    return LCD_RAM;
}


/*******************************************************************************
* Function Name  : LCD_WriteReg
* Description    : Writes to the selected LCD register.
* Input          : - LCD_Reg: address of the selected register.
*                  - LCD_RegValue: value to write to the selected register.
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/
__inline void LCD_WriteReg(uint16_t LCD_Reg,uint16_t LCD_RegValue)
{
    /* Write 16-bit Index, then Write Reg */  
    LCD_WriteIndex(LCD_Reg);         
    /* Write 16-bit Reg */
    LCD_WriteData(LCD_RegValue);  
}

/*******************************************************************************
* Function Name  : LCD_ReadReg
* Description    : Reads the selected LCD Register.
* Input          : None
* Output         : None
* Return         : LCD Register Value.
* Attention         : None
*******************************************************************************/
__inline uint16_t LCD_ReadReg(uint16_t LCD_Reg)
{
    /* Write 16-bit Index (then Read Reg) */
    LCD_WriteIndex(LCD_Reg);

    /* Read 16-bit Reg */
    return LCD_ReadData();
}

void SetArea(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y)
{
    LCD_WriteIndex(SSD1963_SET_COLUMN_ADDRESS);
    LCD_WriteData(start_x>>8);
    LCD_WriteData(start_x);
    LCD_WriteData(end_x>>8);
    LCD_WriteData(end_x);
    LCD_WriteIndex(SSD1963_SET_PAGE_ADDRESS);
    LCD_WriteData(start_y>>8);
    LCD_WriteData(start_y);
    LCD_WriteData(end_y>>8);
    LCD_WriteData(end_y);
}



/*******************************************************************************
* Function Name  : LCD_Clear
* Description    :
* Input          : - Color: Screen Color
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/
void LCD_Clear(uint16_t Color)
{
    uint32_t index=0;
    SetArea(0,0,MAX_X,MAX_Y);

    LCD_WriteIndex(SSD1963_WRITE_MEMORY_START);
    for( index = 0; index < DISP_HOR_RESOLUTION * DISP_VER_RESOLUTION; index++ )
    {
        LCD_WriteData(Color);
    }

}

/******************************************************************************
* Function Name  : LCD_BGR2RGB
* Description    : RRRRRGGGGGGBBBBB convert to BBBBBGGGGGGRRRRR
* Input          : RGB color
* Output         : None
* Return         : RGB color
* Attention         :
*******************************************************************************/
uint16_t LCD_BGR2RGB(uint16_t color)
{
    uint16_t  r, g, b, rgb;
    
    b = ( color>>0 )  & 0x1f;
    g = ( color>>5 )  & 0x3f;
    r = ( color>>11 ) & 0x1f;
    
    rgb =  (b<<11) + (g<<5) + (r<<0);
    
    return( rgb );
}

/******************************************************************************
* Function Name  : LCD_GetPoint
* Description    : Get color of the point
* Input          : - Xpos: Row Coordinate
*                  - Ypos: Line Coordinate
* Output         : None
* Return         : Screen Color
* Attention         : None
*******************************************************************************/
uint16_t LCD_GetPoint(uint16_t Xpos,uint16_t Ypos)
{
    uint16_t dummy = 0;
  uint8_t red,green,blue;
    
    SetArea(Xpos,Ypos,MAX_X,MAX_Y);

    LCD_WriteIndex(SSD1963_READ_MEMORY_START);  
    // 16bit 565 value are
    // RRRRRGGGGGGBBBBB
  red = LCD_ReadData()>>3;
  green = LCD_ReadData()>>3;
  blue = LCD_ReadData()>>2;
  dummy = ( red << 11 ) | (green << 5 ) | blue;
  return  dummy;
}

/******************************************************************************
* Function Name  : LCD_SetPoint
* Description    :
* Input          : - Xpos: Row Coordinate
*                  - Ypos: Line Coordinate
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/
void LCD_SetPoint(uint16_t Xpos,uint16_t Ypos,uint16_t color)
{
    if( Xpos > MAX_X || Ypos > MAX_Y ) return;
    SetArea(Xpos,Ypos,Xpos,Ypos);
    LCD_WriteIndex(SSD1963_WRITE_MEMORY_START);
    LCD_WriteData(color);
}



/******************************************************************************
* Function Name  : LCD_DrawLine
* Description    : Bresenham's line algorithm
* Input          : - x0:
*                  - y0:
*                          - x1:
*                      - y1:
*                  - color:
* Output         : None
* Return         : None
* Attention         : None
*******************************************************************************/    
void LCD_DrawLine( uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2 , uint16_t color )
{
  uint8_t yLonger = 0;
  int incrementVal, endVal;
  int shortLen = y2-y1;
  int longLen = x2-x1;
    int decInc;
    int j = 0, i = 0;

  if(abs(shortLen) > abs(longLen)) {
    int swap = shortLen;
    shortLen = longLen;
    longLen = swap;
    yLonger = 1;
  }

  endVal = longLen;

  if(longLen < 0) {
    incrementVal = -1;
    longLen = -longLen;
    endVal--;
  } else {
    incrementVal = 1;
    endVal++;
  }

  if(longLen == 0)
    decInc = 0;
  else
    decInc = (shortLen << 16) / longLen;

  if(yLonger) {
    for(i = 0;i != endVal;i += incrementVal) {
      LCD_SetPoint(x1 + (j >> 16),y1 + i,color);
      j += decInc;
    }
  } else {
    for(i = 0;i != endVal;i += incrementVal) {
      LCD_SetPoint(x1 + i,y1 + (j >> 16),color);
      j += decInc;
    }
  }
}


/*
 * Draw a rectangle in the requested color.
 * x1, y1 - the position of one corner
 * x2, y2 - the position of the other corner
 * color - color of the rectangle.
 */

void Draw_Rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
  LCD_DrawLine(x1, y1, x2, y1, color);
  LCD_DrawLine(x2, y1, x2, y2, color);
  LCD_DrawLine(x2, y2, x1, y2, color);
  LCD_DrawLine(x1, y2, x1, y1, color);
}

/*
 * Draw a full rectangle.
 * x1, y1 - the position of one corner
 * x2, y2 - the position of the other corner
 * color - color of the rectangle.
 */

void Draw_Full_Rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
    uint16_t swp = 0;
    uint32_t index = 0;
    uint32_t nbpix = 0;
    // look if we have to swap x1-x2 or y1-y2
    if (x2 < x1) {swp = x1; x1 = x2 ; x2 = swp;}
    if (y2 < y1) {swp = y1; y1 = y2 ; y2 = swp;}
    nbpix = (x2-x1+1) * (y2-y1+1);

    // Fill the LCD memory area from the rectangle
    SetArea(x1,y1,x2,y2);
    LCD_WriteIndex(SSD1963_WRITE_MEMORY_START);
    for( index = 0; index < nbpix; index++ )
    {
        LCD_WriteData(color);
    }
}

/*
 * Draw a circle.
 * x, y - center of circle.
 * r - radius.
 * color - color of the circle.
 */

void Draw_Circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{
  int32_t  D;       /* Decision Variable */
  uint32_t  CurX;   /* Current X Value */
  uint32_t  CurY;   /* Current Y Value */

  D = 3 - (r << 1);
  CurX = 0;
  CurY = r;

  while (CurX <= CurY)
  {
    if (((x+CurX) < DISP_HOR_RESOLUTION) && ((y+CurY) < DISP_VER_RESOLUTION))
      LCD_SetPoint(x+CurX, y+CurY, color);
    if (((x+CurX) < DISP_HOR_RESOLUTION) && ((y-CurY) >= MIN_Y))
      LCD_SetPoint(x+CurX, y-CurY, color);
    if (((x-CurX) >= MIN_X) && ((y+CurY) < DISP_VER_RESOLUTION))
      LCD_SetPoint(x-CurX, y+CurY, color);
    if (((x-CurX) >= MIN_X) && ((y-CurY) >= MIN_Y))
      LCD_SetPoint(x-CurX, y-CurY, color);
    if (((x+CurY) < DISP_HOR_RESOLUTION) && ((y+CurX) < DISP_VER_RESOLUTION))
      LCD_SetPoint(x+CurY, y+CurX, color);
    if (((x+CurY) < DISP_HOR_RESOLUTION) && ((y-CurX) >= MIN_Y))
      LCD_SetPoint(x+CurY, y-CurX, color);
    if (((x-CurY) >= MIN_X) && ((y+CurX) < DISP_VER_RESOLUTION))
      LCD_SetPoint(x-CurY, y+CurX, color);
    if (((x-CurY) >= MIN_X) && ((y-CurX) >= MIN_Y))
      LCD_SetPoint(x-CurY, y-CurX, color);

    if (D < 0)
    {
      D += (CurX << 2) + 6;
    }
    else
    {
      D += ((CurX - CurY) << 2) + 10;
      CurY--;
    }
    CurX++;
  }
}

/*
 * Draw a full circle.
 * x, y - center of circle.
 * r - radius.
 * color - color of the circle.
 */

void Draw_Full_Circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color)
{
  int32_t  D;       /* Decision Variable */
  uint32_t  CurX;   /* Current X Value */
  uint32_t  CurY;   /* Current Y Value */

  D = 3 - (r << 1);
  CurX = 0;
  CurY = r;

  while (CurX <= CurY)
  {
    if(CurY > 0)
    {
      LCD_DrawLine(x-CurX, y+CurY, x-CurX, y-CurY, color);
      LCD_DrawLine(x+CurX, y+CurY, x+CurX, y-CurY, color);
    }

    if(CurX > 0)
    {
      LCD_DrawLine(x-CurY, y+CurX, x-CurY, y-CurX, color);
      LCD_DrawLine(x+CurY, y+CurX, x+CurY, y-CurX, color);
    }

    if (D < 0)
    {
      D += (CurX << 2) + 6;
    }
    else
    {
      D += ((CurX - CurY) << 2) + 10;
      CurY--;
    }
    CurX++;
  }
}


/*
 * Draw an image in format GRB565.
 * x, y - position, where to start displaying.
 * x_res, y_res - resolution in pixels.
 * *ptr_image - pointer to image array.
 */

void Draw_Image(uint16_t x, uint16_t y, uint16_t x_res, uint16_t y_res,const uint16_t *ptr_image)
{
  uint32_t cnt =0;
    SetArea(x, y,x + x_res-1,y + y_res-1);
    LCD_WriteIndex(SSD1963_WRITE_MEMORY_START);
  for(cnt = 0; cnt < (x_res * y_res) ; cnt++)
  {
        LCD_WriteData(*(ptr_image++));
    }
}

/*
 * Draw a character.
 * x, y - position
 * color - character's color
 * *c - pointer to character data
 */

void Draw_Char(uint16_t x, uint16_t y, const uint16_t *c, uint16_t color)
{
  uint32_t index = 0, i = 0;

  for(index = 0; index < Current_Font->Height; index++)
  {
    for(i = 0; i < Current_Font->Width; i++)
    {
      if( ((((c[index] & ((0x80 << ((Current_Font->Width / 12 ) * 8 ) ) >> i)) == 0x00) && (Current_Font->Width <= 12)) ||
          (((c[index] & (0x1 << i)) == 0x00)&&(Current_Font->Width > 12 )))  == 0x00)
      {
        LCD_SetPoint( x+i,y+index, color);
            }
    }
    //x++;
  }
}

/*
 * Display a character.
 * x, y - position
 * c - character in ASCII
 * color - character's color
 */

void Display_Char(uint16_t x, uint16_t y, uint8_t c, uint16_t color)
{
  c -= 32;
  Draw_Char(x, y, &Current_Font->table[c * Current_Font->Height], color);
}

/*
 * Display a string.
 * x - line. Next line have to respect the high of used font.
 * y - vertical position
 * *ptr - pointer to string.
 */

void Display_String(uint16_t x, uint16_t y, char *ptr,uint16_t color)
{
  uint16_t refcolumn = x;
  /* Send the string character by character on LCD */
  while (*ptr != 0)
  {
    /* Display one character on LCD */
    Display_Char(x,y, *ptr, color);
    /* Decrement the column position by 16 */
    refcolumn += Current_Font->Width;
        x += Current_Font->Width;
    /* Point on the next character */
    ptr++;
  }
}

// Nouvelles fonctions a tester


/**
  * @brief  Displays an poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @retval None
  */
void LCD_PolyLine(pPoint Points, uint16_t PointCount,uint16_t color)
{
  int16_t X = 0, Y = 0;

  if(PointCount < 2)
  {
    return;
  }

  while(--PointCount)
  {
    X = Points->X;
    Y = Points->Y;
    Points++;
    LCD_DrawLine(X, Y, Points->X, Points->Y,color);
  }
}

/**
  * @brief  Displays an relative poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @param  Closed: specifies if the draw is closed or not.
  *           1: closed, 0 : not closed.
  * @retval None
  */
static void LCD_PolyLineRelativeClosed(pPoint Points, uint16_t PointCount, uint16_t Closed,uint16_t color)
{
  int16_t X = 0, Y = 0;
  pPoint First = Points;

  if(PointCount < 2)
  {
    return;
  }  
  X = Points->X;
  Y = Points->Y;
  while(--PointCount)
  {
    Points++;
    LCD_DrawLine(X, Y, X + Points->X, Y + Points->Y,color);
    X = X + Points->X;
    Y = Y + Points->Y;
  }
  if(Closed)
  {
    LCD_DrawLine(First->X, First->Y, X, Y,color);
  }  
}

/**
  * @brief  Displays a closed poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @retval None
  */
void LCD_ClosedPolyLine(pPoint Points, uint16_t PointCount,uint16_t color)
{
  LCD_PolyLine(Points, PointCount,color);
  LCD_DrawLine(Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y,color);
}

/**
  * @brief  Displays a relative poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @retval None
  */
void LCD_PolyLineRelative(pPoint Points, uint16_t PointCount,uint16_t color)
{
  LCD_PolyLineRelativeClosed(Points, PointCount, 0,color);
}

/**
  * @brief  Displays a closed relative poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @retval None
  */
void LCD_ClosedPolyLineRelative(pPoint Points, uint16_t PointCount,uint16_t color)
{
  LCD_PolyLineRelativeClosed(Points, PointCount, 1,color);
}


/**
  * @brief  Displays a  full poly-line (between many points).
  * @param  Points: pointer to the points array.
  * @param  PointCount: Number of points.
  * @retval None
  */
void LCD_FillPolyLine(pPoint Points, uint16_t PointCount,uint16_t frontcolor,uint16_t backcolor)
{
  /*  public-domain code by Darel Rex Finley, 2007 */
  uint16_t  nodes = 0, nodeX[MAX_POLY_CORNERS], pixelX = 0, pixelY = 0, i = 0,
  j = 0, swap = 0;
  uint16_t  IMAGE_LEFT = 0, IMAGE_RIGHT = 0, IMAGE_TOP = 0, IMAGE_BOTTOM = 0;

  IMAGE_LEFT = IMAGE_RIGHT = Points->X;
  IMAGE_TOP= IMAGE_BOTTOM = Points->Y;

  for(i = 1; i < PointCount; i++)
  {
    pixelX = POLY_X(i);
    if(pixelX < IMAGE_LEFT)
    {
      IMAGE_LEFT = pixelX;
    }
    if(pixelX > IMAGE_RIGHT)
    {
      IMAGE_RIGHT = pixelX;
    }
    
    pixelY = POLY_Y(i);
    if(pixelY < IMAGE_TOP)
    {
      IMAGE_TOP = pixelY;
    }
    if(pixelY > IMAGE_BOTTOM)
    {
      IMAGE_BOTTOM = pixelY;
    }
  }
 
  /*  Loop through the rows of the image. */
  for (pixelY = IMAGE_TOP; pixelY < IMAGE_BOTTOM; pixelY++)
  {  
    /* Build a list of nodes. */
    nodes = 0; j = PointCount-1;

    for (i = 0; i < PointCount; i++)
    {
      if (((POLY_Y(i)<(double) pixelY) && (POLY_Y(j)>=(double) pixelY)) || \
          ((POLY_Y(j)<(double) pixelY) && (POLY_Y(i)>=(double) pixelY)))
      {
        nodeX[nodes++]=(int) (POLY_X(i)+((pixelY-POLY_Y(i))*(POLY_X(j)-POLY_X(i)))/(POLY_Y(j)-POLY_Y(i)));
      }
      j = i;
    }
 
    /* Sort the nodes, via a simple "Bubble" sort. */
    i = 0;
    while (i < nodes-1)
    {
      if (nodeX[i]>nodeX[i+1])
      {
        swap = nodeX[i];
        nodeX[i] = nodeX[i+1];
        nodeX[i+1] = swap;
        if(i)
        {
          i--;
        }
      }
      else
      {
        i++;
      }
    }
 
    /*  Fill the pixels between node pairs. */
    for (i = 0; i < nodes; i+=2)
    {
      if(nodeX[i] >= IMAGE_RIGHT)
      {
        break;
      }
      if(nodeX[i+1] > IMAGE_LEFT)
      {
        if (nodeX[i] < IMAGE_LEFT)
        {
          nodeX[i]=IMAGE_LEFT;
        }
        if(nodeX[i+1] > IMAGE_RIGHT)
        {
          nodeX[i+1] = IMAGE_RIGHT;
        }
        LCD_DrawLine(pixelY, nodeX[i+1], pixelY,nodeX[i+1] - nodeX[i], backcolor);
        LCD_SetPoint(pixelY, nodeX[i+1],frontcolor);
        LCD_SetPoint(pixelY, nodeX[i],frontcolor);
        /* for (j=nodeX[i]; j<nodeX[i+1]; j++) PutPixel(j,pixelY); */
      }
    }
  }
}

void PixBuffer(uint16_t Xpos , uint16_t Ypos , uint16_t color , uint8_t Buffer_Num)
{
    // Buffer_Num can be 1 or 2 to select on wich buffer we write the pixel
    
    uint32_t mem_offset;
    if( Xpos > MAX_X || Ypos > MAX_Y ) return;
    if(Buffer_Num > 2) return;
    
    mem_offset = (Ypos * DISP_HOR_RESOLUTION) + Xpos;
    if(Buffer_Num == 1)
        PSRAM_Write(mem_offset , color) ;
    else
        PSRAM_Write(mem_offset + Buffer_Length + 1, color) ;
}

void Buffer_To_Screen(uint16_t Xpos , uint16_t Ypos , uint16_t width , uint16_t height , uint8_t Buffer_Num)
{    // todo : Use DMA and not this full software solution
    
    uint32_t mem_offset;
    uint32_t nbpix;
    uint16_t psram_data;
    
    if( Xpos > MAX_X || Ypos > MAX_Y ) return;
    nbpix = width * height;
    SetArea(Xpos,Ypos,Xpos + width ,Ypos + height);
    LCD_WriteIndex(SSD1963_WRITE_MEMORY_START);
    for( mem_offset = 0; mem_offset < nbpix; mem_offset++ )
    {
        if(Buffer_Num == 1)
            {
                psram_data = PSRAM_Read(mem_offset * 2);
                LCD_WriteData(psram_data);    // multuply offset by 2 to get 16bit data
                //LCD_WriteData(PSRAM_Read(mem_offset * 2));    // multuply offset by 2 to get 16bit data
            }
        else
            {
                psram_data = PSRAM_Read((mem_offset + Buffer_Length + 1) * 2);
                LCD_WriteData(psram_data);
                //LCD_WriteData(PSRAM_Read((mem_offset + Buffer_Length + 1) * 2));
            }
    }
}

void Delay_ms(__IO uint32_t nTime) // added 27.10.2014
{
  TimingDelay = nTime;

  while(TimingDelay--)
  {
  }
}

/*********************************************************************************************************
      END FILE
*********************************************************************************************************/

MAIN:

#include "stm32_ub_uart.h"
#include "stm32_ub_button.h"
#include "main.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stdio.h"
#include "stdlib.h"

#include "LCD.h"
#include "fsmc.h"

#define LED_GREEN      12
#define LED_ORANGE     13
#define LED_RED        14
#define LED_BLUE       15

int main(void)
{
    SystemInit();         // Quarz Einstellungen aktivieren
    UB_Button_Init();    // Buttons initialization

    /*******LCD TEST 27.10.2014*****/

    FSMC_LCD_Config();
    LCD_Init();

             /**********************************************************************************
             * This block of code blinks all four LED's on initial startup
             * **********************************************************************************/
            GPIO_SetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13); //|GPIO_Pin_14|GPIO_Pin_15 removed due to fsmc use 03.11.2014
            Delay_ms(0xFFFFF);
            GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13); //|GPIO_Pin_14|GPIO_Pin_15 removed due to fsmc use 03.11.2014


      char buf[RX_BUF_SIZE]; // Puffer fuer Datenempfang
      UART_RXSTATUS_t check;

      // Init UART
      // Com2 mit 115200 Baud
      UB_Uart_Init();

      // String per UART senden (mit LineFeed+CarriageReturn)
      UB_Uart_SendString(COM2,"Hier ist UART2 [PA2,PA3]",LFCR);

      //added 24.10.2014:
      float fZahl;
      fZahl = 1.337;

      LCD_Clear(Blue);

      while(1)
             {

                //Reads the status of the push-button on the Discovery board
                 //If button is pressed blue LED is toggled

                 if (UB_Button_OnClick(BTN_USER)==true)
                 {
                     UB_Uart_SendString(COM2,"User button pushed!",LFCR);
                    FloatToUart2(fZahl);
                    GPIO_ToggleBits(GPIOD, GPIO_Pin_12);


                 }

         }
}





Outcomes