LPC1788 - TFT Image is Teared. Checked all timings. Help please.

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC1788 - TFT Image is Teared. Checked all timings. Help please.

2,419 次查看
poptelecanconst
Contributor II

  Hello everyone. 

    I am banging my head with this for weeks now. I have a custom board, that sports a LPC1788 208 pin + AS4C8M16SA Alliance Memory 128M - 8M x 16 bit Synchronous DRAM + an TFT RFC570Y-6IW-DNN.

   One by one - I started with the memory. runs at 60 MhZ clock, checked all timings with an oscilloscope, checked the integrity with a simple code - writing and reading back from memory. All is fine. 

  

   I am using a simple routine with the LCD. Nothing fancy. No emwin. I simply want to display a slideshow of BMPs on it. But until then I want to draw a simple line. It's tearing the image in half. I will attach some pictures. I GUESS is a timing issue, but I cannot figure out what's the problem. Checked vsync / hsync with an oscilloscope (on the trace) - and looks fine. Checked the TFT clock - 6.3 MhZ looks fine. I checked every single trace with a multimeter under a microscope ... all fine. Checked the voltages, took care of screen orientation registers (mentioned in the datasheet) ... still cannot have a clear picture. I don't know what to do next really ... 

  This is the datasheet for the TFT...

    https://www.tme.eu/en/Document/aa5324e3d006c80d8ca67e400949ee5c/RFC570Y-6IW-DNN.pdf

 I don't understand the timing graphs , I used the values from the table at page 14. 

 The simple code that works somehow is here:

#include "LCD/lpc177x_8x_lcd.h"
#include "EX_SDRAM/EX_SDRAM.H"

#define C_GLCD_CLK_PER_LINE     (C_GLCD_H_SIZE + C_GLCD_H_PULSE + C_GLCD_H_FRONT_PORCH + C_GLCD_H_BACK_PORCH)
#define C_GLCD_LINES_PER_FRAME  (C_GLCD_V_SIZE + C_GLCD_V_PULSE + C_GLCD_V_FRONT_PORCH + C_GLCD_V_BACK_PORCH)
#define C_GLCD_PIX_CLK          (C_GLCD_CLK_PER_LINE * C_GLCD_LINES_PER_FRAME * C_GLCD_REFRESH_FREQ)
 
 //************************************************************************
void GLCD_Ctrl (Bool bEna)
{
 volatile uint32_t i;
  if (bEna)
  {
    LPC_LCD->CTRL |= (1<<0);
    for(i = C_GLCD_PWR_ENA_DIS_DLY; i; i--)
    LPC_LCD->CTRL |= (1<<11);
  }
  else
  {
    LPC_LCD->CTRL &= ~(1<<11);
    for(i = C_GLCD_PWR_ENA_DIS_DLY; i; i--);
    LPC_LCD->CTRL &= ~(1<<0);
  }
}
 
 //*************************************************************************/
