Pixel delayed on K70 - MQX - PEG

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

Pixel delayed on K70 - MQX - PEG

Jump to solution
3,738 Views
arnogir
Senior Contributor II

Hello,

I have the tower K70f120m.
I'm using Codewarrior v10.3 and MQX (4.0 or 4.1)
I have the PEG lite (Free on Kinetis)
And I use an LCD screen 800x480


I try the "Hellopeg" exemple provided with the PEG software.
I adapted the twrlcdrgb_k70_16.cpp file for my specific TFT screen.


1) Hellopeg with Codewarrior in standalone (No MQX):
When I swith display from picture to another, following function is called: K70_TWRLCDScreen::MemoryToScreen
This function copy bitmap to the background LCD memory.
During this step, the code write data in the same memory (DDR) than read by the LCD COntroller.
So the display is bad during this step. Some pixels are delayed. Horizontal line appears on the screen.


2) HelloPeg with Cw and MQX.
The MQX must access at anytime in the RAM (DDR) because some pixel are ALWAYS delayed.


-The problem decrease when I change the DMA configuration from LCDC_LDCR {HM-TM} = {4-60} to {2-70} But it is not yet perfect.


-The problem stop when I decrease the LCD clock from 30MHz to 20Mhz (probably because the LCDC read slower in DDR). Unfortunately my TFT specification requires a clock between 28 to 32Mhz even if currently the sample that I have accept to work at 20Mhz.


-The problem stop when I make "pause" my debbuger. During this phase, the LCDC controller still running, just the code don't make access to the ram because it is stopped.


Then the problem come from DDR access, which is bad managed between the need of LCDC at 30Mhz and the need of the software which need to read/write in continous manner.

Have you an Idea to resolve my problem?

Labels (1)
0 Kudos
1 Solution
2,982 Views
arnogir
Senior Contributor II

Hello

You can find in attached file the modified driver for the LCD TFT 7" 800x480 65K colors working at 16bpp.

With this drivers, all work correctly now.

Note: this driver control also the LCD PWM output to enable and modify the backlight luminosity.

View solution in original post

0 Kudos
7 Replies
2,982 Views
arnogir
Senior Contributor II

Hello

I change the driver to drive the TFT in 16 bpp. All work fine now. May me K70/PEG can't assume an LCD in 24bpp at 30MHz?

0 Kudos
2,982 Views
LuisCasado
NXP Employee
NXP Employee

Hello,

I think there is not limitation for that as soon as the LCDC can manage it. Memory layout is different, 24bpp use 32bits per pixel in memory and PEG drivers are different. Perhaps the problem is in the DMA copy aligned to 16 or 32 bpp.

Luis

2,983 Views
arnogir
Senior Contributor II

Hello

You can find in attached file the modified driver for the LCD TFT 7" 800x480 65K colors working at 16bpp.

With this drivers, all work correctly now.

Note: this driver control also the LCD PWM output to enable and modify the backlight luminosity.

0 Kudos
2,982 Views
LuisCasado
NXP Employee
NXP Employee

Great!

Thank you for sharing your driver.

Luis

0 Kudos
2,982 Views
arnogir
Senior Contributor II

I join a video and two picture (One with problem, one without problem when debbuger is in pause)

IMG_1523.JPG.jpg

0 Kudos
2,982 Views
LuisCasado
NXP Employee
NXP Employee

Hello,

The LCDC controller fetch the data from framebuffer (DDR) with his own DMA engine and the CPU can write the framebuffer in any time. That wouldn't cause that problem.

You can configure the Screen driver to use Double buffer and DMA can copy one buffer to the other and swap buffers in a synchronous way.

But delay in the pixels, in my opinion, is a wrong LCDC configuration for your display panel.

Best Regards,

Luis

2,982 Views
arnogir
Senior Contributor II

Hello

I configured PEG to use double buffer.

In standalone, the problem occurs ONLY during the following phase (which consist to copy image from flash to the second buffer in RAM not yet used by the LCDC) (Problem during imbricated "for" loop):

void K70_TWRLCDScreen::MemoryToScreen(void)

...

