Showing results for 
Search instead for 
Did you mean: 

Changing from LCD16bpp to LCD8bpp

Associate II

Hello, I am facing an issue where the rendered frame buffer is printed on the display as gibberish pixels.

I'm using the Nucleo F746ZG and interfacing it (over SPI) with an external display controller that writes to a 240*320 display. I was not able to locate the exact color depth of the display in the datasheet, but the information suggests that each pixel has 2ddot. Given RGB, I assumed 6bpp is the correct format.

Initially I set up touch gfx to render a 16bpp frame buffer. With the 16bpp rendering I used the following code segment to send the rendered gibberish buffer to my display controller and get some random pixels printed.

In TouchGFXGeneratedHAL.cpp:

void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
    uint32_t ibaseaddr = (uint32_t)getClientFrameBuffer();
    uint16_t istride = lcd().framebufferStride();
    uint16_t HParam = 1;
    uint16_t WParam = 1;
    uint16_t HScale = 100*HParam;
    uint16_t WScale = 100*WParam;
    uint16_t rot = 128;//<< rotates 90 degrees
    // send frame buffer to display
    ImgCpyRotScale( 120, //Destination Window center X coordinate.
                    160, //Destination Window center Y coordinate.
                    ibaseaddr, //Source Window base address.
                    istride, //Source Window stride.
                    rect.width-1, //Source Window width.
                    rect.height-1, //Source Window height.
                    120, //Source Window center of transformation X coordinate.
                    160, //Source Window center of transformation Y coordinate
                    0xC0, rot, //Fill color (if FILL is enabled) | Rotation value
                    HScale, HScale, //left scale % | right scale %
                    WScale, WScale, &cpyctrl); // top scale % | bottom scale %
    PanelUpdate(0, 320-1);


I have tested the display controller SPI command and its arguments, it works as expected. But I believe the 16bpp frame buffer does not render the correct display buffer. To fix this I made the necessary changes in CubeMX and ported over the changes manually. The main change was inside TouchGFXConfiguration.cpp.

The display object changed from:

static LCD16bpp display;


static LCD8bpp_RGBA2222 display;


This causes a problem where during touch gfx initialization, hal.initialize() fails 4 instructions after returning from touchgfx GPIO init.


Since the source code for HAL initialize is inside the compiled library, I am not able to debug why zero (0x0) is copied to the r3 register through this instruction.

ldr   r3,[r3,#12] // copies zero to r3

r3 Memory address at the time of ldr instruction:


resulting in a hard fault when branching the r3 register

blx   r3



Ok, but what's the fault and registers

What call back is at 0x08014FF2 ?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Chief II

Your showed info is irelevant. Show display ID or controller ID.

Associate II

@Tesla DeLorean  This operation results in a hard fault, because r3 will get populated with the address 0x0 and:

blx   r3

is an invalid instruction @ 0x0 .

To answer your second question, the disassembly returns the following for 0x08014FF2:


I tried manually modifying the assembly instruction results:

=> 0x0800a10e <+16>:    ldr     r3, [r3, #12]

Above instruction, returned 0x0 to r3. Instead, I copied the value I expected r3 to be populated with (found it by looking at the memory):



After manually populating that address to r3 and stepping once it resolved to this function:

"touchgfx LCD16bpp TextureMapper RGB565 NonOpaque Bilinear Interpolation NoGAD"


I'm not sure if that's the correct function that needs to be called. I wonder if there are further manual changes needed to have touch gfx use the correct function calls to render for 8bpp.

I wouldn't say it is entirely irrelevant, I covered all the points I thought are useful for debugging touch gfx.

This page has specs for the display I'm using. I haven't had much luck with datasheets for this product.

I experimented with the display controller before and was able to print bitmap images, that were located in the F7 internal flash, to the display. I'm using similar functionality by pointing to the frame buffer address instead of bitmap images. In an ideal world, the correct frame buffer would be rendered through touch gfx, and I can just get the address and pass it to the display controller. My suspicion is that some configuration settings for touch gfx is causing it to render the frame buffer incorrectly.

I spent a good amount of time researching the color depth I need for this display. The display size is 240*320 pixels. Seems like each rgb pixel has a set of MSB and LSB bits, for each color. The MSB Pixel block occupies 2/3 of the sub pixels of each pixel. And LSB occupies 1/3. Each pixle has 9 (3x3) sub pixels, and the colors are divided by columns. The top and bottom row of pixels are regarded as MSB, and middle row is LSB. Like this:


Is LCD8bpp_RGBA2222 the correct selection for my use case? What are your thoughts on this?

I mean no maybe. LCD8 is palete format in buffer stored index and to display send RBG888 value. But your func can convert this. For this i ask LCD info, because more flexible is use hw based management as sw rotations usw.

My display part number is LS035Q7DD01. My display controller is not sophisticated enough to perform the conversions (I wish it was). It doesn't make a difference for me to perform software transformation or use hardware, whichever works I'll be happy. Are you suggesting I render the RG565 frame buffer and transform it to RGBA2222 after it is rendered? I was under the assumption that touch gfx can accomplish this for me.

I mean your display have own memory , then best is switch TouchGFX to partial buffer mode and write own func instead 


but you can leave full single buffer mode when flush is quick . Format choiced L8 based on mode for bits ARGB RGBA ... before send to display require convert optimaly line by line to display format.