LCD Frame Buffer

23 replies [Last post]
dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

I have a custom designed board populated with the LPC1788 and a 32-bit wide SDRAM chip. I seem to be having bus contention issues between the LCD and my frame buffer update routine. I have found that if I allow them to access the memory space simultaneously the LCD gets out of sync and displays pseudo-random data. So if I load buffer #1 with half red data and the other half with blue, the LCD will display this beautifully. As soon as I begin accessing (asynchonrously) the SDRAM to write to buffer 2, the blue and red data start mixing randomly. Does anyone know how to synchronize my buffer updates with the LCD DMA requests so that I don't step on those requests? I thought changing the matrix arbitration register might help but that did not seem to make a difference which is also puzzling.

And on a related note, what was NXP thinking forcing users to under-clock the CPU if they want to use SDRAM?! Why is the EMC limited to 80MHz?

Thanks in advance for any advice given!

0
Your rating: None

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
wmues
Offline
Joined: 2011-08-16
Posts: 118

I am using a 480x272 LCD with 16bit RGB, a 16bit SDRAM with 78MHz Clock, and Code Execution from SDRAM. There is no visible display distortion.

So I assume you are doing something weird with the LCD controller. Post your code here.

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Lcd::Lcd()
{

//Initialize the frame buffer/external memory controller
unsigned int ConfigPointer;

//Set bus matrix arbitration priorities (see datasheet)
volatile unsigned int * AHB_Arbitration = (unsigned int *) 0x400FC188;
*AHB_Arbitration = 0x00000C09;

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

LPC_IOCON->P2_14 = 1; //EMC_CS2
LPC_IOCON->P2_15 = 1; //EMC_CS3
LPC_IOCON->P2_16 = 1; //EMC_CAS
LPC_IOCON->P2_17 = 1; //EMC_RAS
LPC_IOCON->P2_18 = 1; //EMC_CLK[0]
LPC_IOCON->P2_19 = 1; //EMC_CLK[1]
LPC_IOCON->P2_20 = 1; //EMC_DYCS0
LPC_IOCON->P2_21 = 1; //EMC_DYCS1
LPC_IOCON->P2_22 = 1; //EMC_DYCS2
LPC_IOCON->P2_23 = 1; //EMC_DYCS3
LPC_IOCON->P2_24 = 1; //EMC_CKE0
LPC_IOCON->P2_25 = 1; //EMC_CKE1
LPC_IOCON->P2_26 = 1; //EMC_CKE2
LPC_IOCON->P2_27 = 1; //EMC_CKE3
LPC_IOCON->P2_28 = 1; //EMC_DQM0
LPC_IOCON->P2_29 = 1; //EMC_DQM1
LPC_IOCON->P2_30 = 1; //EMC_DQM2
LPC_IOCON->P2_31 = 1; //EMC_DQM3

LPC_IOCON->P3_0 = 1; //EMC_D0
LPC_IOCON->P3_1 = 1; //EMC_D1
LPC_IOCON->P3_2 = 1; //EMC_D2
LPC_IOCON->P3_3 = 1; //EMC_D3
LPC_IOCON->P3_4 = 1; //EMC_D4
LPC_IOCON->P3_5 = 1; //EMC_D5
LPC_IOCON->P3_6 = 1; //EMC_D6
LPC_IOCON->P3_7 = 1; //EMC_D7
LPC_IOCON->P3_8 = 1; //EMC_D8
LPC_IOCON->P3_9 = 1; //EMC_D9
LPC_IOCON->P3_10 = 1; //EMC_D10
LPC_IOCON->P3_11 = 1; //EMC_D11
LPC_IOCON->P3_12 = 1; //EMC_D12
LPC_IOCON->P3_13 = 1; //EMC_D13
LPC_IOCON->P3_14 = 1; //EMC_D14
LPC_IOCON->P3_15 = 1; //EMC_D15
LPC_IOCON->P3_16 = 1; //EMC_D16
LPC_IOCON->P3_17 = 1; //EMC_D17
LPC_IOCON->P3_18 = 1; //EMC_D18
LPC_IOCON->P3_19 = 1; //EMC_D19
LPC_IOCON->P3_20 = 1; //EMC_D20
LPC_IOCON->P3_21 = 1; //EMC_D21
LPC_IOCON->P3_22 = 1; //EMC_D22
LPC_IOCON->P3_23 = 1; //EMC_D23
LPC_IOCON->P3_24 = 1; //EMC_D24
LPC_IOCON->P3_25 = 1; //EMC_D25
LPC_IOCON->P3_26 = 1; //EMC_D26
LPC_IOCON->P3_27 = 1; //EMC_D27
LPC_IOCON->P3_28 = 1; //EMC_D28
LPC_IOCON->P3_29 = 1; //EMC_D29
LPC_IOCON->P3_30 = 1; //EMC_D30
LPC_IOCON->P3_31 = 1; //EMC_D31

LPC_IOCON->P4_0 = 1; //EMC_A0
LPC_IOCON->P4_1 = 1; //EMC_A1
LPC_IOCON->P4_2 = 1; //EMC_A2
LPC_IOCON->P4_3 = 1; //EMC_A3
LPC_IOCON->P4_4 = 1; //EMC_A4
LPC_IOCON->P4_5 = 1; //EMC_A5
LPC_IOCON->P4_6 = 1; //EMC_A6
LPC_IOCON->P4_7 = 1; //EMC_A7
LPC_IOCON->P4_8 = 1; //EMC_A8
LPC_IOCON->P4_9 = 1; //EMC_A9
LPC_IOCON->P4_10 = 1; //EMC_A10
LPC_IOCON->P4_11 = 1; //EMC_A11
LPC_IOCON->P4_12 = 1; //EMC_A12
LPC_IOCON->P4_13 = 1; //EMC_A13
LPC_IOCON->P4_14 = 1; //EMC_A14
LPC_IOCON->P4_15 = 1; //EMC_A15
LPC_IOCON->P4_16 = 1; //EMC_A16
LPC_IOCON->P4_17 = 1; //EMC_A17
LPC_IOCON->P4_18 = 1; //EMC_A18
LPC_IOCON->P4_19 = 1; //EMC_A19
LPC_IOCON->P4_20 = 1; //EMC_A20
LPC_IOCON->P4_21 = 1; //EMC_A21
LPC_IOCON->P4_22 = 1; //EMC_A22
LPC_IOCON->P4_23 = 1; //EMC_A23
LPC_IOCON->P4_24 = 1; //EMC_OE
LPC_IOCON->P4_25 = 1; //EMC_WE
LPC_IOCON->P4_30 = 1; //EMC_CS0
LPC_IOCON->P4_31 = 1; //EMC_CS1

LPC_EMC->DynamicConfig0    = 0x00004300; //set bank size
LPC_EMC->DynamicRasCas0 = 0x00000201; //1 RAS, 2 CAS latency
LPC_EMC->DynamicReadConfig = 0x00000001; //command delayed strategy, using EMCCLKDELAY
LPC_EMC->DynamicRP = 0x00000000; //1 clock cycle
LPC_EMC->DynamicRAS = 0x00000002; //3 clock cycles
LPC_EMC->DynamicSREX = 0x00000003; //4 clock cycles
LPC_EMC->DynamicAPR = 0x00000001; //2 clock cycles
LPC_EMC->DynamicDAL = 0x00000002; //2 clock cycles
LPC_EMC->DynamicWR = 0x00000001; //2 clock cycles
LPC_EMC->DynamicRC = 0x00000003; //4 clock cycles
LPC_EMC->DynamicRFC = 0x00000003; //4 clock cycles
LPC_EMC->DynamicXSR = 0x00000003; //4 clock cycles
LPC_EMC->DynamicRRD = 0x00000000; //1 clock cycle
LPC_EMC->DynamicMRD = 0x00000000; //1 clock cycle

Timer::Delay(100); //wait 100ms
LPC_EMC->DynamicControl = 0x00000183; //issue NOP command

Timer::Delay(200); //wait 200ms
LPC_EMC->DynamicControl = 0x00000103; //issue PALL command
LPC_EMC->DynamicRefresh = 0x00000002;

Timer::Delay(10);

LPC_EMC->DynamicRefresh = 0x0000001A; //set refresh timing
LPC_EMC->DynamicControl = 0x00000083; //issue MODE command
ConfigPointer = *((volatile uint32_t *)(RamBaseAddress | (0x22 << (2 + 2 + 9)))); //load 4 burst, 2 CAS latency
LPC_EMC->DynamicControl = 0x00000000; //issue NORMAL command
LPC_EMC->DynamicConfig0 = 0x00084300; //re-enable buffer
ConfigPointer++; //Only here to eliminate compiler warning

if(!RunBufferTest())
while(1); //Test failed, TODO

//Initialize the backlight control
LPC_IOCON->P1_2 = 3; //PWM0
LPC_PWM0->MR0 = MaxPwmScale;
LPC_PWM0->MCR |= 0x02;
LPC_PWM0->MR1 = MaxPwmScale / 2;
LPC_PWM0->LER |= 0x03;
LPC_PWM0->PCR |= 0x200;
LPC_PWM0->TCR |= 0x01;

Timer::Delay(100); //Delay to guaranteee LCD has powered-up

//Lcd Setup

//Setup LCD Pins
LPC_IOCON->P2_4 = 0x207; //DE
LPC_IOCON->P2_2 = 0x207; //CLK

LPC_IOCON->P4_29 = 0x207; //R1 (LCD_VD[3])
LPC_IOCON->P2_6 = 0x207; //R2 (LCD_VD[4])
LPC_IOCON->P2_7 = 0x207; //R3 (LCD_VD[5])
LPC_IOCON->P2_8 = 0x207; //R4 (LCD_VD[6])
LPC_IOCON->P2_9 = 0x207; //R5 (LCD_VD[7])

LPC_IOCON->P1_20 = 0x207; //G0 (LCD_VD[10])
LPC_IOCON->P1_21 = 0x207; //G1 (LCD_VD[11])
LPC_IOCON->P1_22 = 0x207; //G2 (LCD_VD[12])
LPC_IOCON->P1_23 = 0x207; //G3 (LCD_VD[13])
LPC_IOCON->P1_24 = 0x207; //G4 (LCD_VD[14])
LPC_IOCON->P1_25 = 0x207; //G5 (LCD_VD[15])

LPC_IOCON->P2_13 = 0x207; //B1 (LCD_VD[19])
LPC_IOCON->P1_26 = 0x207; //B2 (LCD_VD[20])
LPC_IOCON->P1_27 = 0x207; //B3 (LCD_VD[21])
LPC_IOCON->P1_28 = 0x207; //B4 (LCD_VD[22])
LPC_IOCON->P1_29 = 0x207; //B5 (LCD_VD[23])

LPC_SC->LCD_CFG = PeripheralClock / LcdDataClock + 1; //Set data clock rate

//Set horizontal timing
LPC_LCD->TIMH = 0;
LPC_LCD->TIMH |= ((HorizontalPixelCount / 16) - 1) << 2;
LPC_LCD->TIMH |= (HorizontalPulseLength - 1) << 8;
LPC_LCD->TIMH |= (unsigned long)(HorizontalFrontPorch - 1) << 16;
LPC_LCD->TIMH |= (unsigned long)(HorizontalBackPorch - 1) << 24;

//Set vertical timing
LPC_LCD->TIMV = 0;
LPC_LCD->TIMV |= VerticalLineCount - 1;
LPC_LCD->TIMV |= (VerticalPulseLength - 1) << 10;
LPC_LCD->TIMV |= (VerticalFrontPorch - 1) << 16;
LPC_LCD->TIMV |= (VerticalBackPorch - 1) << 24;

LPC_LCD->POL |= ((HorizontalPixelCount - 1) << 16); //Set clock pulses per line
LPC_LCD->POL |=(1 << 26); //Bypass the pixel clock divider
LPC_LCD->UPBASE = Buffer1BaseAddress; //Set the frame buffer address
LPC_LCD->CTRL |= (0x02 << 1); //Set the bits-per-pixel to 5:5:5 mode
LPC_LCD->CTRL |= (0x01 << 5); //Set the panel type as TFT
LPC_LCD->CTRL |= (0x10 << 12); //Set vertical compare interrupt
LPC_LCD->CTRL |= (0x01 << 16); //Set watermark level to 8

LPC_LCD->INTMSK = 0x08;
NVIC_SetPriority(LCD_IRQn, 0x09); //Set preemption to 1, priority to 1
NVIC_EnableIRQ(LCD_IRQn); //Enable interrupt

LPC_LCD->CTRL |= 0x900; //Power the LCD Controller

SetBrightness(60);

LPC_LCD->CTRL |= 0x801; //Enable LCD Controller
}
Here are the constants:
static const unsigned short HorizontalPixelCount = 800;
static const unsigned short HorizontalPulseLength = 55; //Clock cycles
static const unsigned short HorizontalFrontPorch = 250; //Clock cycles
static const unsigned short HorizontalBackPorch = 250; //Clock cycles

