LCD 7 Inch and EMC Buffer

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LCD 7 Inch and EMC Buffer

985 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hamidrm on Sat Sep 13 15:03:20 MST 2014
Hi
I have two problem with my LCD 7 inch working. I m using LPC1788. I locate 2 buffer for lcd 7 inch at K4S561632C memory. a buffer for current show and a  wait buffer for drawing. I am using double buffer to make fast drawing images and make immediately drawing.
I used from DMA to copying data in buffers. but DMA need some delay to done copying successfully.
void SwapBuffer(){
LPC_LCD->UPBASE = (VIDEOWAITBUFFER_BASE_ADDR) & ~7UL ;
LPC_LCD->LPBASE = (VIDEOWAITBUFFER_BASE_ADDR) & ~7UL ;

DMI_SDRAM->TransferType = GPDMA_TRANSFERTYPE_M2M;
DMI_SDRAM->TransferSize = 4000;
DMI_SDRAM->TransferWidth = 2;

for(j=0;j<6;j++){
for(i=0;i<8;i++){
DMI_SDRAM->ChannelNum = i;
DMI_SDRAM->SrcMemAddr = VIDEOWAITBUFFER_BASE_ADDR+4000*i*4+16000*8*j;
DMI_SDRAM->DstMemAddr = VIDEOBUFFER_BASE_ADDR+4000*i*4+16000*8*j;
GPDMA_Setup(DMI_SDRAM);
GPDMA_ChannelCmd(i,ENABLE);
}
for(i=0;i<200000;i++);
}

LPC_LCD->UPBASE = (VIDEOBUFFER_BASE_ADDR) & ~7UL ;
LPC_LCD->LPBASE = (VIDEOBUFFER_BASE_ADDR) & ~7UL ;
.
.
.
.

It work correctly , but is too slowly... How can i speedup copying???
my second problem is CLK of LCD. The LCD image have a some vibration! It is caused of low CLK frequency . but when i increase CLK frequency , LCD work but with noise... I think EMC or LCD not work at Maximum speed. please check my code :

voidInitSDMEM(){
uint32_t i=0;
volatile unsigned long Dummy;
PINSEL_ConfigPin(2,16,1); // /CAS
PINSEL_ConfigPin(2,17,1); // /RAS
PINSEL_ConfigPin(2,18,1); // CLK
PINSEL_ConfigPin(2,24,1); // CKE
PINSEL_ConfigPin(2,28,1); // LDQM
PINSEL_ConfigPin(2,29,1); // UDQM
PINSEL_ConfigPin(2,20,1); // /DYCS
for(;i<16;i++){
PINSEL_ConfigPin(3,i,1); // DATA(i)
}
for(i=0;i<15;i++){
PINSEL_ConfigPin(4,i,1); // DATA(i)
}
PINSEL_ConfigPin(4,25,1); // /WE
LPC_SC->PCONP |= (1<<11); // Power on EMC Clock
LPC_SC->EMCDLYCTL |= (4 <<16); // CLK = 100MHz According datasheet
LPC_EMC->DynamicControl = 0x0183;  // NOP COMMAND
for(i= 200*30; i;i--);
LPC_EMC->DynamicControl = 0x0103; // PALL COMMAND
LPC_EMC->Control = 1;
LPC_EMC->DynamicReadConfig = 1;
LPC_EMC->DynamicRP = P2C(SDRAM_TRP);
LPC_EMC->DynamicRAS = P2C(SDRAM_TRAS);
LPC_EMC->DynamicSREX = P2C(SDRAM_TXSR);
LPC_EMC->DynamicAPR = SDRAM_TAPR;
LPC_EMC->DynamicDAL = SDRAM_TDAL+P2C(SDRAM_TRP);
LPC_EMC->DynamicWR = SDRAM_TWR;
LPC_EMC->DynamicRC = P2C(SDRAM_TRC);
LPC_EMC->DynamicRFC = P2C(SDRAM_TRFC);
LPC_EMC->DynamicXSR = P2C(SDRAM_TXSR);
LPC_EMC->DynamicRRD = P2C(SDRAM_TRRD);
LPC_EMC->DynamicMRD = SDRAM_TMRD;
LPC_EMC->DynamicConfig0 = 0x0080680;
LPC_EMC->DynamicRefresh = 0x100;//P2C(SDRAM_REFRESH) >> 4;
LPC_EMC->DynamicRasCas0 = 0x303;
LPC_EMC->DynamicControl    = 0x00000083; // MODE COMMAND
Dummy = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<12)));
LPC_EMC->DynamicControl = 0x0000;
for(i = 100000; i;i--);
}



#define REFRESH_FREQ 100//Hz
#define LCDDCLK(uint8_t)(120000000*((1.0/REFRESH_FREQ)/(TFTLCD_X_SIZE*TFTLCD_Y_SIZE)))

