gfx_demo icon indicating copy to clipboard operation
gfx_demo copied to clipboard

Availability of resource usage information

Open ammaree opened this issue 2 years ago • 13 comments

ammaree avatar Feb 15 '22 07:02 ammaree

We are interested to changing from current library to yours but before starting the process and investing the time to convert, some background and questions. A: We use native ESP-IDF (Master or v4.4) with Eclipse on macOS. B: Our primary dev platform is the Espressif WROVER-DEVKIT 4v1 C: MCU flash, SRAM and MCU overhead is of critical importance to us D: Initially the LCD will primarily be used to display just text info (no graphics) to aid in performance optimisation and debugging E: In the next phase we will add graphics to plot sensor values and touch or button operated menus to navigate. F: We have tested both LVGL and LCDGFX with our current text info code to create a level of benchmark for flash and SRAM usage, and MCU overhead with our basic text display task.

Q1: Do you have any statistics for FLASH and [P]SRAM requirements and MCU overhead, preferably for a minimalist (monochrome text only) and more sophisticated graphics GUI options?

Q2: Based on A: and B: above, can you provide us with very basic example of the most efficient initialisation and updating code, just to display a text buffer of 1000 characters (40h x 25v)

Q3: We notice the existence of 2 repositories being gfx and gfx_demo. It seems gfx_demo is the newer and more actively maintained repo, but largely/completely includes the gfx repo. Also, gfx_demo includes all the supporting files to build as a separate firmware. Which should we clone to have access to the latest GFX code, but purely as a library to link to our firmware?

Q4: certain directories ie "fonts" seem to be duplicated in gfx_forever, is this intended and required?

Much appreciated

André

ammaree avatar Feb 15 '22 08:02 ammaree

Hello, 

I appreciate your interest in this offering of mine. For some background, I originally created it for my own use in my commercial projects, but I wrote it such that I could release it. I never intended it to compete with other offerings so I haven’t compared them except for featurewise. I almost used LVGL which is similar in raw graphics featureset but their truetype support left something to be desired since it was near impossible to build it, and unfortunately only works under the ESP-IDF, not Arduino. 

Q1: I do not have statistics. I’ve never measured it, but I have run GFX on a STM32 machine with 80kB of RAM with no trouble. LVGL however, I’m guessing is more efficient just because they have like 100 contributors to optimize it. =) However, unless your LCD requires an offscreen framebuffer to operate, like many e-paper displays, or certain monochrome devices like the SSD1306 memory use is almost nil for basic drawing. Even the truetype doesn’t use much RAM, and allocates from the heap only during the actual drawing, freeing when done. So the short answer is no. The long answer is, while I haven’t gathered statistics, I designed this to be lean in terms of memory use. Raster Fonts can be embedded into the program binary instead of loaded into RAM, or loaded into RAM, but there’s your primary memory sink. TrueType and JPG loading use memory temporarily during the rendering process. I’ve not measured precisely how much, but it’s modest. 

Q2: Sort of. It will not let you bench 1000 characters at once accurately because the code will not draw off screen, and 1000 characters will not fit on the screen at once. Are you looking for like 10 characters 100 times? The rendering would be a bit different in terms of performance – theoretically it would have more overhead than 1000 characters at once, but like I said, GFX will not draw 1000 characters unless you have a big enough screen to hold them all. Anyway, here’s an example, loading from SPIFFS (which leads to the fastest rendering) and drawing “test!” 200 times for a total of 1000 characters 

https://pastebin.com/aaA3mxJq

I hope this helps! 

Best regards, honey the codewitch  

Edit: I realize support might be a concern. I'm willing to offer support on an hourly basis. Bug fixes notwithstanding which I'd fix anyway, I realize that this is a large offering with a lot of dark corners to it, and in the case that you need help navigating it all for your project, I can sign an NDA and help you orchestrate your project using GFX for a reasonable hourly fee.

codewitch-honey-crisis avatar Feb 15 '22 13:02 codewitch-honey-crisis

Thanks for your quick feedback, appreciated.

With respect to Q2, maybe I wasn't clear. We have the text buffer, 1000 character, to display on the 320x240 ILI9341, so the display can handle all in 1 go. What I was looking for was just the basic functions that will take a pointer to this text buffer and display the text on screen.