for(Row = Top; Row < (Top + Height); Row++)
    {
       ...
        pGet = (PEGCOLOR *)(pSurface->pScanPointers[0]);
      ...

        pPut = (PEGULONG *)mpVidMemBase;
     

        for(Column = 0; Column < Width ; Column++)
        {
            #if defined (PEG_RGB_USE_565)
            PEGCOLOR Color = *pGet++;
//Debug AG, BIT 0 to 5 Used, not 8 to 2.  
/*            *pPut++ = ((Color & 0xf800) << 8) |
                      ((Color & 0x7e0) << 5)  |
                      ((Color & 0x1f) << 3);*/
            *pPut++ = ((Color & 0xf800) << 6) |   //Rouge
                      ((Color & 0x7e0) << 3)  |   //Vert
                      ((Color & 0x1f) << 1);   //Bleu     
            #else
            PEGCOLOR Color = *pGet++;
            *pPut++ = ((Color & 0x7c00) << 9) |
                      ((Color & 0x3e0) << 6)  |
                      ((Color & 0x1f) << 3);
            #endif
        }
    }

....

    #if defined (PEG_DOUBLE_BUFFER)

    SwapFrameBuffers(Copy);  // !!!!! Here, LCDC address is swap to the buffer copied just above

    #endif

...

void K70_TWRLCDScreen::SwapFrameBuffers(PegRect &Copy)
{
    PEGINT* pPut;
    PEGINT* pGet;
    PEGINT Row;
    PEGINT Top = Copy.Top;
    PEGINT Left = Copy.Left;
    PEGINT Width = Copy.Width();
    PEGINT Height = Copy.Height();

    PEGULONG* pReg;

    pReg = (PEGULONG*) LCDC_LSSAR;
    *pReg =  (PEGULONG) mpVidMemBase;

    if(LCDC_LSSAR == (PEGULONG) mpFrameBufferB)
    {
        pGet = (PEGINT *)mpFrameBufferA;
        pPut = (PEGINT *)mpFrameBufferB;

        LCDC_LSSAR = (PEGULONG) mpFrameBufferA;
    }
    else
    {
        pGet = (PEGINT *)mpFrameBufferB;
        pPut = (PEGINT *)mpFrameBufferA;

        LCDC_LSSAR = (PEGULONG) mpFrameBufferB;
    }

   #if defined(SYNCHRONIZE_DOUBLE_BUFFER)
    WaitForEndOfFrame();
   #endif

    pGet += mHRes * Top;
    pGet += Left;
    pPut += mHRes * Top;
    pPut += Left;

    for(Row = Top; Row < (Top + Height); Row++)
    {
        memcpy(pPut, pGet, Width * 4);
        pGet += mHRes;
        pPut += mHRes;
    }

}
#endif  // PEG_DOUBLE_BUFFER

If this problem comes from a wrong LCDC configuration, why all run correclty when RAM concurent access is not done? Why it run correctly when TFT clock is down to 20Mhz?

My LCDC config:

