tuupola / hagl_pico_mipi

Raspberry Pi Pico MIPI DCS absraction layer for the HAGL graphics library
MIT License
43 stars 13 forks source link

add screen rotation? #55

Open SebKuzminsky opened 9 months ago

SebKuzminsky commented 9 months ago

I just found this library and I'm very impressed with the design and the code quality!

I've been using a different (simpler) driver library to talk to little LCD screens from the Pico, and one feature i miss when switching to HAGL is screen rotation, e.g.:

https://github.com/gavinlyonsrepo/ST7735_TFT_PICO/blob/main/src/st7735/ST7735_TFT.cpp#L455-L509

I'm wondering if you are interested in a PR to add this feature to hagl, or maybe just to hagl_pico_mipi, I confess I don't know the best place to implement this.

tuupola commented 9 months ago

Thanks! It is my project to learn C. I started it because I could not find a portable graphics library which could be used between different microchips. I also disliked how people kept writing the same code for every single different display controller.

That said I like to keep the api lean and the code fairly low level. Instead of writing a separate function for each operation, I prefer to use a helper to write to the display controller registers.

The rotation is configured by MIPI_DISPLAY_ADDRESS_MODE. To set the rotation you could do something like:

uint8_t mode = MIPI_DCS_ADDRESS_MODE_SWAP_XY|MIPI_DCS_ADDRESS_MODE_MIRROR_Y;
mipi_display_ioctl(MIPI_DISPLAY_ADDRESS_MODE, &mode, 1)

The mode is a combination of bitfieds. There is a short explanation in the README.

This is mostly a matter of taste. I know some people prefer a function for each operation. I prefer it other way.

SebKuzminsky commented 9 months ago

That did it, thanks :-)

This is the code I ended up using:

mode[0] =  0x00;
mode[1] =  MIPI_DCS_ADDRESS_MODE_SWAP_XY | MIPI_DCS_ADDRESS_MODE_MIRROR_X;
mode[2] =  MIPI_DCS_ADDRESS_MODE_MIRROR_X | MIPI_DCS_ADDRESS_MODE_MIRROR_Y;
mode[3] =  MIPI_DCS_ADDRESS_MODE_SWAP_XY | MIPI_DCS_ADDRESS_MODE_MIRROR_Y;

mipi_display_ioctl(MIPI_DCS_SET_ADDRESS_MODE, &mode[i], 1);
SebKuzminsky commented 8 months ago

Unfortunately the ioctl method you suggested does not completely solve the problem. I think there are three issues that need to be addressed, in addition to changing the addressing mode of the controller:

  1. The clipping window needs to be updated with the new width & height.
  2. X and Y offsets are set at compile-time via the HAGL_PICO_MIPI_DISPLAY_WIDTH and HAGL_PICO_MIPI_DISPLAY_HEIGHT macros, and without changing them the rotated screen is displayed with incorrect offsets.
  3. For double- and triple-buffered modes, the backing bitmap needs to have its width and height changed.

(1) is easy to do right next to the ioctl in "user code", but (2) and (3) need driver support.

I've implemented this in a combination of hagl (to set the clipping window), hagl_pico_mipi (to set the backing bitmap and make the X & Y offsets dynamic), and my application (to call the ioctl "by hand" and then call into hagl to do the other things).

This works for me, but given that there does need to be support in hagl for some of this stuff, it seems better to me to add a function to the hagl API that does all this. If you agree, i'll be happy to come up with a PR to do this.