STM32F746 Discovery portrait mode

Hi,

Description

Do you know how to change the orientation in STM32F746 discovery?
I couldn’t find any config options to change it on driver level. :frowning:

What MCU/Processor/Board and compiler are you using?

STM32F746 Discovery

What do you want to achieve?

Get protrait mode

What have you tried so far?

  • Checked rk043fn48h.h but here only the timing is set.
  • Checked how the LCD is initialized but no display controller is initialized here. (I.e. no place to change the scan direction)

In the past I have done it by flipping the X/Y coordinates in software. Unfortunately I think you lose the ability to use DMA(2D) this way.

Do you mean flipping X/Y coordinates in the flush function?

Yes. I am not sure if DMA2D provides a way to rotate an image on 90-degree increments or not; if so that might be an alternative option.

I’ve searched a lot, but I never found any information whether the STM Chrome-ART Accelerator (DMA2D for short) can handle rotation.
To allow rotation I think the DMA2D would need to allow at least negative offsets, which is not the case.

I have an OpenH7XX board with a 800x480 pixel display, and I do rotation without DMA.

Building rotation into lvgl might be ‘easy’ for simple drawing primitives (like circles, lines, rectangles, dots), but is more effort (?) for rendering the glyphs. As they have to be drawn rotated.

I’ve found that uGFX and STemWin do rotation with DMA2D - I can share some links for you to take a look and confirm if they are actually doing it with DMA or not.

If it is the case, I don’t believe it will be an quick implementation though - but I’ll let you be the judge of that

EDIT:
uGFX post
And someone else’s code which seems to have implemented it as well

Unfortunately both of those drivers appear to be under restrictive licenses.

Totally understand. I had no intention of implying that we should copy their code - feel free to remove the links if it’s against forum rules or general lisence guidelines.

Searching though the DMA2D documentation there is a reference to those registers in section 6.3.1 and 6.3.2

I know that stm32f429 code.
I found it when I did the search about rotation…

He is not doing any rotation in the kind, that you have a pixel area (with the finished drawings) and draw it rotated into the display’s real frame buffer (as far as I can see).

That’s what we do currently. Everything is drawn in one standard orientation. And if we rotatate the display, we have to do the rotation from standard orientation (as lvgl is seeing it) into the display orientation.

He (the stm32f429 project) is drawing primitives with the help of the DMA2D and doing the ‘rotation’ of the x and y (width and height) before he draws, so the resulting frame buffer matches the display orientation.

Not a problem; just wanted to clarify that so no one makes a pull request based off their code. :slightly_smiling_face:

Let’s use STM32F746 as an example. Its natural orientation is landscape 480x272.

In this architecture, it sounds like LVGL would be responsible for drawing/rotating everything into the correct positions for portrait orientation, but arranging everything in memory such that the display controller can be left in landscape mode?

I don’t know about ‘smart’ displays, whether they do the rotation by themselves.

When speaking of ‘dump’ displays (like direct driven with the STM32F4/F7/H7), the display has a fixed orientation. Most of them are in landscape (e.g 800 x 480) and a few (maybe more expensive also) in portrait (480 x 800). If you have a landscape display but you operate it in portrait, you have to rotate any frame paket within the flush_cb (lvgl is of course setup for (480 x 800)).
If lvgl would rotate it while (or just before) drawing, flush_cb would be able to use the DMA2D just for copying the small frame pakets into the real display frame buffer.
In the case that lvgl is doing the rotation internally, we would also be able the use the double frame buffer.

Getting “smart” displays to rotate is not an easy task at all.
The best example is the ILI9341 and even the 9488 I am using. Even after setting the registers the the correct values via SPI, something still doesn’t work properly. I believe the issue is with the RGB interface - HSYNC, VSYNC and DE.
Technically they need to be swapped around but that doesn’t always work. Its all one big mystery.

I think if there was an option to rotate the final image in LVGL before transferring it to the buffer(s) it would make adaptation between display/drivers/app much easier and less time consuming.

Although not exactly what would one hope for, the DMA2D probably could be coaxed into rotating one line.

JW

Just a speculation?

When you want to do a counter clockwise 90 degree rotation.

source frame: this it to be rotated counter clockwise. The numbers are single pixels
................
................
................
................
...12345........
................
................

destination frame
................
..5.............
..4.............
..3.............
..2.............
..1.............
................

