Skip to main content
ALomb
Senior
April 8, 2020
Question

2.8'' ILI9341 SPI LCD and XPT2046 Touch Controller

  • April 8, 2020
  • 10 replies
  • 6689 views

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?

This topic has been closed for replies.

10 replies

ALomb
ALombAuthor
Senior
April 8, 2020

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
Principal III
April 8, 2020

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
Principal III
April 8, 2020

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
ALombAuthor
Senior
April 9, 2020

@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
ALombAuthor
Senior
April 9, 2020

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
Principal III
April 9, 2020

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
ALombAuthor
Senior
April 10, 2020

@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?

PKriv.1
Associate II
October 10, 2020

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

@Martin KJELDSEN​ could you please address this issue? I have the same problem, the flushFrameBuffer is not called if the lockDMAToFrontPorch(true); is called in initializaiton. Only when it's set to false, I do get an image, like the @Community member​ .

Martin KJELDSEN
Principal III
October 12, 2020

Refresh me on your setup. When you "lockDMAToFrontPorch(true)" you're basically telling the DMA2D to wait until the front porch has been reached. But front porch does not make sense in an scenario where your display has GRAM.

lockDMAToFrontPorch() is used with something like a TFT controller where you can get a line interrupt when the front porch is hit.

Javier_Leyva08
Associate
June 24, 2020

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
June 24, 2020

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 ?

PKriv.1
Associate II
October 8, 2020

Hello @Community member​ , nice work you've done! I've studied your project long and wide, and tried to implement it on my custom board.

Since I want to learn, I decided to use your example and go with your libraries.

I am using an STM32F411RE, that has significantly less RAM - 128KB and is not able to carry a full framebuffer. For that reason, I decided to make my screen only half the size, that is 160x240 framebuffer. I only needed to modify GUI_WIDTH to 160 in ili9341.h I made the sample in the TouchGFX Designer, it worked just fine, and the program builds.

However, the image I get is for some reasone offset, and the items on it (a simple circle button) is duplicated. Do you see a reason why that might happen? I.e. is there something in your code that might not work with modified screen resolution?

Best regards,

Pero