Essentially the line below will do it, provided I replace sz with my buffer pointer?

draw::text(lcd,{0,0,lcd.bounds().x2,lcd.bounds().y2},sz,my_font,lcd_color::white,lcd_color::black,false);

To avoid the loading of the font from file would be our preference. Surely the fonts already exist as headers that can be included and selected?

Lastly, any help with Q3? Is the gfx repo as up to date as the gfx_demo repo?

André

ammaree avatar Feb 15 '22 21:02 ammaree

Q3: GFX is a drawing library library. It does not know about display hardware. GFX Demo is GFX (under the /lib folder) plus drivers for ESP-IDF and Arduino. That are both in sync, it's just that GFX is just the standalone drawing library. Unlike most offerings my drawing code is different than the driver code and has no knowledge of it. I should note that at the moment, the Arduino drivers are now significantly faster than they are under ESP-IDF. I will research how to make them faster under the ESP-IDF, as this was a very recent update that had these performance improvements.

Q4: It was accidentally checked in duplicated because i use the fonts under both projects.

And to answer your question in the final response, yes, it will take any null terminated ASCII buffer. Note that UTF-8 support is only available with TrueType because the old win 3.1 FON format doesn't support it. Note that it doesn't word wrap - it clips. Insert line breaks "\n" or "\r\n" in your text to compensate.

Edit: There are headers in the /font folders you can embed. Basically, if your header is called myfont8x8.h (that was generated from myfont8x8.fon) you would include it after gfx_cpp14.hpp Then you could do like const font& my_font = myfont8x8_fon;

The name of the font to reference is the name of the header with illegal chars turned to underscores.

codewitch-honey-crisis avatar Feb 15 '22 22:02 codewitch-honey-crisis

Thanks for the above, will try as soon as I get a change. For now I am still working through the gfx_demo repo to see how I can bring that in as a component without any modifications to your repos...

I am not that experienced in creating ESP-IDF components but through trial and error have found that the relationship between directory structure and CMakeLists.txt is critical. It sounds to me like you have 3 possible components here with a specific relationship between them.

At the bottom I guess should be 2 components, gfx and the SPI/I2C/8bit drivers, housed in separate repositories. This will allow developers to use these 2 components, individually or together, in their own applications.

At the top level I guess should be your gfx_demo as a separate repository. This repo should maybe contain only the code required to demonstrate the functionality of the other 2 repos. The 2 "lower level" repos being linked/included on this level, providing you the functionality, using the links, to select the version/release of the lower level repos to use. This will also allow for fixes and changes to be made only only and in 1 place.

Just my thought on what I have seen the experts do...

ammaree avatar Feb 16 '22 11:02 ammaree

For gfx_demo what you want to do is pull out the ILI9341 code and everything under the /lib folder for your own project. The ILI9341 code is arduino/drivers/ili9341.hpp, and then you'll need all the spi_master.hpp and tft_spi_driver.hpp files under esp-idf/drivers/common. Recreate the "/common" folder under your sources includes folder and dump those files under there. Dump ili9341.hpp in the includes folder one level back from /common so instead of say, inc/common, ili9341.hpp would simply go in inc/

If you're using platformIO you'll need to set the build flags for the compiler to use gcc++14 instead of 11. See the platformio.ini entries for examples. You'll probably want to copy the code from the esp-wrover-kit entry since it enables PSRAM

It's not distributable as a component yet. I'm still working on the best way to deploy it as a series of libraries. I've been holding off because when I do it I don't want to botch it. I need to make sure everything is in it's final form, or close to it at least. For example I recently made major change to the structure of the arduino drivers.

Edit: You don't want to always build with the latest directly off github. sometimes i make breaking changes. I'd stick to a version if i were you.

codewitch-honey-crisis avatar Feb 16 '22 11:02 codewitch-honey-crisis

If you're seeing this in email please go to github and refresh. I made significant edits to my prior post. It's early here and I'm still on my first coffee. =)

codewitch-honey-crisis avatar Feb 16 '22 12:02 codewitch-honey-crisis

First coffee !!!! that explains everything....

I am unlikely to try doing the GFX test before this weekend, probably Sunday or Monday, due to other pressing work. Maybe I leave you to do what you need to until then and we touch base on Monday?

