-
Posts
2,653 -
Joined
-
Last visited
-
Days Won
2
Content Type
Forums
Store
Downloads
Blogs
Everything posted by Joel Bodenmann
-
Seems like you're making progress - good work. Now you need to verify whether the signals are really doing what the display controller expects (and there's not really much that can go wrong like with SPI modes or so on). Once you're sure that your waveforms look right you can just go back to your uGFX stuff and implement the board file / driver. Timings should not be of a concern at this stage. Usually you set them very low (or rather high, depending on your point of view) intentionally just to be sure that it won't be a limiting factor. Once you have everything running you can start dialing the timings to find the sweet spot.
-
I didn't carefully check every line of your code but I assume that the compiler is simply optimizing it out because you always change fsc[0] (this might be wrong if you setup volatile pointers correctly and so on, I barely skimmed your code). Try to write to different FMC target locations. Also, disabling compiler optimization completely is always a good help in these kinds of debugging / boot-strapping situations.
-
Hello @quipu and welcome to the µGFX community! As @aeroman already mentioned the problem is that the changes are not being flushed to the real display. The UC1610 GDISP driver needs to maintain an internal framebuffer as the display controller doesn't provide one that allows addressing each pixel individually. Therefore, when rendering you always modify the framebuffer inside your microcontroller's RAM. The framebuffer contents need to be actively pushed to the UC1610 display controller. This is done by what's called "flushing" in the GDISP module. There are multiple ways to flush: Manually call gdispFlush() Use auto flushing (can be enabled in the configuration file) Use a flush timer (can be enabled in the configuration file) I hope that helps.
-
Great!
-
I agree that the best solution is to run your µGFX computer on a desktop machine as suggested by @inmarket. µGFX is fully portable. You can take your microcontroller application and compile it to a native Windows / Linux / MacOS application. Of course, if you did your software design right you can just copy paste the entire thing. Otherwise, just copy the GUI parts.
-
Hello @youqun and welcome to the µGFX community! The font converter is now up again. We did a lot of reconfiguration in our network lately and this one must have been missed out. Please excuse the inconvenience. Pro tip: The new µGFX-Studio has a built-in font converter.
-
https://wiki.ugfx.io/index.php/Pixmaps https://wiki.ugfx.io/index.php/Multiple_displays Yes. that is correct. It cannot be disabled. It's a built-in feature. This allows for a much smaller and faster window manager. You cannot hide a background (container) without overwriting the area because you can't delete something from the display - you need to overwrite it. You can use doublebuffering as explained in my previous post to prevent things like this (there are many other additional things such as TE integration and so on).
-
I'd just like to add that µGFX still has everything you need to read back the framebuffer. So if you GDISP driver and/or your hardware supports it, you can use GDISP high-level API to read back the framebuffer and write it to an image. Another alternative for a GWIN based application is to render everything into a pixmap. If you have a top-level container you can just change the display pointer to render into the pixmap. The pixmap itself already supports writing to an image. Here's a forum post regarding rendering to GWIN stuff to a pixmap:
-
To save a lot of resources (especially RAM and also CPU time).
-
This is the relevant code taken from the µGFX-Studio v0.22.4: void UGfxWindow::setDisplay(GDisplay* g) { if (!_ghandle) { return; } // Nullptr means default/standard display if (!g) { g = GDISP; } gwinHide(_ghandle); _ghandle->display = g; gwinShow(_ghandle); } _handle is the GHandle.
-
There's no hacking involved. You just need to change the GDisplay* pointer. We did the same thing for the µGFX-Studio.
-
Hi, The most common solution is (as you mentioned) double buffer. However, proper double buffering is very hard to implement and also requires hardware support. While µGFX can fully support double buffering (with the multiple displays API) we do also provide you with a more flexible way: Pixmaps. You can simply render your widget into a pixmap and then blit that pixmap to your real display. Pixmaps have certain advantages over real double buffering. The most notable is that you don't need two times the memory for the entire display area - a pixmap can be just a small portion of the screen. Other than that there are other things which vastly improve these sort of things such as anti-tearing-effect flags and so on. But all of that needs to be supported by the hardware.
-
The SSD1963 has an R/S pin which is used to tell the display controller whether the incoming data is configuration data or actual pixel data. This is done so that you don't need to wire up all the address pins in order to address each pixel individually (and each configuration register). The two macros above are used to access the SSD1963's memory, one time with R/S set to 0 and one time set to 1 - essentially giving you the option to write pixel data or configuration using "stock FSMC" without having to manually control the R/S pin via a GPIO. You need to ensure that the macro which sets the R/S pin has the correct address. So if you hooked the R/S pin up to FSMC_A16 you need to sure that GDISP_RAM has address bit 16 (the 17th bit) set to 1. FSMC is usually extremely straight forward and there is little that can go wrong. Just make sure that you use low timings until everything is working. Then you can ramp them up. But usually you want to be somewhere in the range of 10k to 100k until everything works. Also make sure that your pins are setup correctly (that the correct pins are being set to alternate function and so on). The most difficult part with the SSD1963 is getting the panel parameters correct. Make sure that you always at least tripple-check them. Those parameters are different for each panel. You should get a table of values together with your panel. However, note that the parameters you get are not always the ones you need to enter into that parameter struct. They are often calculated differently. I know that this post isn't as helpful as you might have wished for but there's not much we can do. FSMC is pretty much self contained: It's all about accessing a memory region. Everything else is up to your hardware and proper pin configuration. Simply tripple-check everything, take a break and do it again. Also, you definitely want to use a scope or logic analyzer to have a peek at those FSMC pins. Keep in mind that you can test the FSMC outside of µGFX. All that FSMC is doing is accessing a memory region. Therefore, you can setup your pins and just try accessing the SSD1963 with the two macros above - no magic involved. You can then just make call to the one with R/S = 0 and one with R/S = 1 in the main loop and use a scope or logic analyzer to verify that the correct pin is toggling.
-
GWidgetObject is the base widget call: https://git.ugfx.io/uGFX/uGFX/src/master/src/gwin/gwin_widget.h#L109 You don't usually worry about those as you always access them using the GHandle. Edit: Yes, GWidgetObjset is definitely a spelling error.
-
STM32F446 + ILI9341 (by STM32F4 to ILI9341 using uGFX)
Joel Bodenmann replied to Bilymo's topic in Support
Hello Bilymo, I don't understand what you're trying to say. The µGFX library is by far the most portable and agnostic library out there. You can run µGFX on virtually any platform and with any driver. The Keil guide clearly states that the example uses the SSD1289 driver but that it's the same process for any other driver: We cannot provide a guide / tutorial for every possible configuration out there. If you need to use the ILI9341 driver just follow the SSD1289 example but pick the ILI9341 driver. We're open to any kind of feedback regarding the documentation. If you feel that you have some improvements to share we're happy to hear them. But we surely aren't going to write guides for every possible combination. -
STM32F446 + ILI9341 (by STM32F4 to ILI9341 using uGFX)
Joel Bodenmann replied to Bilymo's topic in Support
I currently don't have access to a running Keil instance. Can you please show us screenshots of the relevant parts (file tree, compiler path settings, ...). The error message you're getting indicates that you didn't properly add the path to the driver directory to the compiler include path list: -
STM32F446 + ILI9341 (by STM32F4 to ILI9341 using uGFX)
Joel Bodenmann replied to Bilymo's topic in Support
as @inmarket already told you: You must not copy the driver directory. Please just follow the guide exactly step-by-step. It's well tested and used frequently. -
I'd recommend you to import the project instead of copying into a workspace folder. That's how Eclipse is meant to be used.
-
May I ask what panel that is? (Just for personal records).
-
Support for STM32F469i-Discovery
Joel Bodenmann replied to inakto's topic in Development and Feedback
The STM32F469i-Discovery board files have been added a long time ago. -
Is it possible that you forgot to include the driver (or just didn't do it accordingly)? Make sure that you follow that guide exactly. It's very well tested. Also, don't forget to set the compiler to GFX_COMPILER_KEIL in the configuration file when using Keil.
-
Redrawing transparent label with background image
Joel Bodenmann replied to Asaliii's topic in Support
Something like this (untested): void myRendering(GWidgetObject* wo, void* param) { coord_t sx, sy; // Cast parameters img = (gdispImage*)param; if (!img) { return; } // Render background (use the specified portion of the specified image) if (img) { // Determine the coordinates relative to the parent if (wo->g.parent) { sx = ... sy = ... } else { sx = 0; sy = 0; } // Render the image gdispGImageDraw(wo->g.display, img, wo->g.x, wo->g.y, sx, sy, wo->g.width, wo->g.height); } // Render the label gdispGDrawStringBox(...); } When creating the label you assign that rendering function to it and you pass a pointer to the containers background image as the parameter. -
Here's the corresponding API documentation: http://api.ugfx.io/group___g_o_s.html
-
Redrawing transparent label with background image
Joel Bodenmann replied to Asaliii's topic in Support
Hi, Yes, this is definitely due to the transparent custom rendering function. There is no concept of transparency in µGFX (that will follow with µGFX v3). The GWIN window manager excepts that the widget always clears it's own area. You have the following options: Modify your label's custom rendering function so that it receives an image chunk that it will use to clear the widget area prior to rendering the new text. The image chunk you give it should be exactly the container's background image below the label area. Redraw the entire container Redraw the entire container but render it into a pixmap and then just blit it to the display to ensure flicker-free and fast updating Write your own GWIN window manager that can handle transparency: https://www.youtube.com/watch?v=xZKgp5XaxVE Which option you're choosing is mainly depending on your platform and the available resources. -
Glad to hear that you managed to get it working I sense a bit of negativity in there - we're not trying to blame stack overflows for everything, but they are an extremely common issue that result in exactly that kind of behavior. However, stack overflows and concurrency issues often lead to very similar results. Also, I mentioned that I don't think that that's the problem in this case That's really difficult to do. 20k definitely sounds like fair amount of RAM then. Depending on what you're actually doing you can get way lower that that. We've systems that run with 5 kB or RAM and they do fancy-looking stuff. Usually you just start off with a very large number and once you're happy with your GUI you start making it smaller and smaller until shit hits the fan. Then you usually add a margin of 10 to 20% depending on the application. But keep in mind that that's a very "unsafe" approach as GUI memory usage often heavily depends on the user interactions. So while it might be enough for you and me it might still blow up if some dude starts pressing all the buttons at once or something