cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 : DMA2D and Blending operation (font display)

Viony
Associate II
Posted on October 13, 2017 at 14:54

Hi everyone !

I am struggling with DMA2D configuration (using HAL library) to display anti-aliased fonts. The fonts I have are A4 coded. Every character has its own array. For example, for the exclamation mark :

uint8_t ExclamationMark[57] = {

  0x00, 0x00, 0x00,

  0x00, 0x00, 0x00,

  0x00, 0x00, 0x00,

  0x05, 0xF7, 0x00,

  0x05, 0xF7, 0x00,

  0x05, 0xF7, 0x00,

  0x05, 0xF7, 0x00,

  0x05, 0xF7, 0x00,

  0x03, 0xE5, 0x00,

  0x03, 0xE5, 0x00,

  0x02, 0xC3, 0x00,

  0x02, 0xC3, 0x00,

  0x02, 0xC3, 0x00,

  0x00, 0x00, 0x00,

  0x05, 0xF7, 0x00,

  0x00, 0x00, 0x00,

  0x00, 0x00, 0x00,

  0x00, 0x00, 0x00,

  0x00, 0x00, 0x00

};

Since it is A4 formatted, every byte in this array allows to draw 2 pixels. Thus, the exclamation mark occupies 6x19 pixels.

Here is what I have done so far using the HAL library (simplified) :

HAL_StatusTypeDef DrawEM(uint16_t x, uint16_t y){

    uint8_t ExclamationMark[57] = {

      0x00, 0x00, 0x00,

      0x00, 0x00, 0x00,

      0x00, 0x00, 0x00,

      0x05, 0xF7, 0x00,

      0x05, 0xF7, 0x00,

      0x05, 0xF7, 0x00,

      0x05, 0xF7, 0x00,

      0x05, 0xF7, 0x00,

      0x03, 0xE5, 0x00,

      0x03, 0xE5, 0x00,

      0x02, 0xC3, 0x00,

      0x02, 0xC3, 0x00,

      0x02, 0xC3, 0x00,

      0x00, 0x00, 0x00,

      0x05, 0xF7, 0x00,

      0x00, 0x00, 0x00,

      0x00, 0x00, 0x00,

      0x00, 0x00, 0x00,

      0x00, 0x00, 0x00

    };

    DMA2D_HandleTypeDef charDMA2D;

    uint32_t destination =  ((uint32_t)backBuffer + (4*(y*LCD_X_SIZE + x)));

    charDMA2D.Instance = DMA2D;

    charDMA2D.Init.Mode = DMA2D_M2M_BLEND;

    charDMA2D.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;

    charDMA2D.Init.OutputOffset =  800 - 6;

    charDMA2D.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;

    charDMA2D.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;

    charDMA2D.LayerCfg[0].InputAlpha = 0;

    charDMA2D.LayerCfg[0].InputOffset = 0;

    charDMA2D.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;

    charDMA2D.LayerCfg[1].InputColorMode = DMA2D_INPUT_A4;

    charDMA2D.LayerCfg[1].InputAlpha = 0;

    charDMA2D.LayerCfg[1].InputOffset = 0;

    HAL_DMA2D_Init(&charDMA2D);

    HAL_DMA2D_ConfigLayer(&charDMA2D, 0);

    HAL_DMA2D_ConfigLayer(&charDMA2D, 1);

    HAL_DMA2D_BlendingStart(&charDMA2D, (uint32_t)EclamationMark, (uint32_t)0xFF000000, destination, 6, 19);

    HAL_DMA2D_PollForTransfer(&charDMA2D, 1000);

}

Of course, it doesn't work. And I know that it doesn't work because there are too many parameters I don't quite understand. To set some parameters, I used adn read some notes and presentations made by ST for the DMA2D. Yet, when it comes to blending, I am just lost.

So, since every character I have is A4 formatted, it means that every 4-bit describes a pixel of the character by its Alpha value. Correct ? This is my FG layer.

My BG layer is supposed to be a fixed color (black for instance).

Thus, the blending between those two layers is supposed to display an anti-aliased character (in relation with the fixed color used). In one of those presentation made by ST, there was this picture :

0690X00000608bOQAQ.png

So I don't know why, but I can't achieve this result (adapted to A4). Where am I supposed to set this ''color register'' ?