static const unsigned short VerticalLineCount = 480;
static const unsigned short VerticalPulseLength = 30; //Clock cycles
static const unsigned short VerticalFrontPorch = 25; //Lines
static const unsigned short VerticalBackPorch = 25; //Lines

static const unsigned int MaxPwmScale = 100000;
static const unsigned int LcdDataClock = 27500000;
I am using a 7" 800x480 TFT display (datasheet attacxhed) with a MT48LC2M32B2P-6:G TR for the frame buffer. Let me know if anything looks off to you.

PreviewAttachmentSize
FEMA-LCD.pdf694.61 KB
Dave
Offline
Joined: 2011-07-16
Posts: 116

to begin with, double check your calculation on this line:
ConfigPointer = *((volatile uint32_t *)(RamBaseAddress | (0x22 << (2 + 2 + 9)))); //load 4 burst, 2 CAS latency

Since you're using the ROW-BANK-COLUMN format (LPC_EMC->DynamicConfig0 = 0x00004300), I believe your shift should look like this:

CAS_Latency = 2;
   *
   *
   *
ConfigPointer = *((volatile uint32_t *)(RamBaseAddress Angry(0x02+(CAS_Latency<<4))<<12)));

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Thanks for the post Dave. I did try your suggestion, it didn't seem to have any effect. Can you explain to me why the value of ConfigPointer needs to be shifted left?