void GLCD_Init (const unsigned long *pPain, const unsigned long * pPallete)
{
 unsigned long i,j;
 unsigned long *pDst = (unsigned long *)LCD_VRAM_BASE_ADDR;
 
  /* R */
  LPC_IOCON->P0_4  = 0x27;  // LCD_VD_0
  LPC_IOCON->P0_5   = 0x27;  // LCD_VD_1
  LPC_IOCON->P4_28   = 0x27;  // LCD_VD_2
  LPC_IOCON->P4_29  = 0x27;  // LCD_VD_3
  LPC_IOCON->P2_6   = 0x27;  // LCD_VD_4
  LPC_IOCON->P2_7   = 0x27;  // LCD_VD_5
  LPC_IOCON->P2_8   = 0x27;  // LCD_VD_6
  LPC_IOCON->P2_9  = 0x27;  // LCD_VD_7
  /* G */    
  LPC_IOCON->P0_6  = 0x27;  // LCD_VD_8
  LPC_IOCON->P0_7  = 0x27;  // LCD_VD_9
  LPC_IOCON->P1_20  = 0x27;  // LCD_VD_10
  LPC_IOCON->P1_21  = 0x27;  // LCD_VD_11
  LPC_IOCON->P1_22  = 0x27;  // LCD_VD_12
  LPC_IOCON->P1_23  = 0x27;  // LCD_VD_13
  LPC_IOCON->P1_24  = 0x27;  // LCD_VD_14
  LPC_IOCON->P1_25  = 0x27;  // LCD_VD_15
 /* B */
  LPC_IOCON->P0_8  = 0x27;  // LCD_VD_16
  LPC_IOCON->P0_9  = 0x27;  // LCD_VD_17
  LPC_IOCON->P2_12  = 0x27;  // LCD_VD_18
  LPC_IOCON->P2_13  = 0x27;  // LCD_VD_19
  LPC_IOCON->P1_26  = 0x27;  // LCD_VD_20
  LPC_IOCON->P1_27  = 0x27;  // LCD_VD_21
  LPC_IOCON->P1_28  = 0x27;  // LCD_VD_22
  LPC_IOCON->P1_29  = 0x27;  // LCD_VD_23
  LPC_IOCON->P2_2   = 0x27;  // LCD_DCLK
  LPC_IOCON->P2_5   = 0x27;  // LCD_LP -- HSYNC
  LPC_IOCON->P2_3   = 0x27;  // LCD_FP -- VSYNC
  LPC_IOCON->P2_4   = 0x27;  // LCD_ENAB_M -- LCDDEN
 
 //Turn on LCD clock
 LPC_SC->PCONP |= 1<<0;
  // Disable cursor
 LPC_LCD->CRSR_CTRL &=~(1<<0);
 // disable GLCD controller 
 LPC_LCD->CTRL = 0;
 
 LPC_LCD->CTRL &= ~(0x07 <<1);
 LPC_LCD->CTRL |= (5<<1);
 
 // TFT panel
 LPC_LCD->CTRL |= (1<<5);
 // single panel
 LPC_LCD->CTRL &= ~(1<<7);
 // notmal output
 LPC_LCD->CTRL |= (1<<8);
 // little endian byte order
 LPC_LCD->CTRL &= ~(1<<9);
 // little endian pix order
 LPC_LCD->CTRL &= ~(1<<10);
 // disable power
 LPC_LCD->CTRL &= ~(1<<11);
 // init pixel clock
 LPC_SC->LCD_CFG = PeripheralClock / ((unsigned long) C_GLCD_PIX_CLK);
 // bypass inrenal clk divider
 LPC_LCD->POL |=(1<<26);
 // clock source for the LCD block is HCLK
 LPC_LCD->POL &= ~(1<<5);
 // LCDFP pin is active LOW and inactive HIGH
 LPC_LCD->POL |= (1<<11);
 // LCDLP pin is active LOW and inactive HIGH
 LPC_LCD->POL |= (1<<12);
 // data is driven out into the LCD on the falling edge
 LPC_LCD->POL &= ~(1<<13);
 // active high
 LPC_LCD->POL &= ~(1<<14);
 LPC_LCD->POL &= ~(0x3FF <<16);
 LPC_LCD->POL |= (C_GLCD_H_SIZE-1)<<16;
 
 // init Horizontal Timing
 LPC_LCD->TIMH = 0; //reset TIMH before set value
 LPC_LCD->TIMH |= (C_GLCD_H_BACK_PORCH - 1)<<24;
 LPC_LCD->TIMH |= (C_GLCD_H_FRONT_PORCH - 1)<<16;
 LPC_LCD->TIMH |= (C_GLCD_H_PULSE - 1)<<8;
 LPC_LCD->TIMH |= ((C_GLCD_H_SIZE/16) - 1)<<2;
 
 // init Vertical Timing
 LPC_LCD->TIMV = 0;  //reset TIMV value before setting
 LPC_LCD->TIMV |= (C_GLCD_V_BACK_PORCH)<<24;
 LPC_LCD->TIMV |= (C_GLCD_V_FRONT_PORCH)<<16;
 LPC_LCD->TIMV |= (C_GLCD_V_PULSE - 1)<<10;
 LPC_LCD->TIMV |= C_GLCD_V_SIZE - 1;
 
 // Frame Base Address doubleword aligned
 LPC_LCD->UPBASE = LCD_VRAM_BASE_ADDR & ~7UL ;
 LPC_LCD->LPBASE = LCD_VRAM_BASE_ADDR & ~7UL ;
 
 
 //here I am trying to draw 2 red lines. WORKS but the second line continues to the 3rd part of the screen.
 
 for( i = 0; 320*5 > i; i++)
 {
  *pDst++ = 0xFF0000;
 }
 
 
 //here I am trying to draw from line 5 to line 100 - the colour green. Also works - but the last 2 lines are teared.
   for( i = 320*5; 320*100 > i; i++)
 {
    //*pDst16++ = purple;
  *pDst++ = 0x00FF00;
 }  
}
and the .h as follows:
#ifndef __LPC177X_8X_LCD_H_
#define __LPC177X_8X_LCD_H_