void TFTLCDInit(){
uint32_t i;
TFTLCDConfigPins();
LPC_LCD->CRSR_CTRL &=~(1<<0);
LPC_SC->PCONP |= 1;//Power On LCD Controller
LPC_LCD->TIMH = (HSW - 1)<<8 | (HFP - 1)<<16 | (HBP - 1)<<24;
LPC_LCD->TIMV = (LPP - 1)<<0 | (VSW - 1)<<10 | (VFP)<<16 | (VBP)<<24;
LPC_LCD->POL = LCDDCLK | ( (ACB - 1)<<6 ) | (IVS<<11) | (IHS<<12) | (IPC<<13) | (CPL-1)<<16;  // ~40Hz Refresh
LPC_LCD->CTRL = (6 << 1) | (1 << 5);
LPC_LCD->UPBASE = VIDEOBUFFER_BASE_ADDR & ~7UL ;
LPC_LCD->LPBASE = VIDEOBUFFER_BASE_ADDR & ~7UL ;
for (i = 0; i < ( sizeof(LPC_LCD->PAL) / sizeof(LPC_LCD->PAL[0]) ); i++) 
  LPC_LCD->PAL = 0;  //Clear the color palette with black 
LPC_LCD->CTRL |= (1<<0);/* LCD enable control bit */
for(i = TFTLCD_PWR_ENA_DIS_DLY; i; i--);
LPC_LCD->CTRL |= (1<<11);/* enable power */
}

Please help me...
Labels (1)
0 Kudos
8 Replies

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wmues on Mon Sep 15 13:16:51 MST 2014
Don't be confused by the 2 frame base registers. The 2nd frame base register (UPBASE) is for a dual-screen output. You don't need it. Use only 1 frame base register.

Add an LCD interrupt handler to your code:

volatile void *newpicture = NULL;
volatile void *freepicture = &videobuffer2;

void LCD_Interrupt_Handler(void)
{
   if (vertical_blank_interrupt) {
      if (newpicture) {
          freepicture = LPBASE;
          LPBASE = newpicture;
          newpicture = NULL;
      }
   }
}

void *getDrawbuffer(void)
{
   while (1) {
      if (freepicture)
          return freepicture;
      waste_some_time();
   }
}

void displayNewPicture(void *picture)
{
    freepicture = NULL;
    newpicture = picture;
}

void Paint(void)
{
    void *p = getDrawbuffer();
    Draw_Into(p);
    displayNewPicture(p);
}

void Init(void)
{
    LPBASE = &videobuffer1;
}
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hamidrm on Mon Sep 15 07:41:44 MST 2014
thank you pacman and wmues. I know there are 2 frame base address register( UPBASE and LPBASE) and 1788 frame base address automatically will switch between theme. it is my question : Which frame base address (UPBASE or LPBASE)  selected every time and When switching will done?? (I can realize it by interrupt, but when??) How can i know which of them is current frame buffer?
I think every frame that is shown every time, after shown , it will copy to another one buffer and then next frame will show another buffer. Is it true??

Now my code work well. without any collide and flickering... and without LPBUFFER and hardware switching (just UPBUFFER used)  8-) .
[img]http://i61.tinypic.com/2lbdk6d.jpg[/img]
void TFTLCDInit(){
uint32_t i;
TFTLCDConfigPins();
LPC_LCD->CRSR_CTRL &=~(1<<0);
LPC_SC->PCONP |= 1;//Power On LCD Controller
LPC_LCD->TIMH = (HSW - 1)<<8 | (HFP - 1)<<16 | (HBP - 1)<<24;
LPC_LCD->TIMV = (LPP - 1)<<0 | (VSW - 1)<<10 | (VFP)<<16 | (VBP)<<24;
LPC_LCD->POL = LCDDCLK | ( (ACB - 1)<<6 ) | (IVS<<11) | (IHS<<12) | (IPC<<13) | (CPL-1)<<16;
LPC_LCD->CTRL = (6 << 1) | (1 << 5);
LPC_LCD->UPBASE = VIDEOBUFFER_BASE_ADDR & ~7UL ;
for (i = 0; i < ( sizeof(LPC_LCD->PAL) / sizeof(LPC_LCD->PAL[0]) ); i++) 
  LPC_LCD->PAL = 0;  //Clear the color palette with black 
LPC_LCD->CTRL |= (1<<0);/* LCD enable control bit */
for(i = TFTLCD_PWR_ENA_DIS_DLY; i; i--);
LPC_LCD->CTRL |= (1<<11);/* enable power */
}
.
.
.
void SwapBuffer(){
uint32_t i=0,j=0;
LPC_LCD->UPBASE = (VIDEOWAITBUFFER_BASE_ADDR) & ~7UL ;
DMI_SDRAM->TransferType = GPDMA_TRANSFERTYPE_M2M;
DMI_SDRAM->TransferSize = 4000;
DMI_SDRAM->TransferWidth = 2;
for(j=0;j<6;j++){
for(i=0;i<8;i++){
DMI_SDRAM->ChannelNum = i;
DMI_SDRAM->SrcMemAddr = VIDEOWAITBUFFER_BASE_ADDR+4000*i*4+16000*8*j;
DMI_SDRAM->DstMemAddr = VIDEOBUFFER_BASE_ADDR+4000*i*4+16000*8*j;
GPDMA_Setup(DMI_SDRAM);
GPDMA_ChannelCmd(i,ENABLE);
}
for(i=0;i<68000;i++); // a short delay
}
LPC_LCD->UPBASE = (VIDEOBUFFER_BASE_ADDR) & ~7UL ;
}
.
.
.
void SetPixel(uint16_t X, uint16_t Y, RGB16 color)
{
    
uint16_t *pLCDbuf = (uint16_t *)VIDEOWAITBUFFER_BASE_ADDR;  /* LCD buffer start address */
pLCDbuf[ Y * SCREEN_WIDTH + X ] = color.A | color.B<<8;
}
.
.
.
// An Analog Watch Drawing
void DrawWatch(uint16_t x,uint16_t y){
double m=20,h=0,s=0,ma,ha,sa;
ClearScreen(White);
while(1){
Delay(0x5FFF);
ClearScreen(White);
sa = (-0.5+s/30.0)*3.14;
ma = (-0.5+m/30.0)*3.14;
ha = (-0.5+h/24.0)*3.14+((m/360)*3.14);
DrawCircle(x,y,100,LightGrey,3);
DrawLine(cos(ha)*-20.0+x,sin(ha)*-20.0+y,cos(ha)*60.0+x,sin(ha)*60.0+y,LightGrey,3);
DrawLine(cos(ma)*-20.0+x,sin(ma)*-20.0+y,cos(ma)*80.0+x,sin(ma)*80.0+y,LightGrey,3);
DrawLine(cos(sa)*-30.0+x,sin(sa)*-30.0+y,cos(sa)*80.0+x,sin(sa)*80.0+y,Red,2);
SwapBuffer();
s = RTC_GetTime(LPC_RTC,RTC_TIMETYPE_SECOND);
m = RTC_GetTime(LPC_RTC,RTC_TIMETYPE_MINUTE);
h = RTC_GetTime(LPC_RTC,RTC_TIMETYPE_HOUR);
}
}
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wmues on Mon Sep 15 00:51:09 MST 2014
It is common standard to