Do you see anything else I should look into?

Dave
Offline
Joined: 2011-07-16
Posts: 116

Back when this forum first got started I posted a thread about setting up the EMC to talk to an LCD...

There is a lot of good stuff in that thread. There is also a discussion on the shift, and how far...

You can find the thread here: http://lpcware.com/content/forum/dk-57vts-lpc1788-configuring-emc-sdram

Have a look and see what you think.

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Thanks Dave. One thing about your post, right before you send the MODE register, shouldn't you have to send the MODE command? I didn't see that line of code anywhere.

Unfortunately this didn't resolve my problem. I have checked the clock output, it running 84MHz as I thought it was.

One new piece of information is that it currently takes about 13 ms to write 48,000 words. This means it's taking 270ns or ~23 clock cycles to complete one write. Does this imply a timing error somewhere?

Dave
Offline
Joined: 2011-07-16
Posts: 116

Comments 14-19 address the missing MODE command... lol

Timing is certainly important - can you verify your values for these registers, as I have shown here:
   // *** Taken from the MT48LC2M32B2 data sheet, page 47 ***                                  
   // configure timing, from Table 18:                                                         
   // -6 (6ns part) timings (see marking on actual chip: MT48LC2M32B2-6)                       
   // NOTE: all timing values for LPC1788 are in units of CLK counts                           
   // ------------------------------------------------------------------------------------------
   LPC_EMC->DynamicRP   = NS_2_CLKS(18);     // tRP: precharge command period             (18ns)
   LPC_EMC->DynamicRAS  = NS_2_CLKS(42);     // tRAS: active to precharge command period  (42ns)
   LPC_EMC->DynamicSREX = NS_2_CLKS(70);     // tXSR: self-refresh exit time              (70ns)
   LPC_EMC->DynamicAPR  = NS_2_CLKS(18);     // tAPR: last-data-out to active command time     
                                             // note: no tAPR value, using tRCD value     (18ns)
   LPC_EMC->DynamicDAL  = CAS_Latency+2;     // tDAL: data-in to active command time           
                                             //       for CL=3, tDAL = 5 tCK                   
                                             //       for CL=2, tDAL = 4 tCK                   
                                             //       for CL=1, tDAL = 3 tCK                   
   LPC_EMC->DynamicWR   = (1+NS_2_CLKS(6));  // tWR: write recovery time is (12ns) UNLESS we're
                                             //      using AUTO PRECHARGE, then it's   (tCK+6ns)
   LPC_EMC->DynamicRC   = NS_2_CLKS(60);     // tRC: ACTIVE-to-ACTIVE command period      (60ns)
   LPC_EMC->DynamicRFC  = NS_2_CLKS(60);     // tRFC: AUTO REFRESH period                 (60ns)
   LPC_EMC->DynamicXSR  = NS_2_CLKS(70);     // tXSR: Exit self refresh to ACTIVE command (70ns)
   LPC_EMC->DynamicRRD  = NS_2_CLKS(12);     // tRRD: active bank A to active bank B command   
                                             //       latency                             (12ns)
   LPC_EMC->DynamicMRD  = 2-1;               // tMRD: LOAD MODE REGISTER command to ACTIVE or  
                                             // REFRESH command time                      (2tCK)

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Dave, I actually tried your initialization code line for line in a test application and saw little difference in performance. I am seeing a maximum throughput of ~35MB/s with the CPU at 120MHz and the EMC at 60MHz. This means it's taking an average of 7 clock cycles to transfer one word. Are these numbers reasonable?