#include "LPC177x_8x.h"
#include "lpc_types.h"
#include "system_LPC177x_8x.h"
#define LCD_VRAM_BASE_ADDR  ((unsigned long)SDRAM_BASE + 0x00010000)
#define LCD_CURSOR_BASE_ADDR  ((unsigned long)0x20088800)
#define C_GLCD_REFRESH_FREQ     (30) // Hz
#define C_GLCD_H_SIZE           320
#define C_GLCD_H_PULSE          30 
#define C_GLCD_H_FRONT_PORCH    20
#define C_GLCD_H_BACK_PORCH     38 
#define C_GLCD_V_SIZE           240
#define C_GLCD_V_PULSE          3
#define C_GLCD_V_FRONT_PORCH    5 
#define C_GLCD_V_BACK_PORCH     15 
#define C_GLCD_PWR_ENA_DIS_DLY  1000
#define C_GLCD_ENA_DIS_DLY      1000
#define TEXT_DEF_TAB_SIZE 5
#define TEXT_BEL1_FUNC()
void GLCD_Init (const unsigned long *pPain, const unsigned long * pPallete);
void GLCD_Ctrl (Bool bEna);
#endif   /*__LPC177X_8X_LCD_H_*/
Also checked against UM10470 all the lcd registers, added some , tweaked some ... but made no difference. 
Please point me to the right direction. 
In this configuration I am measuring on the trace with an oscilloscope the values: 
   LCD clock - 6.31 MhZ
   HSync - 15.4 Khz
   VSync - 58.8 Hz
 Thankyou verry much in advance !
Popte.
标签 (4)
4 回复数

2,015 次查看
poptelecanconst
Contributor II

Hello again, 

  This is a picture with the output on the screen.

  I am trying to write "Hello World" just once - but  appears twice, 3 times ... 

 All day I checked the lines again. I connected pin 34 (Data Enable) to GND. As mentioned in datasheet at page 8 - "DE signal is fixed low for SYNC mode ".

  Now vsync and hsync has an impact (when changed in code). Also pulse moves the image up/down, right / left.

  I still have the problem (always did) wit that tearing / double / triple content. I am in progress of troubleshooting the SDRAM.

  Please remember I have a single external SDRAM module, NOT 2. I searched everywhere , and seems that 2 x 16 bit modules are needed for LCD , but I would love to make this work as it is.

  After the picture I've attached the source code for SDRAM init. I am sure I will be asked about it ... 

  Thankyou again.

Popte.IMG_0048.JPG 

#define EMC_NS2CLK(ns, nsPerClk)     ((ns + nsPerClk - 1) / nsPerClk)
#define tCLK_ns ((double)EMCClock / 1000000000.0 )     // CCLK periods in ns
volatile uint32_t ringosccount[2] = {0,0};
#define MDKCFG_RASCAS0VAL     0x00000303
#define MDKCFG_RASCAS1VAL     0x00000303


