Skip to content

TinyPi #37

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
moosepr opened this issue Sep 28, 2018 · 13 comments
Closed

TinyPi #37

moosepr opened this issue Sep 28, 2018 · 13 comments

Comments

@moosepr
Copy link

moosepr commented Sep 28, 2018

Howdy @juj

I thought i would give your code a bit of the old college try on my TinyPi Pro board. It is using a ST7789 screen which looks much like the one on the 1.3" waveshare board (actual screen is here https://www.aliexpress.com/item/1-3-inch-white-light-full-view-SPI-OLED-LCD-SSD1306-drive-IC-128-64-not/1609778123.html) mounted on a custom board, and i have been using the notro flexfb driver with great success, using the following modprobe lines
modprobe fbtft_device name=flexfb speed=32000000 gpios=reset:25,dc:24 modprobe flexfb width=240 height=240 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3

I have spent the best part of a day trying to get your code to work, and im sure i must be doing something silly, but im struggling to put my finger on it. At first i though it was down to the fact that i had some old fbtft settings lying about somewhere, so i have got a fresh copy of retropie today, and installed nothing but your code to make sure there are no conflicts, and im still struggling.

I would like to think i know what im doing in this area, but alas no screen yet!!

My cmake code is as follows
cmake -DST7789VW=ON -DGPIO_TFT_DATA_CONTROL=24 -DGPIO_TFT_RESET_PIN=25 -DSPI_BUS_CLOCK_DIVISOR=10 -DUSE_DMA_TRANSFERS=OFF ..

have tried various combinations of divisor and dma and such to no avail. even adding pi zero specific options to see if that helps!!

Any chance you could cast an eye over my config, see if you can spot anything obvious?

Many thanks

Pete

@moosepr
Copy link
Author

moosepr commented Sep 28, 2018

actually, hang fire!! I might have a technical issue with my casing!! just tried my standard retropie image from before I started tweaking code, and i have to hold it a set way for the screen to work!!!

@moosepr
Copy link
Author

moosepr commented Sep 29, 2018

Ok so it was hardware, but I do have one request. The dst7789vw driver is designed for the wave share board, so the screen is 90 degrees out from 'standard' usage with the chip at the bottom. Is there any way to fix that without having to resort to rotating the entire os in the /boot/config ?

@juj
Copy link
Owner

juj commented Oct 1, 2018

Great to hear TinyPi is going well!

To rotate the image, there are a couple of options. One is to adjust the display from landscape to portrait:

diff --git a/config.h b/config.h
index ced2b29..f82fb3e 100644
--- a/config.h
+++ b/config.h
@@ -159,7 +159,7 @@

 // If defined, displays in landscape. Undefine to display in portrait. When changing this, swap
 // values of DISPLAY_WIDTH and DISPLAY_HEIGHT accordingly
-#define DISPLAY_OUTPUT_LANDSCAPE
+// #define DISPLAY_OUTPUT_LANDSCAPE

This should produce a 90 degrees flip in one direction. If it flips to the wrong side and is upside down, you can also pass -DDISPLAY_ROTATE_180_DEGREES=1 CMake config variable to make the rotation go the other way around.

That being said, I don't recall if I ever tested these flags with ST7789, but they should be hooked up to control orientation on that display as well. If that does not work, you can also directly adjust the madctl register in st7735r.cpp that governs st7789 support:

fbcp-ili9341/st7735r.cpp

Lines 42 to 69 in df4d5db