Dave
Offline
Joined: 2011-07-16
Posts: 116

Sorry, I didn't mean that you should "copy" my code, I meant you should verify your values... each SDRAM device has a table with timing constants. Your device is probably not the same as my device... By the way, what is your device anyway???

I use my device with multiple display pages, and never have any contention - I also run my devices at 120Mhz... again, no problems...

This indicates to me that it is possible, and more than probably you haven't programmed the EMC, the SDRAM, or the LCD controller the way you think you have...

There are several complete examples on how to program the EMC and SDRAM here - Wolfgang has even uploaded his entire driver set here I believe...

The trick is to make sure you have the timing values set properly, and that you are configuring the LCD controller properly...

Not sure how much more I can help without actually doing it for you...

Oh, one more thing - you indicated you are using a custom board - how confident are you in the design? Trace spacing, signal grouping, matched trace lengths, trace widths, dah, dah, dah... All of this comes into play, and can really screw things up if you don't have them just right.

Oh, and another thing - what's the maximum frequency of the SDRAM part you are using?

Just thinking out loud...

Hope this helps,

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Yeah, I didn't mean your code is now sitting in project files, I just meant I dropped your code in a dummy project to try it out.

The exact part number of the chip I'm using is: MT48LC2M32B2P-6:G TR

I think my next step will be to try this out on a development board to verify my trace routing isn't to blame. My board is not impedance matched (controlled dielectric) but the trace width and length was tuned during the layout. In my experience, controlled-dielectric doesn't really become a necessity until you hit several hundred megahertz.