oid K70_TWRLCDScreen::ConfigureController(void)
{
    /*Enable Port clocks */
    SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK |
    SIM_SCGC5_PORTB_MASK |
    SIM_SCGC5_PORTC_MASK |
    SIM_SCGC5_PORTD_MASK |
    SIM_SCGC5_PORTE_MASK |
    SIM_SCGC5_PORTF_MASK;

    /* Enable LCDC and DDR Modules */
    SIM_SCGC3 |= SIM_SCGC3_LCDC_MASK | SIM_SCGC3_DDR_MASK;


    /* Disable MPU */
    MPU_CESR &= ~MPU_CESR_VLD_MASK;

    /* Setup LCD pin muxing */
    LcdPanelPinsInit();

    /* Basic LCD configuration */

    /* set LCD Screen Start Address (if double buffered, rendering starts in B) */
    LCDC_LSSAR = (PEGUINT)mpVidMemBase;

    /* set LCD Size */
    LCDC_LSR = LCDC_LSR_XMAX( (mHRes / 16) ) | LCDC_LSR_YMAX(mVRes);

    /* set LCD virtual page width */
    LCDC_LVPWR = LCDC_LVPWR_VPW( mHRes);

    /* set LCD cursor positon & settings (turn off) */
    LCDC_LCPR = 0;
    LCDC_LCWHB = 0;

    /* set LCD panel configuration */
    LCDC_LPCR =
    LCDC_LPCR_TFT_MASK      |       /* TFT Screen */
    LCDC_LPCR_COLOR_MASK    |       /* Color */
    LCDC_LPCR_BPIX(0x7)     |       /* bpp */

    LCDC_LPCR_FLMPOL_MASK   |       /* first line marker active low */
    LCDC_LPCR_LPPOL_MASK    |       /* line pulse active low */
    LCDC_LPCR_END_SEL_MASK  |       /* Use big-endian mode (0xFFAA5500 means R=AA,G=55,B=00) */

    LCDC_LPCR_SCLKIDLE_MASK |       /* Enalbe LSCLK when vsync is idle */
    LCDC_LPCR_SCLKSEL_MASK  |       /* Always enable clock */
    //Debug AG LCDC_LPCR_CLKPOL_MASK  |        /* Active on positive edge of LSCLK. In TFT mode, active on negative edge of LSCLK. */

    LCDC_LPCR_PCD(3);             /* Divide 120 PLL clock by (3+1)=4 to get 30MHz clock */


//Debug AG timming on p2232 datasheet
    /* set LCD horizontal configuration based on panel data ( 6.1 Innolux datasheet) */
    LCDC_LHCR =
    LCDC_LHCR_H_WIDTH(63)   |    /* (63+1)=64 SCLK period for HSYNC activated */
    LCDC_LHCR_H_WAIT_1(99)  |    /* (99+1)=100 SCLK period between end of OE and beginning of HSYNC */
    LCDC_LHCR_H_WAIT_2(63);     /* (63+3)=66 SCLK periods between end of HSYNC and beginning of OE */
/* Total of 230 TCLK for Thb. */

    /* set LCD vertical configuration based on panel data (Figure 3-3 in Seiko datasheet) */
    LCDC_LVCR =
    LCDC_LVCR_V_WIDTH(2)  |    /* 2 SCLK period for VSYNC activated */
    LCDC_LVCR_V_WAIT_1(10) |    /* 20 SCLK period between end of OE and beginning of VSYNC */
    LCDC_LVCR_V_WAIT_2(2);    /* 2 SCLK periods between end of VSYNC and beginning of OE */

    /* set LCD panning offset */
    LCDC_LPOR = 0;

    /* set LCD interrupt configuration */
    LCDC_LICR = 0;

    /* set LCD interrupt enable */
    LCDC_LIER = 0;

    /* set LCD graphic window start address */
    LCDC_LGWSAR = 0x80000000;

    /* set LCD graphic window size */
    LCDC_LGWSR =
    LCDC_LGWSR_GWW(0) |
    LCDC_LGWSR_GWH(0);

    /* set LCD graphic window virtual page width */
    LCDC_LGWVPWR = 0;

    /* set LCD graphic window panning offset */
    LCDC_LGWPOR = 0;

    /* set LCD graphic window position */
    LCDC_LGWPR =
    LCDC_LGWPR_GWXP(0) |
    LCDC_LGWPR_GWYP(0);

    /* set LCD graphic window control */
    LCDC_LGWCR =
    LCDC_LGWCR_GWAV(0xF)          | /* alpha-transparent */
    (1 << LCDC_LGWCR_GWCKE_SHIFT) | /* color key enable */
    LCDC_LGWCR_GWCKR(0xFF)        | /* color key */
    LCDC_LGWCR_GWCKG(0)           |
    LCDC_LGWCR_GWCKB(80);

    /*Set background plane DMA to burst mode */
    LCDC_LDCR&=~LCDC_LDCR_BURST_MASK;

    /*Set graphic window DMA to burst mode */
    LCDC_LGWDCR&=~LCDC_LGWDCR_GWBT_MASK;

/* Set PWM backlight */
LCDC_LPCCR = LCDC_LPCCR_PW(128)    |    /* Set PWM duty to 50% */
              LCDC_LPCCR_CC_EN_MASK ;    /* Enable contrast control */
    
    /* Change PTD12 to outputs and set to 1(Enable Backlight)*/
    GPIOD_PDDR |= GPIO_PIN(12); 
    GPIOD_PSOR = GPIO_PSOR_PTSO(GPIO_PIN(12));

    /* Enable LCD */
    SIM_MCR|=SIM_MCR_LCDSTART_MASK;
    return;

0 Kudos