Jump to content

David Kibble

Members
  • Posts

    32
  • Joined

  • Last visited

Everything posted by David Kibble

  1. Thanks Guys. Done and working, just detached the source when screen back light goes off then I use a periodic check on the ginputGetMouseStatus() to detect a touch and re-attach the listener. Did that so that it doesn't matter where on the panel is touched.
  2. Thanks Joel - you are a star. That sounds much cleaner than hacking the core uGFX code. I'll have a look at what's needed for the gwinDetachMouse(). Dave
  3. Hi Guys. I'm after some advice on where and how to modify the ginput code so that I can catch and if necessary block a mouse (touch) event. The reason for wanting to do this is that for bedroom usage I need to turn off the backlight of a control panel, that's easy - if no use for > some timeout turn off the backlight. So when it comes to turning back on, I can easily capture a touch event, BUT the problem then is the user might have touched a button without being able to see it triggering an action they may not want, so we need to say "If backlight is off, catch touch event and turn backlight back on but do not pass that touch event to any widgets for processing". I can see a few places where I could add that sort of code, such as within the gmouse_lld_linux_event.c (I'm using a Linux board) or within ginput_mouse.c itself. Or is there a better way to tackle this? Many thanks in advance. Dave
  4. Many thanks - that got it. Maybe it would be worth putting that vital hint on the Wiki in the custom board section along with a sample project and board makefile?
  5. Hi Guys. Could you please give me an official steer on the use of local GHandles. Your examples and Studio always generate global scope vars for all GHandles, but is there actually any problem in taking the approach of using local (within a function) GHandles for graphic entities which are transient and modal such as dialogue boxes? For example you could have a function; showDialogBox(...) { GHandle container; GHandle button1; GHandle button2; etc etc gwinShow(container); <event loop waiting and processing modal events for button 1 and 2> gwinDestroy(container); } I prefer this style wise as it contains the variables and logic, reduces the sheer volume of global vars which you end up with on a large UI project and creates a more easily reusable component. But - are there any negative side effects within uGFX of doing this? I ask because I'm getting some odd behavior now on a large UI where container hierarchies are not redrawn properly and before I start diving into my code, it occurred to me I should check the above pattern with you guys. Thanks
  6. Hi Guys. Not having much luck with this. Following the above advice my project makefile looks like this; GFXBOARD = Linux-Framebuffer-Touch_A13 ... include /home/dkibble/workspace/TouchControl/Linux-Framebuffer-Touch_A13/board.mk The TouchControl/Linux-Framebuffer-Touch_A13/board.mk looks like this: GFXINC += /home/dkibble/workspace/TouchControl/Linux-Framebuffer-Touch_A13 GFXSRC += GFXDEFS += -DGFX_USE_OS_LINUX=TRUE GFXLIBS += rt include /home/dkibble/workspace/TouchControl/Linux-Framebuffer_A13/board.mk include $(GFXLIB)/drivers/ginput/touch/Linux-Event/driver.mk and the TouchControl/Linux-Framebuffer_A13/board.mk looks like thisl GFXINC += /home/dkibble/workspace/TouchControl/Linux-Framebuffer_A13 GFXSRC += GFXDEFS += -DGFX_USE_OS_LINUX=TRUE GFXLIBS += rt include $(GFXLIB)/drivers/gdisp/framebuffer/driver.mk Alas when I execute make I just get; make -f makefile.arm clean /home/dkibble/ugfx/ugfx/gfx.mk:38: /home/dkibble/ugfx/ugfx/boards/base/Linux-Framebuffer-Touch_A13/board.mk: No such file or directory make: *** No rule to make target '/home/dkibble/ugfx/ugfx/boards/base/Linux-Framebuffer-Touch_A13/board.mk'. Stop. and that line in the gfx.mk is; # Include the boards and drivers ifneq ($(GFXBOARD),) include $(GFXLIB)/boards/base/$(GFXBOARD)/board.mk endif Which was my original starting place. Any ideas? I've copied the board.mk files from the ugfx source as that seemed logical. Is that my error? What should a custom board.mk look like? Many thanks
  7. Is cost the main concern for you and do you have stringent real time constraints? If not - maybe look at other embedded Linux boards such as those from Olimex (a20, a13 etc). These boards offer a huge amount of processing power and memory along with good i/o and various LCD interfaces including direct RGB for a reasonable price and size. I've used the A20 and A13 along with RGB 4.3" and 5" 800x480 LCDs from China alongside uGFX. The BuyDisplays LCDs are pretty good in my experience (have used 2.8" SPI + 4.3" RGB models). Touch screens work fine with uGFX as they use the Linux touch driver included by Olimex in their Debian build. The great thing with these types of embedded Linux boards is you can easily move from testing on your Linux PC to the real hardware with good confidence things will work exactly the same. Yes there are some odd differences, but it's a much easier road in my experience compared with truly dedicated hardware. Just an idea in case you are not wedded to the STM32.
  8. Hi Guys. Going back to the original question - did you solve the problem of the double redraw? I'm having something similar on multi-container UIs. Switching between 'screens' using the guiShowPage(...) type approach generates two redraws, the first after the gwinHide, the second after the gwinShow I think. You mention trying different GWIN_REDRAW_IMMEDIATE modes, what did you conclude? Many thanks
  9. Hi Guys. I've got a simple problem which there must be a simple answer to, but I've not found it yet. With the 2.7 release of uGFX I took the opportunity to tidy up my projects and code so that I would not have any modified or non-uGFX files within the uGFX source tree. I have a custom board file for my production hardware which I moved to my project source tree and I use the standard Linux-SDL board for PC based testing. My problem is gfx.mk, it has the section; # Include the boards and drivers ifneq ($(GFXBOARD),) include $(GFXLIB)/boards/base/$(GFXBOARD)/board.mk endif So fairly obviously that fails to find my custom board in my source tree, but works fine when I switch to the standard "Linux-SDL" board. I can modify gfx.mk to work with both my project based board and the standard UGFX boards, but that's breaking my aspiration to not fiddle with anything in the uGFX source tree. What am I missing / not doing here? I've read the Wiki section on custom boards, but it doesn't seem to have any additional steps which I'm missing. My dev environment is Eclipse CDT running on Debian 8. Many thanks Dave
  10. Thanks Joel. I'll certainly cut the code over to using a GTimer and post back here when it's done. Dave
  11. Hi Joel. I could certainly move this to a GTimer but as I wasn't using that module and my hardware is pretty fast I went the dedicated thread route. I hope someone finds this helpful, even if thats just for learning uGFX basics. Dave
  12. Hi All. Not sure if this is the right place to share code, but please find attached some simple code to create a 'spinner'. By spinner I mean a visual indicator of the system being busy or processing, much like the hour glass in old Windows or the rotating circle in Linux, Android etc. It's fairly basic but does the job for me. The code is hopefully self explanatory but just to give a quick summary. The spinner is displayed by a gfxThread which is created the first time you call showSpinner(...), that function takes two params, one is a Boolean (bool_t) which controls if the spinner is made visible or not and the second is a GHandle for the parent under which the spinner is drawn. There are functions to control, colour, size and style of the spinner. I've coded 3 styles, a spinning pie segment, a spinning arc segment and a horizontal bar "knight rider" style. If for any reason you need to stop the thread which runs the spinner just call stopSpinnerThread(), this may save resources on very low spec hardware instead of just hiding the spinner using showSpinner(FALSE,...). I've left a few printfs in there so you can see the thread startup and exit. Just take them out if you don't want them. To use the code just include "spinner.h" in your code, add the spinner.c to your source code folder, add spinner.c to your makefile and then just call showSpinner(TRUE,<parent>) from your code. You can pass NULL for <parent> in which case my code redraws the whole display, e.g. showSpinner(TRUE,NULL); The spinner will run until you call showSpinner(FALSE,<parent>). The speed of the spinner is hard coded, but you can easily change it by altering the usleep(...) in spinner.c line 149. The code has been written and tested on Linux host and targets and uses the default thread stack size with low priority. You can experiment with these values if you need to. You'll need to enable a few things in your gfxconf.h #define GDISP_NEED_CIRCLE TRUE #define GDISP_NEED_ARC TRUE #define GDISP_NEED_MULTITHREAD TRUE Good luck. Dave spinner.c spinner.h
  13. Hi Joel. Many thanks for the reply. Its an ARM Cortex A8 driving a 480x272 RGB mode TFT. The SDL emulator is about 250us. Not tried anything else yet. I've got a BBB knocking around, might benchmark that for fun. Dave
  14. Hi. OK - that is a good call. I'd missed the non-filled gdispGDrawStringBox(...) function. Using that makes the code a lot simpler as now I don't need all the lower level supporting gdisp code for my custom gdispGFillStringBox(...), also thanks for the design guidance re "no gwin calls from gdisp". I'm going to have a look at the streaming API when I get a chance, but the rendering is only taking around 400us max for a whole screen and about 80us for an individual label so it's not a pressing performance issue. Many thanks Dave
  15. Hi - I'm not sure I'm getting you on this; Here's the standard line draw code; void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { MUTEX_ENTER(g); g->p.x = x0; g->p.y = y0; g->p.x1 = x1; g->p.y1 = y1; g->p.color = color; line_clip(g); autoflush(g); MUTEX_EXIT(g); } MUTEX is on GDisplay Here's the standard gdispFillStringBox which is called by the standard label rendering routine: void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { #if GDISP_NEED_TEXT_WORDWRAP wrapParameters_t wrapParameters; uint16_t nbrLines; #endif MUTEX_ENTER(g); g->p.cx = cx; g->p.cy = cy; g->t.font = font; g->t.clipx0 = g->p.x = x; g->t.clipy0 = g->p.y = y; g->t.clipx1 = x+cx; g->t.clipy1 = y+cy; g->t.color = color; g->t.bgcolor = g->p.color = bgcolor; TEST_CLIP_AREA(g) { // background fill fillarea(g); Again MUTEX on GDisplay - or am I wrong? So - my problem is that as I want to use gdispDrawLine from my gradient code which is called from my cusomised FillStringBox the MUTEX on GDisplay is already locked. Hence my workaround to unlock it prior to my gradient draw and then re-lock it all within my cusomised FillStringBox. This is absolutely the problem as a simple GDB session shows and is all at the gdisp layer not the gwin layer. Yes - the cusom label rendering as the gwin layer, but that MUST call the FillStringBox routine in gdisp to repaint the background. Now it's quite possible I'm missing your point, so apologies in that case, but as far as I can tell there is no separate gwin MUTEX at play in the problem here. On the streaming front - I'll take a look at that when I have a bit of spare time. Performance on my Cortex A8 board is absolutely fine, can't even see the slightest hint of the redraw occurring. Many thanks for the help with this. Dave
  16. Hi Guys. I'm having to partially give up on this approach. I looked at the low level innards of the line drawing routines and to utilize them I'd either have to pull a huge chunk of the internal gdisp code into my codebase or directly modify your gdisp code. Both of those would be a PITA when the next version of uGFX comes along. So for now what I've done is quite simple and I cannot believe I missed it before; void gdispGGradFillStringBox(GWidgetObject * gw, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { GDisplay * g = (GDisplay *)gw->g.display; MUTEX_ENTER(g) #if GDISP_NEED_TEXT_WORDWRAP wrapParameters_t wrapParameters; uint16_t nbrLines; #endif g->p.cx = cx; g->p.cy = cy; g->t.font = font; g->t.clipx0 = g->p.x = x; g->t.clipy0 = g->p.y = y; g->t.clipx1 = x+cx; g->t.clipy1 = y+cy; g->t.color = color; g->t.bgcolor = g->p.color = bgcolor; TEST_CLIP_AREA(g) { MUTEX_EXIT(g) gradientPartialRendering(gw,&mainFormGradConfig); MUTEX_ENTER(g); // background fill //fillarea(g); So it's a bit of a hack - but gives very little window of opportunity for other threads to corrupt 'g' If you can either expose the internal functions or make the MUTEX's controllable (or have any other ideas how I can link my code to your code without mods) then I can come back to this. For now though, the above works fine for my multi-threaded app. Just to recap in case anyone else is reading..... The problem here was how to override the rendering of the label component. Easy to create a custom rendering function for the label, but that custom rendering cannot easily use high level gdisp functions like DrawLine because the Label rendering routine itself uses the same MUTEX as the other gdisp functions. Hence if you lift and shift the existing label rendering to modify it, you get stuck in a mutual dependency of MUTEX's. Thanks for the idea and info though, all much appreciated. Dave
  17. Many thanks - I'll take a look at moving my gradient draw routines to the low level functions. Once I'm happy with all of this I do still plan to share my gradient code, I guess I'm a bit of a perfectionist so didn't want to pass it on until I'd shaken out all these sorts of issues. Dave.
  18. When I looked at this I took away that a buffer is really no more than a shared memory block. You can certainly use buffers as a means to move data between threads or functions but it depends what functionality you want. Queues are FIFO so preserve sequence which may be important to you. Also queues take care of next available and empty functionality. Mutex's can be used with both to control thread behaviour but generally I haven't needed them with queues other than for when I'm searching a queue and want to stop other threads adding / removing at the same time. Concurrent queue processing is fine, the get functions are atomic. I think without knowing more about your requirements its hard to say which would be most appropriate. If you aren't sure and you don't need random access most of the time I'd go with queues. I'm using queues for command processing and message queuing and have found uGFX to be very solid. Dave
  19. Hi Guys. Sorry for posting an update so soon but I've been having more of a poke around this. I've changed the code in my custom gdisp function to look like this; void gdispGGradFillStringBox(GWidgetObject * gw, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { GDisplay * g = (GDisplay *)gw->g.display; #if GDISP_NEED_TEXT_WORDWRAP wrapParameters_t wrapParameters; uint16_t nbrLines; #endif g->p.cx = cx; g->p.cy = cy; g->t.font = font; g->t.clipx0 = g->p.x = x; g->t.clipy0 = g->p.y = y; g->t.clipx1 = x+cx; g->t.clipy1 = y+cy; g->t.color = color; g->t.bgcolor = g->p.color = bgcolor; TEST_CLIP_AREA(g) { gradientPartialRendering(gw,&mainFormGradConfig); // Moved to avoid the MUTEX which locks on (g) MUTEX_ENTER(g); // background fill //fillarea(g); I added the gw widget param to make it easier to drive my gradientPartialRendering function but the main thing I wanted to check is what is the risk around moving the MUTEX_ENTER(g) in the way I have? Without pouring over the low level code it's hard to know. Just FYI - my application does do a small amount of GUI updates via a background thread with the bulk of the work being on a single GUI thread. I'm assuming that's why you have the MUTEX in there? Anyway - the result is perfect and is attached. Note the clock in the lower right corner. Dave
  20. Hi Folks. Over the past month or so I've implemented a number of custom rending routines for uGFX but now I've hit on a problem. I've created a set of very nice looking gradient fill and partial gradient fill rendering routines which I'm using without issue. However - I now want to use my partial gradient fill (fills a specific area of the screen with a gradient colour to match the gradient colour of the background at that point) to produce a label which would therefore appear 'transparent'. The label background is my custom gradient fill and the text is as per normal. It's use would be great for something like a digital clock which although functional without this enhancement looks a bit clumsy with a solid background over the gradient. So first up this took a bit more doing than most of the other customisation I've done as the standard label fill comes from the gdispGFillStringBox function which is buried down in the gdisp code and seems to come with a lot of dependencies when you pull it out. Anyway - sorted that and have my own renamed gdispGFillStringBox and all associated functions out in my own codebase. All compiles and works fine. :-) Now the problem. (Finally I hear you cry !) My custom rendering uses gdispDrawLine and gdispDrawLine's first instruction is MUTEX_ENTER(g), unfortunately that MUTEX_ENTER(g) is also executed by the gdispGFillStringBox and thus as it stands gdispGFillStringBox cannot therefore call my custom gradient function which uses gdispDrawLine as the MUTEX is already locked. I hope that makes sense? So at this point I'm really open to some expert guidance on how to solve this. I can see that the gdispGFillStringBox uses some low level functions for it's fill and the gdispGDrawLine uses line_clip(g), but should I try to implement my custom gradient rendering using those low level functions? I guess its not that hard to do, but before I go off and figure it out I'd really appreciate some advice from the experts as to what the correct approach in this sort of situation would be? Have I for example gone off on completely the wrong track here? Many thanks Dave
  21. Hi Guys. A few screen shots attached. The colours used in the gradients and the degree of fade can all be changed. The banding is just from the JPG compression, on the screen the gradient is very smooth indeed. Dave
  22. Thanks Guys. I knew the answer would be obvious. I hadn't appreciated that primitives wouldn't be included in the redraw logic. I've done some nice custom draw routines already for creating background gradients and a few 'gauge' type widgets so now that I know what to do I can just add my primitive decorators in there too :-) Thanks for the great support and a great product. If I end up getting this all to work I'd like to contribute something to you financially. Is there a 'donate' facility anywhere? I'll also try to help others as and when I can from the experience I'm gaining now. Dave
  23. Hi Everyone. I'm pretty new to uGFX having spent a while dabbling with QT in an attempt to create a nice UI for a home automation system. That was fairly painful and frankly overkill for what I needed, so when I found uGFX I was thrilled given it's capabilities and the fit with my experience of C. So - lots of try out code written, projects building nicely in Eclipse, Cross compiling working for my target A13 board, but now I've hit something so stupid I cannot believe I'm stuck! So here goes.... I want to draw a line on a window container that also holds some buttons. That's it!!! Try as I might, I can get the buttons to show up and function, but no line.... I want to use containers so I can create 'pages' of buttons and switch them nicely, but for visual effect I'd like the pages to have some of the basic primitives on them. My gui part of my noddy code looks like this; GWidgetInit wi; GHandle ghMainPage; // Apply some default values for GWIN gwinWidgetClearInit(&wi); wi.g.show = TRUE; wi.g.width = 480; wi.g.height = 272; wi.g.x = 0, wi.g.y = 0; // create container widget: MainPage wi.g.show = TRUE; wi.g.x = 0; wi.g.y = 0; wi.g.width = 480; wi.g.height = 272; wi.g.parent = 0; wi.text = "MainPage"; wi.customDraw = gwinContainerDraw_Std; wi.customParam = 0; wi.customStyle = &MaroonStyle; ghMainPage = gwinContainerCreate(0, &wi, 0); // Create the separator gwinDrawLine(ghMainPage,0,40,480,40); // create button widget: ghSettings wi.g.show = TRUE; wi.g.x = 240; wi.g.y = 20; wi.g.width = 120; wi.g.height = 20; wi.g.parent = ghMainPage; wi.text = "Settings"; wi.customDraw = gwinButtonDraw_Normal; wi.customParam = 0; wi.customStyle = &SilverStyle; ghMainSettings = gwinButtonCreate(0, &wi); That all complies and runs fine, but the separator just doesn't show up. Please let me know what I'm doing wrong, happy to be pointed at the docs (which are great by the way) but I feel like I must be missing something basic here. Oh - I've tried this on Linux-SDL, Linux-Framebuffer (on the target) and Win32 and all behave the same. Many thanks for any help. Dave
×
×
  • Create New...