ammaree avatar Feb 16 '22 12:02 ammaree

Well here's the thing. I'm not nearly ready to put the drivers up as a library. The problem is that the source code is going to dramatically change, but that rewrite is going to take research and time. I won't have it by monday, and maybe not this month. The esp-idf drivers work as is. I'm just planning on bringing them more on par with the Arduino drivers, but the esp-idf is quite different.

So for the following bear in mind that GFX is just a drawing library.

The drivers it uses are a separate animal. That makes it unlike other libraries.

And GFX itself is a library. Remember that standalone GFX repository? You can convince platform IO to fetch that and put it under your lib folder.

I'll add it to platform IO's official repository this weekend.

I will not be adding the drivers themselves for some time. You should really include those files manually. In the end it will make your project more robust to version changes, since the new versions WILL break your code when released. Your drawing code WILL NOT break. But your driver initialization code will.

codewitch-honey-crisis avatar Feb 16 '22 13:02 codewitch-honey-crisis

No problem, I will relook the config using your advice this weekend.

But just remember, we do not use PlatformIO but as mentioned in 1st post, native IDF (master) with Eclipse so I will need to bring it in, most probably manually as you suggest, as my own component.

ammaree avatar Feb 16 '22 13:02 ammaree

Sorry, I forgot you were using Eclipse. I've recently updated the codebase and the documentation, but it won't affect your code. GFX is just a bit more cross-platform friendly now.

I have no plans to release this as an ESP-IDF component. Sorry. It's just not in the cards. If I had more contributors I'd strongly consider it, but I've got to pick my battles, and I'm already struggling with a game plan for keeping a platformio repo.

I've looked into making the ESP-IDF drivers faster. I've talked to one of the developers that works for Espressif as we have a rapport. He confirmed my fears that I'd have to spelunk through the HAL headers to figure out what to do. Because of that, I may not have drivers that perform as fast as the Arduino versions. The problem is "SPI Master" which is the API that ESP-IDF exposes for SPI communication isn't very good at driving TFT displays. It's just not, because of the way it was designed. It's unfortunate, really. This is part of the reason why I've focused so much of my efforts on the Arduino end of things lately, and part of the reason why I use Arduino for my own commercial endeavors - that and more library/device support.

I'm not saying you should switch, but buyer beware. I'll do some more research into making the ESP-IDF drivers faster. I haven't exhausted my approaches yet. I may be able to get around using ESP-IDF's SPI transaction system altogether by driving the CS line myself. We'll see.

codewitch-honey-crisis avatar Feb 18 '22 21:02 codewitch-honey-crisis

Sorry to revisit an old issue, but any progress on the ESP-IDF front over the last 5 months.

We have done some looking into the ESP-IDF vs Arduino comments in your previous post. From what we can see the Arduino code is almost completely based on ESP-IDF APIs, mainly wrapping IDF functions together to maintain the Arduino functionality.

To find an example of the fastest ESP32 SPI drivers, from everything I have been able to see the most efficient SPI drivers are used in the LVGL repository. I think they originally come from another Github contributor, just need to scan through the LCVGL forum to find the source of the optimised SPI driver

ammaree avatar Jul 11 '22 16:07 ammaree

It is not based on the ESP-IDF. The only bits that are are the DMA transfers. Most of the code uses internal ESP32 registers exposed by the HAL. That's a level below the IDF's API. The generic (unoptimized) calls fall back to the Arduino framework on those drivers.

This is all in the latest stuff, not gfx_demo, mind you.

If you want to look at the SPI interop code the latest drivers use, check this link. https://github.com/codewitch-honey-crisis/htcw_tft_io Specifically this: https://github.com/codewitch-honey-crisis/htcw_tft_io/blob/master/include/tft_spi.hpp

The ESP-IDF has no corollary in terms of how it handles transactions. You cannot manually set transaction boundaries like you can with Arduino, you must manually copy into a buffer then use that buffer for a transaction. You also cannot set the speed on a per transaction basis under the IDF. These are both critical features to enable performance and things like alpha-blending.

I'll look into LVGL code but so far it has been kind of confusing to me. I haven't wrapped my head around the architecture.

codewitch-honey-crisis avatar Jul 11 '22 17:07 codewitch-honey-crisis