cancel
Showing results for 
Search instead for 
Did you mean: 

2.8'' ILI9341 SPI LCD and XPT2046 Touch Controller

ALomb
Senior

I'm trying to integrate the display in question with TGX 4.13. This is the LCD module.

I developed the drivers for both display and touch, configured the project and trying to follow what is reported in the documentation at this link (spi scenarios for ST7789H2).

I have an error during compilation which is as follows:

../TouchGFX/target/TouchGFXHAL.cpp:91:8: error: 'class TouchGFXHAL' has no member named 'copyFrameBufferBlockToLCD'; did you mean 'setFrameBufferAllocator'?

How to solve?

25 REPLIES 25
ALomb
Senior

By reading better the documentation I understood that the function copyFrameBufferBlockToLCD must be implemented and added to the TouchGFXHAL class!

@Martin KJELDSEN​  I found this project on gitHub which uses same LCD module of this question.

Would it be possible for you to review it so that it can be used as a template for TouchGFX with SPI interface ?

Otherwise could you provide a complete project that uses the SPI interface?

Martin KJELDSEN
Chief III

Yes, the TouchGFX HAL driver requests that you implement your display specific driver (SPI) partly in copyFrameBufferBlockToLCD() -

You really don't have to worry about TouchGFX specifics here. Is there anything you're worried about concretely? Check this scenario where i described how to implement a driver to work with TouchGFX HAL - The link covers both FMC and SPI. Is this what you've read? It should outline the steps usually involved in sending pixels to a spi display (set command mode, set cursor based on pos in framebuffer, set data mode, send pixels)

https://support.touchgfx.com/docs/development/touchgfx-hal-development/scenarios/scenarios-fmc

Martin KJELDSEN
Chief III

Let me just post the code i put in the article for ST7789H2 . Also, this makes me realize that copyFrameBufferBlockToLCD() is a private function, not required by the compiler.

void  TouchGFXHAL::flushFrameBuffer(const Rect& rect)
{
    /* Set Cursor */
    __ST7789H2_SetDisplayWindow(rect.x, rect.y, rect.width, rect.height);
 
    /* Prepare to write to LCD RAM */
    ST7789H2_WriteReg(ST7789H2_WRITE_RAM, (uint8_t*)NULL, 0);
 
    /* Send Pixels */
    this->copyFrameBufferBlockToLCD(rect);
}

Function to set the virtual cursor in GRAM:

extern "C"
void __ST7789H2_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
    uint8_t   parameter[4];
 
    /* CASET: Column Addrses Set */
    parameter[0] = 0x00;
    parameter[1] = Xpos;
    parameter[2] = 0x00;
    parameter[3] = Xpos + Width - 1;
    ST7789H2_WriteReg(ST7789H2_CASET, parameter, 4);
 
    /* RASET: Row Addrses Set */
    parameter[0] = 0x00;
    parameter[1] = Ypos;
    parameter[2] = 0x00;
    parameter[3] = Ypos + Height - 1;
    ST7789H2_WriteReg(ST7789H2_RASET, parameter, 4);
}

Does the actual copying - You could also use DMA to transfer:

void TouchGFXHAL::copyFrameBufferBlockToLCD(const Rect rect)
{
    __IO uint16_t* ptr;
    uint32_t height;
 
    // This can be accelerated using regular DMA hardware
    for (height = 0; height < rect.height ; height++)
    {
        ptr = getClientFrameBuffer() + rect.x + (height + rect.y)  * BSP_LCD_GetXSize();
        LCD_IO_WriteMultipleData((uint16_t*)ptr, rect.width);
    }
}

ALomb
Senior

@Martin KJELDSEN​ ,

I integrate driver and modify (on GitHub if you want to take a look)

and made the changes as you indicated.

The problem I have now is that function TouchGFXHAL::flushFrameBuffer is never called!

Something else is missing ?

ALomb
Senior

Hi @Martin KJELDSEN​ ,

I made some progress: on the display I see the screen created with the TouchGFX Designer !

I created a timer to call the signalVSync()

I have set lockDMAToFrontPorch(false); in TouchGFXGeneratedHAL :: initialize () (why ?)

I push changes on GitHub.

Now the next step is to use SPI transfer with DMA. Any suggestions ?

Martin KJELDSEN
Chief III

Awesome!

Are you able to get a sync signal from the display? The timer might not be fully aligned with the display and you may see tearing if the application is complex.

>> I have set lockDMAToFrontPorch(false); in TouchGFXGeneratedHAL :: initialize () (why ?)

I don't know. What's your reason for doing that? :) Generally, though, lock to front porch means that DMA2D won't process blitops until the LTDC is not accessing the framebuffer anymore - it's a way to ease the strain on RAM and avoid congestion issues.

Here's some pseudo code of flushFrameBuffer with DMA transfers. Notice how you need to introduce an additional semaphore here because flushFrameBuffer() should not return before the transfer is complete.

void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
    uint16_t* fb = HAL::lockFrameBuffer();
 
    //Prepare display
    prepare();
 
    //Try to take a display semaphore - Always free at this point
    xSemaphoreTake(screen_frame_buffer_sem, portMAX_DELAY);
 
    //Set up DMA and transfer
    screenDMAEnable();
 
    // Wait for the DMA transfer to complete
    xSemaphoreTake(screen_frame_buffer_sem, portMAX_DELAY);
 
    //Unlock framebuffer and give semaphore back
    HAL::unlockFrameBuffer();
    xSemaphoreGive(screen_frame_buffer_sem);
}

ALomb
Senior

@Martin KJELDSEN​ ,

I have successfully introduced DMA on SPI transfers (video - update code on GitHub).

Transactions are currently row by row. Do you think it is better to transfer the entire buffer in one transaction?

>>I don't know. What's your reason for doing that? 

if I don't, the flushFrameBuffer is never called!

>>Are you able to get a sync signal from the display?

Unfortunately not. How to properly choose the timer frequency ?

And with this I conclude :grinning_face_with_sweat: : would be possible to use DMA2D in my scenario?

Javier_Leyva08
Associate II

hi everyone, according whit the project of @Community member​ that is this ---> https://github.com/ndunello/TouchGFX-SPI_Demo based on [strategy by allocation] and this another one ---> https: //github.com/kotetsuy/TouchGFXDemo/tree/master/GUITestNoOS based on [strategy by partial buffer] i have experimented a bug, that is regarding analog clock animation issue, it turn out the project base on [strategy by allocation] has error when i try to annimated my analog clock, but in the other hand project based on [strategy by partial buffer] the animation runs fine .. !! my doubt is, according to this post https://support.touchgfx.com/docs/development/touchgfx-hal-development/scenarios/scenarios-fmc/ @Martin KJELDSEN​  exists more codes or steps to add to my project?

Javier_Leyva08
Associate II

in first glance i thought that was error by using DMA and issues about synchronization with buffer memory and touchgfx engine, but i have changed without DMA and doesn't work around issue. any idea about this ?