- draw everything in the offscreen buffer
- marking the offscreen buffer as "ready"
- flipping the buffers in the vertical blanking interrupt
- wait with the next drawing into the new buffer until the flipping has occured.

regards
Wolfgang

0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Sun Sep 14 13:52:59 MST 2014
What hamidrm is doing may be correct.

If you just flip between the buffers, you will have flickering.
You have two options:
1: Draw everything on the 'offscreen' before switching the double-buffer pointer.
2: Copy everything already on the displayed screen before switching the double-buffer pointer.

Otherwise you will get flickering.
If you do not know what's on the screen already, then copying would be the only option.
On the other hand, if you're drawing everything yourself, you could in some cases make the redrawing faster than copying.

However... consider that you use the DMA for copying. Memory-to-memory is very fast, so you may not be able to keep up with it.

@hamidrm:
You may want to set up interrupts. I know the LPC1788 supports Vertical Blanking Interrupts, which means each time a new frame is to be drawn, your interrupt will be triggered.
So you would probably want to set some flag in your interrupt, that a VBL has occurred, perhaps increment a VBL-counter.
You may also want another flag, that tells your interrupt that the off-screen buffer is ready to be displayed, and that the interrupt should take care of switching to the off-screen buffer and then copy the new on-screen data to the new off-screen buffer.
Thus you can safely complete your drawing, and when done, you set your "ready" flag, and you wait until the interrupt has occurred (that's usually called vsync).

Note: Make sure your DMA copying do not collide with your LCD controller's reading of the memory. This means it might be a good idea to do the copying right after the last LCD line has been displayed.
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wmues on Sun Sep 14 10:34:02 MST 2014
I do not understand why you use a DMA to copy your video buffers.
Because the 1788 LCD controller can do double buffering without help.

You have declared a VIDEOBUFFER and a VIDEOWAITBUFFER. This is plain wrong.

The solution is to have 2 buffers, and swap these buffers between output and drawing.

regards
Wolfgang
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hamidrm on Sun Sep 14 10:18:05 MST 2014
Thanx a lot guy, because of your important notice ;-)
My problam has been solved  :bigsmile:
I had used from the half CPU clock for EMC clock (EMCDIV was 1 that changed to 0)
And I have some mistakes at EMC initial function that changed. Every things ("SetPixel" function) are drawing fast now , better than emWin  J) !!!
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Sun Sep 14 04:21:21 MST 2014
You will need to be patient. Especially during weekends. The worst thing you can do is to reply to your own question, as people will see in the list that it has an answer. If a question / post has no answers, it's more likely to be answered.
-But I recommend waiting for a number of days, because the one who can answer your question might not drop in every day.
Unfortunately I am not able to help, even though I have a LPC1788, because I can't attach external RAM to it.
0 Kudos

829 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by hamidrm on Sat Sep 13 23:22:01 MST 2014
No body cant help me????
0 Kudos