Is anyone can help me out and guide me through this darkness ? I have tried to study the STCube blending example but it doesn't seem to work with my STM32F469-DISCOVERY.

Thanks !

EDIT : Ok so I managed to make it work, barely work. Here are my new parameters for both layers :

    charDMA2D.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;

    charDMA2D.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;

    charDMA2D.LayerCfg[0].InputAlpha = 0x00;

    charDMA2D.LayerCfg[0].InputOffset = 0;

    charDMA2D.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;

    charDMA2D.LayerCfg[1].InputColorMode = DMA2D_INPUT_A4;

    charDMA2D.LayerCfg[1].InputAlpha = 0x00; // Set the color register

    charDMA2D.LayerCfg[1].InputOffset = 0;

Plus the fact that I didn't understand back then that it was necessary to have a kind of ''background buffer'' that contains pixel to blend with the FG layer.

Anyway, even if it barely works, I have the feeling that it doesn't work completely. Here is why :

I draw the ''1'' number on my display (100px height). Here is what I am supposed to get :

0690X00000608V2QAI.png

And here is what I get (do not focus on the red color) :

0690X00000608bsQAA.png

Sorry for the quality of the picture. As you can see (not easy I know), it is... strange when it comes to draw the border of the character. For example, at the beginning of it (left, beginning of the ''1'' curve), there is on my screen one vertical black line (1px), then one white (1px) and black gain. Even on the right of the character, even if we can't see there easily, there is :

- All black on the vertical path ;

- A vertical white line (1px) ;

- A kind of grey vertical line (1px) ;

Do you have a solution ? This result is from the blending operation, which is not possible to see for the user. But I don't understand why I have white pixel where I am supposed to have black ones (or black ones where I am supposed to have white ones).

EDIT 2 : Sooo, after some thinking I figure it out why my characters are not quite drawn as I expected. The issue seems to be the way the DMA2D peripheral fetches data. As I explained before, my characters are A4 formatted. For example to draw two pixels (side by side on the same line) in A4 format I need one byte. Let's say 0x0F : 0 is the alpha channel of the first pixel. F the alpha channel of the second pixel. At least that's what I thought. Actually, when the DMA2D fetches data in memory, it associates F to the first pixel and 0 to the second pixel. This way, there is an inversion. Every two vertical lines are inverted. The result if this inversion is the picture above. I tried manually on a character to ''reverse'' every 4-bit in a byte and my character was as I expected.

So my new question is : is there any way to change the way DMA2D fetch A4 formatted data ?

Here is what the Reference Manual indicates :

0690X00000608YpQAI.png

What I want to achieve is :

Format@ + 3@ + 2@ + 1@ + 0

A4A6[3:0]A7[3:0]A4[3:0]A5[3:0]A2[3:0]A3[3:0]A0[3:0]A1[3:0]

Is this possible ? Or should I wrote some kind of script of my own to ''rewrite'' every file character ?

Thanks again !

#dma2d #stm32f4
2 REPLIES 2
AVI-crak
Senior
Posted on October 14, 2017 at 02:34

The color for A4 mode is assigned in the DMA2D->FGCOLR + DMA2D-> BGCOLR register.

The brightness control in A4 mode is one bit. The bit is set to 1 - the color of the register DMA2D-> FGCOLR, the bit is zero - the color of the register DMA2D-> BGCOLR. Transparency management one bit alpha A4, + 1 bit color A4 = 4 gradations. Separately for each color. The total alpha for the top layer DMA2D-> BGPFCCR (multiplication or addition) affects all the upper layer registers, the letter can be made semi-transparent with the original four gradation levels preserved.

The use of multiple variables often gives a glare or complete darkness. You can use the documentation, you can achieve the result by experience.

But the main thing, the separate influence of the alpha channel on each color - imposes a restriction on the order of building the physical color points on the screen. The screens with the reverse color construction (BGR) will have a distorted image. This will happen when the screen is flipped, regardless of the software correction.

And yet - how did you manage to create data in A4 format? All that I met - he does not know how.

Posted on October 14, 2017 at 15:04

Thank you for your answer. I managed to make it work. It is almost perfect but not completely yet. I have edited my post (see EDIT 2, it explains the issue I am facing with now with the way DMA2D fetches data).

And yet - how did you manage to create data in A4 format? All that I met - he does not know how.

I simply used the font converter application provided with the CubeF4 package.