You see, within the source frame, the memory addresses are running in positive direction.
The offset is 1 (for 8-bit color).
Whereas for the destination the addresses are running back (negative direction).
So you would need negative offsets.
I did not find any information within the DMA2D whether the offsets can be negative. They would need a sign bit. There is none.
Also you can’t use overflow method, as the offset registers are 16-bit only.
My assumtion is, if they (STM) would have spend a sign bit for the DMA2D offset registers (and of course a signed adding), at least a rotation of a single line would easily be possible.

Yes. I’m not going to test.

The easiest solution is, not to use CCW rotation. Turn the display upside down, and it’s suddenly CW what you need… :slight_smile:

Other solution is to mirror the display. Even the “naked” displays sometimes have controllers which have some means of tweaking them. The display in question here, RK043FN48H, is controlled by OTA5180A, https://www.orientdisplay.com/wp-content/uploads/2018/08/OTA5180A.pdf - see register R0. Again, speculation, I’m not going to try.

But the third option is probably the simplest. You assumed that source frame increments by 1 pixel while the destination increments by the number of pixels in destination row. But you can do it the other way round - increment the source by the number of pixels in source row (i.e. go “vertically” in the source) and increment by 1 in destination (go “horizontally” in destination).

column  
<-----o  scan direction
ABCD  |r
EFGH  |o
IJKL  |w
MNOP  |
QRST  V

destination frame
DHLPT
CGKOS
BFJNR
AEIMQ

e.g. you read AEIMQ from source, and write to the last row in destination.

Again, just speculating.

JW

JW, you are right.

  1. If you can flip the display physically, and you only need it mounted in that way, it will work with positive offsets only. But if hardware is against you, means the connector is only mountable the opposite position, it will not work. Or if you need dynamic rotation as you have it with smart phones etc…
  2. Didn’t know that there are ‘smart’ display controllers for ‘dump’ displays where you can flip the x and y directions. Unfortunately I have an 800 x 480 display for the OpenH7xx board which has no ‘smart’ controller, or at least the display controller can’t be accessed from outside.
  3. This method is working with 90 degrees clockwise (scanning in x direction), and in 90 degrees counter clockwise (scanning in y direction). But it is not working with 180 degree rotation. Or do I miss something?
90 degree CCW   scan in y dir (works with pos. offsets)
................         ................
................         ..5eE...........
................         ..4dD...........
................         ..3cC...........
..12345.........         ..2bB...........
..abcde.........         ..1aA...........
..ABCDE.........         ................
................         ................
................         ................

180 degree
................         ................
................         ................
................         ....EDCBA.......
................         ....edcba.......
..12345.........         ....54321.......
..abcde.........         ................
..ABCDE.........         ................
................         ................
................         ................

270 degree (90 degree CW) scan in x dir (works with pos. offsets)
................         ................
................         ................
................         .........Aa1....
................         .........Bb2....
..12345.........         .........Cc3....
..abcde.........         .........Dd4....
..ABCDE.........         .........Ee5....
................         ................
................         ................

I understand the ramifications of LCD rotation. In the dawn of LCD era, I was involved in getting a monitor working upside down, for horizontal mounting, as the vertical viewing angle’s axis was way upwards (as it is the common case even today, but with much wider total angles than back then). It required some unforeseen tricks to get the custom semigraphics video controller based on the venerable 6845 to get working in that mode; and I also had to modify all the associated software respectively… Fun, but tedious.

The STM32 DMA2D does not allow the 180 degree rotation. Yes, it might’ve been designed more smartly, more flexibly, but that can be said of any peripheral in any microcontroller. I’ve opened a “request”, please vote on it https://community.st.com/s/ideazone#0873W000000PAuxQAG

JW

6845? :bowing_man: Quite old stuff man.
I was thinking about the Amiga custom chips, whether the Blitter was able to do rotation (35 years back)?

@wek Thanks for the question on ST’s forum. Upvoted :slight_smile:

Actually I could leave without DMA2D because it turned out it’s not much faster LVGL’s renderer (altough it can run in the background).

The problem is that I think even LTDC doesn’t support rotation. As you already mentioned swapping row/column is a little bit complicated in the HW too. However, (for the same reasons), it’s complicated to support in LVGL too. :frowning:

Hi, why that?