void EMC_GPIO_Init (void)
{
    // (ok comment - means I checked the line with a multimeter / oscilloscope)
    LPC_IOCON->P2_16 = 0x00000021; /* CASN @ P2.16 */ //ok CAS
    LPC_IOCON->P2_17 = 0x00000021; /* RASN @ P2.17 */ //ok RAS
    LPC_IOCON->P2_18 = 0x00000021; /* CLK[0] @ P2.18 */ //ok CLK
    LPC_IOCON->P2_20 = 0x00000021; /* DYCSN[0] @ P2.20 */ //ok CS
    LPC_IOCON->P2_24 = 0x00000021; /* CKE[0] @ P2.24 */
    LPC_IOCON->P2_28 = 0x00000021; /* LDQM[0] @ P2.28 */
    LPC_IOCON->P2_29 = 0x00000021; /* UDQM[1] @ P2.29 */
     
    LPC_IOCON->P3_0 = 0x00000021; /* D0 @ P3.0 */ //ok 
    LPC_IOCON->P3_1 = 0x00000021; /* D1 @ P3.1 */ //ok
    LPC_IOCON->P3_2 = 0x00000021; /* D2 @ P3.2 */ //ok
    LPC_IOCON->P3_3 = 0x00000021; /* D3 @ P3.3 */ //ok

    LPC_IOCON->P3_4 = 0x00000021; /* D4 @ P3.4 */ //ok
    LPC_IOCON->P3_5 = 0x00000021; /* D5 @ P3.5 */ //ok
    LPC_IOCON->P3_6 = 0x00000021; /* D6 @ P3.6 */ //ok
    LPC_IOCON->P3_7 = 0x00000021; /* D7 @ P3.7 */ //ok

    LPC_IOCON->P3_8 = 0x00000021; /* D8 @ P3.8 */ //ok
    LPC_IOCON->P3_9 = 0x00000021; /* D9 @ P3.9 */ //ok
    LPC_IOCON->P3_10 = 0x00000021; /* D10 @ P3.10 */ //ok
    LPC_IOCON->P3_11 = 0x00000021; /* D11 @ P3.11 *///ok

    LPC_IOCON->P3_12 = 0x00000021; /* D12 @ P3.12 */ //ok
    LPC_IOCON->P3_13 = 0x00000021; /* D13 @ P3.13 */ //ok
    LPC_IOCON->P3_14 = 0x00000021; /* D14 @ P3.14 */ //ok
    LPC_IOCON->P3_15 = 0x00000021; /* D15 @ P3.15 */ //ok
               
    
    LPC_IOCON->P4_0 = 0x00000021; /* A0 @ P4.0 */ //ok
    LPC_IOCON->P4_1 = 0x00000021; /* A1 @ P4.1 */ //ok
    LPC_IOCON->P4_2 = 0x00000021; /* A2 @ P4.2 */ // ok
    LPC_IOCON->P4_3 = 0x00000021; /* A3 @ P4.3 */ // ok

    LPC_IOCON->P4_4 = 0x00000021; /* A4 @ P4.4 */ // ok
    LPC_IOCON->P4_5 = 0x00000021; /* A5 @ P4.5 */ //ok 
    LPC_IOCON->P4_6 = 0x00000021; /* A6 @ P4.6 */ //ok
    LPC_IOCON->P4_7 = 0x00000021; /* A7 @ P4.7 */ //ok 

    LPC_IOCON->P4_8 = 0x00000021; /* A8 @ P4.8 */ //ok
    LPC_IOCON->P4_9 = 0x00000021; /* A9 @ P4.9 */ //ok
    LPC_IOCON->P4_10 = 0x00000021; /* A10 @ P4.10 */ //ok
    LPC_IOCON->P4_11 = 0x00000021; /* A11 @ P4.11 */ //ok
          
    LPC_IOCON->P4_12 |= 0x00000021; // BA0 //ok
    LPC_IOCON->P4_13 |= 0x00000021; // BA1 //ok 
    
    LPC_IOCON->P4_25 = 0x00000021; /* WEN @ P4.25 */
                              
}