Dave
Offline
Joined: 2011-07-16
Posts: 116

Gotchya - you're using the exact same device I'm using...

I missed the part about the display earlier - you're using a FEMA display - funny, so am I... ( do you know George? )

'cept mine is 640x480...

One thing I did find during development of my own board was that I needed to adjust my delays a bit higher to remove some speckling on the display - my SDRAM memory test indicated no errors, but from time to time there were random pixels being set on the display...

Increasing the values for both the feedback clock and the command outputs eliminated the problem

         //DelayConstant = 0x00000B05;      // dev kit works at 0B05...                         
         DelayConstant = 0x00000F07;      // SBC R1 works at 0F07...                        

   *
   *
   *

   // Setup delays  (Note:  UM has an error in Table #140 - should look like this:                                         
   // [Ref: LPC178x_7x_UM_1.4 page 183 ]                                                                                   
   // ----------------------------------------------------------------------------------------------------------------------
   // Bit      Symbol         Description                                                                              Reset
   //                                                                                                                  Value
   // ----------------------------------------------------------------------------------------------------------------------
   // 4:0      CMDDLY         Programmable delay value for EMC outputs in command delayed mode. See                    0x10
   //                         Section 10.12.6. The delay amount is roughly (CMDDLY+1) * 250 picoseconds.                   
   // 7:5      -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 12:8     FBCLKDLY       Programmable delay value for the feedback clock that controls input data sampling. See   0x02
   //                         Section 10.5.3. The delay amount is roughly (FBCLKDLY+1) * 250 picoseconds.                  
   // 15:13    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 20:16    CLKOUT0DLY     Programmable delay value for the CLKOUT0 output. This would typically be used in clock   0x00
   //                         delayed mode. See Section 10.12.6 The delay amount is roughly (CLKOUT0DLY+1) *               
   //                         250 picoseconds.                                                                             
   // 23:21    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 28:24    CLKOUT1DLY     Programmable delay value for the CLKOUT1 output. This would typically be used in clock   0x00
   //                         delayed mode. See Section 10.12.6 The delay amount is roughly (CLKOUT1DLY+1) *               
   //                         250 picoseconds.                                                                             
   // 31:29    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   //                                                                                                                      
   //  ---X XXXX ---X XXXX ---X XXXX ---X XXXX => DelayConstant = 0x00000C04                                               
   //  0000 0000 0000 0000 0000 1100 0000 0100 => CMDDLY=0x04=1250ps & FBCLKDLY=0x0C=3.25ns                                
   LPC_SC->EMCDLYCTL   = DelayConstant;

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