#define MADCTL_BGR_PIXEL_ORDER (1<<3)
#define MADCTL_ROW_COLUMN_EXCHANGE (1<<5)
#define MADCTL_COLUMN_ADDRESS_ORDER_SWAP (1<<6)
#define MADCTL_ROW_ADDRESS_ORDER_SWAP (1<<7)
#define MADCTL_ROTATE_180_DEGREES (MADCTL_COLUMN_ADDRESS_ORDER_SWAP | MADCTL_ROW_ADDRESS_ORDER_SWAP)
uint8_t madctl = 0;
#if defined(ST7735R) || defined(ST7735S)
madctl |= MADCTL_BGR_PIXEL_ORDER;
#endif
#ifdef DISPLAY_SWAP_BGR
madctl ^= MADCTL_BGR_PIXEL_ORDER;
#endif
#if defined(DISPLAY_FLIP_ORIENTATION_IN_HARDWARE)
madctl |= MADCTL_ROW_COLUMN_EXCHANGE;
#endif
madctl |= MADCTL_ROW_ADDRESS_ORDER_SWAP;
#if defined(WAVESHARE_ST7789VW_HAT) || defined(WAVESHARE_ST7735S_HAT)
madctl ^= MADCTL_ROTATE_180_DEGREES;
#endif
#ifdef DISPLAY_ROTATE_180_DEGREES
madctl ^= MADCTL_ROTATE_180_DEGREES;
#endif
SPI_TRANSFER(0x36/*MADCTL: Memory Access Control*/, madctl);

where adding a line like

madctl ^= MADCTL_ROW_COLUMN_EXCHANGE | MADCTL_ROW_ADDRESS_ORDER_SWAP;

or

madctl ^= MADCTL_ROW_COLUMN_EXCHANGE | MADCTL_COLUMN_ADDRESS_ORDER_SWAP;

just before line

SPI_TRANSFER(0x36/*MADCTL: Memory Access Control*/, madctl);
should do the trick.

@moosepr
Copy link
Author

moosepr commented Oct 1, 2018

Awesomesauce!!! Thanks for getting back to me, i will try this and let you know :)

@juj
Copy link
Owner

juj commented Oct 1, 2018

A curious note if you like to be picky/golden hi-fi eyes about vsync tearing, then running with madctl register set to 0 on each of the three orientation bits is the configuration that produces least visual tearing, since in that mode, the panel pixel refresh scan order should match with the memory read order, i.e.

madctl &= ~(MADCTL_ROW_COLUMN_EXCHANGE | MADCTL_COLUMN_ADDRESS_ORDER_SWAP | MADCTL_ROW_ADDRESS_ORDER_SWAP);

to kill the all of the three bits from being set, before line 69 that sets madctl. That should show the "native direction" of the panel, in case if you have custom control over which way to install it into your enclosure.

If you prefer the diagonal tearing artifact over straight line tearing, that occurs when running with MADCTL_ROW_COLUMN_EXCHANGE bit enabled.

(Having either MADCTL_COLUMN_ADDRESS_ORDER_SWAP or MADCTL_ROW_ADDRESS_ORDER_SWAP bits enabled could be argued to cause added micro-level latency, which is why theoretically ideal way to run is with both disabled)

@moosepr
Copy link
Author

moosepr commented Oct 1, 2018

that solved my rotation and does seem to reduce the tiny bit of tearing i was seeing before.

I am however getting a little bit of choppy audio which i am assuming is linked to the USE_GPU_VSYNC issue. do i just comment that define out? (please accept cat tax in video as payment in advance for help :P )

https://youtu.be/ldJvhJn6S4I

@juj
Copy link
Owner

juj commented Oct 1, 2018

The audio choppiness is caused by fbcp-ili9341 consuming too much CPU, and there is not enough time for other programs, such as the audio driver, to operate. This is unfortunate on the single core boards, it needs to be quite careful about performance. Check out the section https://github.com/juj/fbcp-ili9341#tuning-cpu-usage about improving performance.