void SDRAM_Init (void)
{
    uint32_t i, dwtemp = dwtemp;
    uint16_t wtemp = wtemp;
       uint32_t mhz, nsPerClk;
    /* Enable External Memory Controller power/clock */
     
LPC_SC->PCONP      |= 0x00000800;
LPC_SC->EMCDLYCTL   = 0x00001010;
//LPC_SC->EMCCLKSEL=0;    //60 MHZ 

LPC_SC->EMCDLYCTL   = 0x00080808; 
     
LPC_EMC->Control    = 0x00000001;
LPC_EMC->Config     = 0x00000000;
  

    EMC_GPIO_Init();
     
     mhz = SystemCoreClock / 1000000;


 
LPC_EMC->DynamicConfig0    = 0x00000480; /* 128B, 8Mx16, row=12, 4 banks,  column=9 */
//Timing for 120MHz Bus: 8.333333 ns/clk
LPC_EMC->DynamicRasCas0    = 0x00000302; // 3 RAS, 3 CAS latency */
LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
LPC_EMC->DynamicRP         = 0x00000003; // Min 20ns. (n + 1) -> 3 clock cycles
LPC_EMC->DynamicRAS        = 0x00000006; // Min 44 ns.(n + 1) -> 6 clock cycles
LPC_EMC->DynamicSREX       = 0x0000000A; // Min 75 ns. ( n + 1 ) -> 10 clock cycles */
LPC_EMC->DynamicAPR        = 0x00000005; // ??? ( n + 1 ) -> 2 clock cycles */
LPC_EMC->DynamicDAL        = 0x00000006; // tWR + tRP: min 35 ns (n + 1) -> 5 clock cycles */
LPC_EMC->DynamicWR         = 0x00000002; // Min 15 ns. ( n + 1 ) -> 2 clock cycles */
LPC_EMC->DynamicRC         = 0x00000008; // Min 66 ns. ( n + 1 ) -> 8 clock cycles */
LPC_EMC->DynamicRFC        = 0x00000008; // Min 66 ns. ( n + 1 ) -> 8 clock cycles */
LPC_EMC->DynamicXSR        = 0x0000000A; // Min 75 ns. ( n + 1 ) -> 10 clock cycles */
LPC_EMC->DynamicRRD        = 0x00000002; // Min 15 ns. ( n + 1 ) -> 2 clock cycles */
LPC_EMC->DynamicMRD        = 0x00000002; // 2 tCK. ( n + 1 ) -> 2 clock cycles */

for (i=0;i<200000;i++){LPC_EMC->DynamicControl    = 0x00000183;}
delayMs(0, 100);
LPC_EMC->DynamicControl    = 0x00000183; /* Issue NOP command */
delayMs(0, 200);  
LPC_EMC->DynamicControl    = 0x00000103; /* Issue PALL command */
LPC_EMC->DynamicRefresh    = 0x00000002; /* ( n * 16 ) -> 32 clock cycles */

for(i = 0; i < 0x80; i++);           /* wait 128 AHB clock cycles */

//Timing for 120MHz Bus
LPC_EMC->DynamicRefresh    = 0x2E;
LPC_EMC->DynamicControl    = 0x00000083; /* Issue MODE command */

//Timing for 48/60/72MHZ Bus
dwtemp = *((volatile uint32_t *)(SDRAM_BASE | (0x33<<(12)))); /* 8 burst, 3 CAS latency */
LPC_EMC->DynamicControl    = 0x00000000; /* Issue NORMAL command */

//[re]enable buffers
LPC_EMC->DynamicConfig0    |= 0x00080000; // Buffer enable
//TIM_Waitms(100);

}
0 项奖励
回复

2,015 次查看
poptelecanconst
Contributor II

Hello everyone ! 

  With GREAT JOY I must update you that I FINALLY solved the problem. Took me over 40 hours of study and debug ... for such a simple solution.

  As you may guess ... YES dumb me I initialized WRONG the memory address mapping. 

 In UM10470 at page 196 (table 134 , address mapping) ->

  LPC_EMC->DynamicConfig0    = (1 << 14) |  /* AM[14]   = 1                   */
                               (1 << 12) |  /* AM[12]   = 0                   */
                               (2 <<  9) |  /* AM[11:9] = 2                   */
                               (0 <<  7) ;  /* AM[8:7]  = 1                   */

THAT is 128Mbit (8Mx16) 4 banks row length =12 column = 10

I hope it will help someone with the same problem as me. This was a single line of code that took me to a 5 day non-stop trouble-shooting, measuring, testing, trace observation, code debug .... 

THANKYOU everyone so much !

Popte.

0 项奖励
回复

2,015 次查看
jeremyzhou
NXP Employee
NXP Employee

Hi,
According to the AS4C8M16SA's datasheet, it's a 16-bit wide memory whose row and column length is 12 and 9 respectively.
So in my opinion, it should be configured as the following figure shows.

pastedImage_1.png
Have a great day,
TIC


-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,015 次查看
poptelecanconst
Contributor II

Hi Jeremy and Many Thanks for Your message. 

   I got an email (a notification) from NXP community yesterday, on my phone, while I was in the city, that someone added a reply. 

  I read the reply and HONESTLY I was SCARED to even try anyhing. Just because I was sure that I will break things again (not by changing a line of code, but because I realised you are 100% right in theory, and I was scared it WON'T work). And then ... my nightmare would start again. Re-calculate and re-think the ... timings to figure out WHY.

  

 OK, this evening I decided ... what the hell. I should try it. And I did. AND YES. WORKS. 

Yes you are 100% correct. Thankyou for your great observation. It would have been produced with my euroneus initialization, and maybe later on something bad would have happened. 

Now ... so I won't live in ignorance, I will spend this night to try to find out (and understand) WHY it has been working with my init ... I will report back.

        Thankyou verry much. 

I wish you all the best, and alot of health ! 

Popte.

0 项奖励
回复