If I post a performance test project would you be able/willing to try it out on your board? For measurement I am just toggling a GPIO so you would need access to an unused one.

Thanks for all your help so far Dave!

Dave
Offline
Joined: 2011-07-16
Posts: 116

Sure... I'll give it a shot.

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

For anyone interested, I was able to bring an FAE in to look at this issue. Not surprisingly, it stumped him as well. I have attached a test application if anyone (Dave) would like to try it out. You'll probably need to select a different GPIO in the while loop based on what you have easy access to. The low pulse length will be the write time; high pulse length will be the read time.

Throughput in MB/s = (48000 words / pulse length) * 4

Thanks for everyone's help!

PreviewAttachmentSize
LPC1788Test.zip87.83 KB
Dave
Offline
Joined: 2011-07-16
Posts: 116

Dustin,

Reviewing your calculation for throughput:

(800*480)/8 = 48000 operations (both read and write).
Each operation is a 32-bit wide operation, or 4 bytes.
48000*4 = 192000 = number of bytes per time frame.

The scope indicates the write operation takes 2.56ms and the read operation takes 4.66ms (on my board), so processor is writing 75MB/sec and reading 41.2MB/sec...

Does this sound right to you?

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

e135193
Offline
Joined: 2012-03-13
Posts: 32

Hello

Is that enough to modify the settings below for costumising emWin for my LCD ?

Link for my LCD's datasheet : http://elinux.org/images/0/07/AT070TN83.pdf

#define HBP_TRULY_3_2 28 // Horizontal back porch in clocks
#define HFP_TRULY_3_2 10 // Horizontal front porch in clocks
#define HSW_TRULY_3_2 2 // HSYNC pulse width in clocks
#define PPL_TRULY_3_2 240 // Pixels per line
#define VBP_TRULY_3_2 2 // Vertical back porch in clocks
#define VFP_TRULY_3_2 1 // Vertical front porch in clocks
#define VSW_TRULY_3_2 2 // VSYNC pulse width in clocks
#define LPP_TRULY_3_2 320 // Lines per panel
#define IOE_TRULY_3_2 0 // Invert output enable, 1 = invert
#define IPC_TRULY_3_2 1 // Invert panel clock, 1 = invert
#define IHS_TRULY_3_2 1 // Invert HSYNC, 1 = invert
#define IVS_TRULY_3_2 1 // Invert VSYNC, 1 = invert
#define ACB_TRULY_3_2 1 // AC bias frequency in clocks (not used)
#define BPP_TRULY_3_2 16 // Bits per pixel b110 = 16 bpp 5:6:5 mode
#define CLK_TRULY_3_2 8200000 // Optimal clock rate (Hz) between 1-8.22 MHz according to SSD1289 datasheet
#define LCD_TRULY_3_2 0 // Panel type; 0: LCD TFT panel
#define DUAL_TRULY_3_2 0 // No dual panel

As far as I can see from the datasheet of the FEMA LCD, there is no need for an SPI interface for LCD. Then, you do not need the code samples below for your LCD. Do you ? I guess that you need SPI interface just for touch panel interface. Am I rigth ?