In particular, for Pi Zero:

  • ensure fbcp-ili9341 is being built with #define ALL_TASKS_SHOULD_DMA enabled,
  • make sure -DUSE_DMA_TRANSFERS=ON is set,
  • disable statistics with -DSTATISTICS=0,
  • enable #define USE_GPU_VSYNC, (unfortunately because of Event notification based version of vc_dispmanx_snapshot? raspberrypi/userland#440 this will cause visual stuttering that one can't avoid, but Pi Zero cannot afford to dedicate a core to hand-hold the GPU either, like Pi 3B can),
  • make sure #define DISPLAY_FLIP_ORIENTATION_IN_SOFTWARE is not enabled,
  • enable #define UPDATE_FRAMES_IN_SINGLE_RECTANGULAR_DIFF,
  • or even enable #define UPDATE_FRAMES_WITHOUT_DIFFING (this is a bit last resort, but works really well if your display can handle a really high SPI bus speed, ~73MHz or better),
  • lower display resolution in /boot/config.txt to exact size only needed for target applications, e.g. 320x240 (as opposed to default 1024x768 or something similar), disconnect HDMI,
  • disable bluetooth and/or wifi,
  • make sure SNES display size in Retroarch is set to pixel perfect instead of stretching aspect ratio. This can be configured for SNES similar to how NES instructions are in https://github.com/juj/fbcp-ili9341/blob/master/gpu.cpp#L365, (avoiding stretching was observed to help pixel processing CPU overhead by ~7-10%),
  • run with a different SNES emulator (I remember playing around with the different variants that Retropie/Emulationstation comes with, and one stood out as fastest of the bunch, but don't quite recall which),
  • if nothing else works, lower frame rate to e.g. 30fps, with #define TARGET_FRAME_RATE 30. This will make the system breathe considerably more

@juj
Copy link
Owner

juj commented Oct 1, 2018

When toying around with NES and SNES emulators, I do recall NES emulators were orders of magnitude lighter to run, compared to SNES. So it may worth sanity checking that NES emulators run with good performance first, to establish a baseline. SNES performance was quite on the edge for Pi Zero if targeting 60fps. Fbcp-ili9341 consumes around ~14-17% of CPU time on Pi Zero when playing fast-paced SNES games if I remember correctly - that was too much for some SNES emulators to not be able to keep up. Another measure may be to lower fbcp-ili9341 process priority by editing

params.sched_priority = sched_get_priority_max(SCHED_FIFO);

and change SCHED_FIFO to SCHED_IDLE, and then uncomment the line

// #define RUN_WITH_REALTIME_THREAD_PRIORITY

in config.h to enable the option. (haven't tried it myself, but this might help establish a priority below the emulator)

@moosepr
Copy link
Author

moosepr commented Oct 4, 2018

I tried setting the priority on line 60, and now I'm getting this error

pi@retropie:~/fbcp-ili9341/build $ sudo ./fbcp-ili9341 pthread_setschedparam() failed!

Do I need to change every instance of FIFO to IDLE?

@moosepr
Copy link
Author

moosepr commented Oct 4, 2018

Ok so I answered my own question after reading the code again. I don't think setting the lower priority is the way to go, it ends up like 2 FPS, and still choppy on the audio

https://youtu.be/6D89IHOmtDU

@juj
Copy link
Owner

juj commented Oct 22, 2018

Hmm, looking at the video, it seems that perhaps the priority did still end up being elevated, instead of lowered. Not quite sure.

There are also some programs like nice on Linux that can control process priorities, though have not tested if they work on a Pi.

It may be the case that for the more demanding applications, lowering TARGET_FRAME_RATE from 60 down to e.g. 40 or 30 is the safest option to go to keep the system from starving. Another option could be to try to introduce sleep(1000); or similar blocks inside the main loop in

while(programRunning)
{
prevFrameWasInterlacedUpdate = interlacedUpdate;

(although that may be inferior in performance to adjusting TARGET_FRAME_RATE)

@moosepr
Copy link
Author

moosepr commented Oct 23, 2018

I have dropped the TARGET_FRAME_RATE down to 30, and put the priority back as it was. Im now using the driver on retropie with no issues, i think the issues i was having before was actually more of a lakka issue than your driver, as it works with the same game on retropie great!!

I think its working fine now. Such a great little driver too!! will make deploying versions of the OS nice and easy :)

@juj
Copy link
Owner

juj commented Oct 23, 2018

Great! I'll close this as resolved. Perhaps lakka distribution has some background process that it needs that takes up a bit more of CPU, or a different build or emulator it uses on games. top or htop over SSH on command line might be able to show up if something else is hogging CPU. Recently I had a case where a GPIO keyboard driver was taking up ~20% of CPU for no reason, and removing that speeded things up considerably.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants