-
Posts
1,309 -
Joined
-
Last visited
-
Days Won
4
Content Type
Forums
Store
Downloads
Blogs
Everything posted by inmarket
-
Where are you loading the image from and what type of image is it? As ugfx decodes inline as it displays, a slow storage can mean slow image displaying. There are three sutions to the problem... 1. Put your image in fast storage eg using ROMFS. 2. Use gdispImageCache() to cache your image decode in memory (if you have enough RAM) 3. Create a pixmap, draw the image to the pixmap and then bitblit the pixmap to the screen whenever you want to draw the image (again this requires you have enough RAM to store the de oded image in RAM)
-
Based on that output please run the demos/modules/gos/threads demo and verify that threading is working correctly. I suspect that although it has compiled that basic threading is not working due to bugs in the Keil C library and this would certainly cause a blank display.
-
All the examples use TIME_INFINITE and therefore will never return a NULL. In practice that is what we encourage - to use TIME_INFINITE whereever possible for geventEventWait. There are plenty of other mechanisms in ugfx that could be used for polling so that the main event loop should not need to be cluttered by polling code eg ugfx threads and gtimer. Sorry, I have not yet had a chance to check out gevent. Coming very shortly.
-
With drawing algorithms we generally code for the lowest common denominator. ie. integer algorithms with as few multiply and divides as possible. To have a seperate "expensive" version just does not make sense. It is twice the code, twice the potential bugs, twice the maintenance etc. If and when we spend more time on it, it will be to improve the accuracy for all platforms. The issues identified are around the integer approximation and its interaction with the midpoint algorithm (note the x axis end-points that you commented on). For the ring you also need the corresponding reverse derivitive approximation for when the octants are not aligned between the two circles. We would really love it if you had time to look at this for us. Unfortunately we just have too much on our development agenda to look at improving this anytime soon.
-
You are right about the macro. We will fix that asap. Yes this is not exactly the midpoint algorithm. This is a first rather than a second derivative using the same reasoning. It is slightly less accurate than the midpoint algorithm however even the µGFX circle algorithm is not quite right either. In practice the true midpoint algorithm has some visual anomalies when rendered on low resolution screens that relate to the way integer rounding works. The µGFX circle algorithm has made some accuracy compromises in order to avoid those issues but is still very close to the midpoint algorithm. The reason the ring uses a different algorithm again is that swapping the quadrants would require a square root operation to do it properly. By making a slight compromise on accuracy we avoid that expensive computation. At some point in the future I may look at performing the same work on the ring code that was performed on the µGFX general circle algorithm but that is definitely not high priority. It is very time consuming to adjust that pixel here and there to get the best looking result at a range of sizes and resolutions.
-
0 = TIME_IMMEDIATE
-
As you found the trick is when the octants change. Even if the gdispFillDualCircle() is not suitable you should be able to derive something from it that will work for you. gdispFillDualCircle() also uses (a variant optimisation of) the Midpoint algorithm so it is very fast.
-
The reason your geventEventWait is returning NULL is that you have passed in 0 which is TIME_IMMEDIATE. You are effectively telling it to not wait for an event, so if there is no event ready it returns 0. If you pass TIME_FOREVER (Ithink that is what it is called) you will not get back a NULL, instead it will wait for an event. Any value in between those numbers is the maximum milliseconds to wait for the event.
-
If you have a framebuffer driver this is easy as you can gain direct access to the bits by knowing where the framebuffer is stored. The next easiest is a driver that supports readback. Looping through the display area using gdispGetColor (I think that is what it is called) would be fairly simple. This will also work for framebuffers as well as they support readback and this is a more generic way of doing things. If the driver does not support readback then things get complicated as there is then no way to actually get to the data. The only option would be to create a pixmap the same size as the display as draw to both the pixmap and the display simultaneously and then use the pixmap to get at the bits. This gets complicated when GWIN is involved as it only supports a window displaying to a single display.
-
This is a complex question. I will need to thouroughly review the code as it has been a number of years since I last looked at it. You know how it goes - if something is working you just don't play with it. My initial suspicions without looking at the code is that perhaps the semaphore is returning in situations that it shouldn't. Can you please tell me what operating system you are using as the problem could actually be in the GOS implementation. I will review the code fully when i get time in the next couple of days. Multithreading stuff can be very complex and there could well be a window of opportunity in the code. Thanks for letting us know.
-
A replacement framebuffer driver would need to be written that writes pixels byte by byte into 3 bytes per pixel format. The existing framebuffer driver assumes that each pixel is 1, 2 or 4 bytes so that it can write the pixel in a single cpu operation. Similarly the existing framebuffer driver does not handle pixel sizes of less than 8 bits per pixel. The changes should be simple by copying the existing framebuffer driver and modifying the pixel addressing and writing.
-
This is now fixed in the repository along with a couple of other bugs found when I reviewed the progressbar code.
-
These are low level GDISP functions. Any low level GDISP function should not have any reference to a GWIN object. I think you are possibly trying to do too much in your gradient call, in particular the drawing of the text. Your label custom draw should look something like... customDraw(...) { yourGradientFill(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gradient color params); gdispGDrawStringBox(....); } Note the use of the DrawStringBox rather than the FillStringBox as you have already filled the background with your gradient. Your gradient fill routine then can either be a high level call (using other GDISP functions such as the streaming or line functions), OR you can write your own low level gdisp call which takes the mutex and does all the hard work itself (and does not call other GDISP public functions). I would suggest the former. As an example - have a look at the button standard draw function. You will notice that the buttons have a top to bottom gradient with centered text on top so it will be very similar in code to the custom draw you are trying to write for the label (albeit with a different gradient algorithm).
-
I think there is a misunderstanding here. There is more than one mutex involved. 1. The low level gdisp calls maintain a mutex to protect the GDisplay structure. You should never play with this mutex unless you are writing low level gdisp code. 2. There is a seperate mutex that protects GWIN structures and drawing. This mutex is held by the gwin code during any gwin drawing routines. So, within a GWIN custom draw routine you are not allowed to use GWIN drawing routines such as gwinDrawLine as that would attempt to take the gwin mutex again resulting in deadlock. You ARE allowed to use GDISP calls such as gdispDrawLine because that does not touch the gwin mutex. For new GDISP calls they can either directly use other gdisp calls or they can take the GDisplay mutex and use low level functions available only in gdisp.c such as line_clip. They should NEVER reference anything to do with the GWIN structures as they are below that level. A GWIN custom draw however should NEVER be touching the GDisplay mutex as that mutex is only for use by the gdisp calls. It should also never touch the GWIN mutex as that is managed by the gwin code itself. A gwin custom draw should only make use of gdisp drawing calls. As you are looking to change color on every pixel you can either use the gdispDrawPixel call (or whatever it is called), or you can make use of the more efficient gdisp streaming calls (see the gdisp streaming demo). The final option is to write a new gradient gdisp area fill call and then use that within your custom draw however that is probably the most complex way of doing things. If you want to try that approach, first try writing it using the gdisp streaming calls and then translate that code block into a proper gdisp call. Using the gdisp streaming calls you don't need to worry about mutexes or driver models, all the nasty hardware and mutex stuff is already taken care of for you allowing you to concentrate on your real code.
-
Thanks Joel for pointing to the correct documentation .
-
The mutex is there to protect the GDriver structure from multi-threaded access. In GDISP there are two types of functions; base calls and high level calls. Base functions eg gdispDrawLine() take the mutex and use internal private low level calls to complete the operation. It was not intended that a user ever write such a function for their own application as any code inside the mutex is potentionally very complex and there are lots of ways that the code may not work properly on different platforms. These functions hide all the complexity of different display types, multiple display handling, syncing, multi-thread protection and many other hardware related issues from the end user. In many ways they are the core of uGFX. High level GDISP calls however are much simpler. They use the base functions and therefore are implicitly multithread safe. An example is gdispDrawBox(). So in answer to your question you should wherever possible avoid playing with the mutex or doing anything below that level. If it can be implemented using the GDISP base functions then it should. As you are doing edge to edge and top to bottom gradients this may not be possible except by using the GDISP streaming functions. The GDISP streaming functions are particularly designed for this or video style displaying. If you believe that your functions really are more appropriate to be in the GDISP base functions then we would be happy to consider their inclusion in the base API. For inclusion we would need source for your functions and we would be checking carefully (and if necessary fix) the issues talked about above to ensure good results for all situations. By the way, nice functionality!
-
GfxBuffers is designed to provide a pool of fixed size buffers that can safely be used accross multiple threads. Good examples of usage would be audio streaming (in and out), network buffers, disk buffers etc. it could also be used for message pools (but is not designed for message queuing). Queues are more general in nature and are basically just a fifo with appropriate multi-thread handling. There are 3 forms of queus, async, fsync and gsync. The difference between the three is what happens in failure situations eg async queues fail if you try to get from an empty queue. fsync queues will block in that situation until another thread puts an item on the queue. Similarly gsync will block in another fail situation (I can't remember exactly what off the top of my head - probably something to do with putting). Both fsync and gsync are extensions of async queues so the async calls will work on fsync and gsync objects when you want the non-blocking behaviour. uGFX itself makes good use of both async and fsync queues. You are right, this probably deserves a wiki article. I hope this discussion helps.
-
While tick positions etc are implemented as a axis style, the thickness of the axis line itself is not.
-
In the /demos/modules/gadc directory is a demo that shows the use of the GADC module on a Olimex AT91 board. It also shows a custom widget to display the GADC output as an osciloscope. In the /demos/modules/gaudio directory is a demo that shows a similar oscilloscope display using the gaudio recording input.
-
Being a posix based operating system i am assuming it will support posix threads. If it does you should be able to write a gos layer that uses that threading. If not, you could look at using the native stm32f7 threading that the raw32 gos port uses. Either way, what you want to be writing is a gos port for frosted. Unfortunately we have too much on our plates to be able to do it for you (except perhaps on a commercial basis) however we would be happy to help via the forum with any technical questions you have.
-
The thing to remember about the graph window is that it doesn't store state. If the screen gets redrawn the user needs to redraw the graph as the default redraw action for the graph is just to fill with the background color waiting for the user to redraw the graph itself. So, when the container the graph is on gets redrawn, the container then tells its children to redraw, the graph because it does not retain state just clears its background which leads to what you have seen. To solve your problem you need to redraw your graph after your container becomes visible. Another little gotcha is that window redrawing on ugfx often occurs on the delayed timer thread. The solution is to put a gfxYield call after making the container visible then redraw the graph after the gfxYield. The reason the graph does not maintain state is because to do so in a general manner would take too much ram. The application either already has the state or it will be redrawing new state (for a moving graph).
-
New post on image resizing: No there is no image resizing support built in to ugfx. Image resizing except in direct integer multiples is a complex process that generally requires the entire image to be resident in RAM. As ugfx avoids loading the entire image into RAM in order to keep resource usage to a minimum, it makes image resizing an even more difficult problem so we just don't do it. Too difficult, generally too resource heavy for an embedded platform.
-
Original post on external fatfs not working... Unless there is an api change in fatfs it must work. The only difference between the internal and external fatfs is that for external fatfs we don't initialise fatfs or include the fatfs code. We make the same fatfs calls in both cases. So, I expect that either there is an api difference in the external version of fatfs you are using that makes in incompatible, or there is some initialisation that has not been done that gfile is expecting. Can you please debug into the code to find why it is not working as we know it has worked for others in the past.
-
A work around is possible. In the gdisp driver directory modify the gdisp_lld_config.h and comment out the line turning on bit blit support (I can't remember the setting name off the top of my head). We still need to know which driver so we can fix it.