static void _InitTrulyLCD(void) {
//
// Power LCD
//
LPC_GPIO2->DIR |= 1; // Set to output
LPC_GPIO2->SET = 1; // Output LCD power
//
// Set display CMD/DATA register select pin to output high
//
LPC_GPIO0->DIR |= (1 << LCD_REG_BIT);
//
// Display init sequence
//
_WriteLcdReg(0x00,0x0001);
_DelayMs(15 * 2);
_WriteLcdReg(0x03,0x6E3E); // AAAC
_WriteLcdReg(0x0C,0x0007); // 0002
_WriteLcdReg(0x0D,0x000E); // 000A
_WriteLcdReg(0x0E,0x2C00); // 2C00
_WriteLcdReg(0x1E,0x00AE); // 00B8
_DelayMs(15 * 2);

_WriteLcdReg(0x07,0x0021);
_DelayMs(50 * 2);
_WriteLcdReg(0x07,0x0023);
_DelayMs(50 * 2);
_WriteLcdReg(0x07,0x0033);
_DelayMs(50 * 2);

_WriteLcdReg(0x01,0x2B3F);
_WriteLcdReg(0x02,0x0600);
_WriteLcdReg(0x10,0x0000);
_DelayMs(15 * 2);
_WriteLcdReg(0x11,0xC5B0); // 60B0: RGB I/R
_DelayMs(20 * 2);
_WriteLcdReg(0x15,0x00D0);

_WriteLcdReg(0x05,0x0000);
_WriteLcdReg(0x06,0x0000);
_WriteLcdReg(0x16,0xEF1C);
_WriteLcdReg(0x17,0x0003);
_WriteLcdReg(0x07,0x0233);
_WriteLcdReg(0x0B,0x5310);
_WriteLcdReg(0x0F,0x0000);
_WriteLcdReg(0x25,0xE000);
_DelayMs(20 * 2);

_WriteLcdReg(0x41,0x0000);
_WriteLcdReg(0x42,0x0000);
_WriteLcdReg(0x48,0x0000);
_WriteLcdReg(0x49,0x013F);
_WriteLcdReg(0x44,0xEF00);
_WriteLcdReg(0x45,0x0000);
_WriteLcdReg(0x46,0x013F);
_WriteLcdReg(0x4A,0x0000);
_WriteLcdReg(0x4B,0x0000);
_DelayMs(20 * 2);

_WriteLcdReg(0x30,0x0707);
_WriteLcdReg(0x31,0x0600); // 0704
_WriteLcdReg(0x32,0x0005); // 0204
_WriteLcdReg(0x33,0x0402); // 0201
_WriteLcdReg(0x34,0x0203);
_WriteLcdReg(0x35,0x0204);
_WriteLcdReg(0x36,0x0204);
_WriteLcdReg(0x37,0x0401); // 0502
_WriteLcdReg(0x3A,0x0302);
_WriteLcdReg(0x3B,0x0500);
_DelayMs(20 * 2);
_WriteLcdReg(0x22,0x0000);
_DelayMs(20 * 2);
}

Thanks in advance

engin

Dave
Offline
Joined: 2011-07-16
Posts: 116

Ummm, your post is a little off topic, Engin. Perhaps you would do better with starting a new thread. I recommend you formulate a question as the thread header, and post your question there...

Good luck,

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

e135193
Offline
Joined: 2012-03-13
Posts: 32

Hello Dave

I clearly know my post is off topic. I have already started a new thread. However no one replys. I know that you are so proficient and you will reply at least an answer.

The pace of this comunity is so slow. There are less senior people like you.

Could you reply one of my threads please ?

http://www.lpcware.com/content/forum/customising-emwin-516-any-other-7-lcd

http://www.lpcware.com/content/forum/eas-7-lcd-interface

Engin

Dave
Offline
Joined: 2011-07-16
Posts: 116

I cannot reply. I have not worked with the emWin library yet. Sorry.

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Dave, I built a project that I have sent to you via email. Can you give this a try on your board when you have time? Let me know what you see (I would expect simply a red screen). If that does work, try un-commenting the code in the while loop and see if anything changes. On my board it quickly changes to blue.

Engin, unfortunately I also have not worked with emWin.

mc's picture
mc
Offline
Joined: 2012-05-21
Posts: 272

Hi engin,
Yes SPI is for touch panel.

Dave
Offline
Joined: 2011-07-16
Posts: 116

So, after our email discussion, did you ever solve your problem? Perhaps others can benefit from your solution, Dustin...

-Dave
"Basic research is what I am doing when I don't know what I am doing"

-Dave
"Basic research is what I am doing when I don't know what I am doing"

dustinkasel
Offline
Joined: 2012-07-31
Posts: 14

Yeah so there were a couple of things that came out from meeting with the engineer from NXP. First off, BA0 and BA1 are connected to A13 and A14 regardless of how many address lines you actually use. I made the assumption that these lines were the most-significant-bits of the address lines.

I also had a solder ball across RAS-CAS that wasn't helping the cause.

Finally I had to re-calculate all of the timing parameters. The SDRAM example that comes with the peripheral library is more or less worthless for real-world testing. I will admit it does run and pass it's tests on the EA board, which has the same part on the SOM as I have.

Interestingly the CAS-RAS issue manifested itself as a refresh failure. I didn't catch this right away because I was constantly reading from/writing to RAM. Once I put long delays in-between accesses that issue popped up.

feedback