|
Forum Index : Microcontroller and PC projects : How to clear graphics from screen
| Author | Message | ||||
| PhilTilson Newbie Joined: 15/11/2015 Location: United KingdomPosts: 35 |
Hi - I'd appreciate some advice on a problem I'm having with a heating controller project. This uses a number of 'pages' to display different things. Moving between pages is mainly trouble-free, except for one page. This is the 'main menu' page: ![]() The third option on here shows an animated system diagram: ![]() This works fine. The problem is when I return to the main menu page: ![]() I have tried all sorts of ways of clearing the screen, starting with the original CLS, then two CLS statements with a pause in between, overwriting the page with a filled box, but I still get the problem! The relevant code sections are as follows: '================= 'These are the page setups GUI SETUP 1 'Display the Main Menu page FONT #9,2 GUI CAPTION #hdr1,"LAS GOLONDRINAS",5,16,"LMN",blk,wht GUI CAPTION #hdr2,"CONTROL SYSTEM",5,54,"LMN",blk,wht GUI BUTTON #btnSetHW, "Hot Water Settings", 200,100,400,60,blk,lgy GUI BUTTON #btnSetCH, "Heating Settings", 200,190,400,60,blk,lgy GUI BUTTON #btnSysDiag, "System Diagram", 200,280,400,60,blk,lgy GUI BUTTON #btnParams, "Set Parameters", 200,370,400,60,blk,lgy GUI INTERRUPT P1_Click GUI SETUP 5 'Display a blank box to contain diagram BOX 1,1,800,480,0,blk,lye GUI SETUP 9 'Display the fixed items on the page FONT 10,1 GUI CAPTION #capBatt,"1",495,26,"LMN",blk,wht 'this is the battery level display FONT 9,2 GUI CAPTION #capTime,left$(time$,5),698,16,"LMN",blk,wht 'this is the time in the top right '================= 'The next lines show the starting pages - illustration 1 above disp$="MENU" PAGE 1,9 readstatus '================= 'When "System Diagram" is touched, the following runs CASE btnSysDiag disp$="DIAG" PAGE 5,9 GUI INTERRUPT P5_Click '================= 'There are three routines that display the actual moving diagram 'One is shown below as an example. They all call the display routine which follows 'This part of the process works perfectly and displays illustration 2 above SUB UFH (mode%) 'This is the routine to get the right characters for the UHF circuit LOCAL disp$(4),col$ STATIC i%=1 SELECT CASE mode% CASE 0 'not active col$= "666666660666666660" disp$(0) = "SRRQ!!!!~TUUV!!l!~" DoDisp disp$(0), col$, 72, 336 CASE 1 'active col$= "111111110222222320" disp$(1) = "SRRQ''''~TUUV**l*~" disp$(2) = "SRRQ((((~TUUV++l+~" disp$(3) = "SRRQ))))~TUUV,,l,~" DoDisp disp$(i%), col$, 72, 336 END SELECT i%=i%+1 IF i%=4 THENi%=1 END SUB SUB DoDisp (d$, col$, stx%, sty%) 'This routine actually draws the characters 'd$ is the display string, col$ is the colour string, stx% and sty% are the starting coordinates LOCAL c$,i%,j%,x%,y% FONT 8 'diagram font x%=stx% : y%=sty% : j%=1 'starting values c$ = LEFT$(col$,1) 'starting colour FOR i%=1 to LEN(col$) if MID$(col$,i%,1)<>c$ then 'the colour has changed text x%,y%,mid$(d$,j%,i%-j%),,,,cols%(val(c$)) 'print the line up to the colour change RBOX 264,144,96,240,4,blk RBOX 288,144,48,72,4,blk RBOX 528,120,72,96,4,blk if MID$(d$,i%,1)="~" then 'this is the end of the line x%=stx% : y%=y%+24 j%=i%+1 ELSE x%=x%+(i%-j%)*24 j%=i% END IF c$ = MID$(col$,i%,1) 'get next colour END IF NEXT i% END SUB '================= 'Finally, when the screen is touched to return to the menu 'the following code is run: SUB P5_Click IF checkbl() THEN EXIT SUB 'exit without action if backlight was less than 100 disp$="MENU" CLS PAGE 1,9 GUI INTERRUPT P1_Click END SUB 'This gives rise to illustration 3 - and I just can't get rid 'of the stray bits of diagram! I appreciate that there's a lot to take in, but I know how difficult it can be to give advice without a full description. I'm hoping someone will be able to say "Ah well, it's obvious - you just need to ..."! Thanks |
||||
| disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 1044 |
I think its probably related to issuing graphics commands within an interrupt. The CLS and PAGE 1,9 stuff may not be started/completed when you expect. P5_Click and P1_Click are interrupts and general practice is to only do quick things in them, say set a flag that is then acted upon in the main DO:LOOP. I would also try to only ever set GUI INTERRUPT only once at the top of the program and have only one subroutine. Regards Gerry P.S. Nice schematic of the system. F4 H7FotSF4xGT |
||||
Grogster![]() Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9755 |
I'd agree with Gerry here. Tempting though it is to simply put what you want to run in the interrupts, you can't. I learnt this the hard way, and I suspect you are about to do the same. ![]() Interrupts MUST be as short as possible, so they process fast, and very odd things can happen if you start calling subs from inside interrupts etc. As an example, I have a page with three buttons on it - EXIT, DELETE and SAVE for database management when the user is editing an entry. I show what I want on the screen, then I execute: At the top of this section of code, I set the GUI interrupt to look for a touch on one of the three buttons on the screen. While waiting for a touch, none of the flags set in the interrupt will be 1, so the loop just goes around and around doing nothing UNTIL one of the button flags is set because the interrupt was called and returned with the flag set - then the code grabs onto that fact, and executes the relevant code. If no button is touched after a set time(SSDELAY*2), then the code sets another flag(Y) which is detected as part of the main loop as an instruction to jump out of the loop cos the user has taken too much time to do something, so this kicks the code back to the main menu via ON Y GOTO START. The interrupt code is: ...and the EXIT_OK buttons on any page interrupt is: You will see how all the actual work is done as part of standard DO/LOOP inside the master loop, and all the interrupt does is set a flag for whatever button was touched, and returns. Using this kind of idea, I have never again had odd things happening, as I am not calling the relevant code inside the interrupt, and THEN trying to return the interrupt - that does not go down well with the interpreter. ![]() Programming GUI's with interrupts is quite tricky for a start, but once you cotton on to how to do it, you will be away laughing. The key thing is to NOT hang around in ANY interrupt. Ever. Just set flags and exit immediately. Have your main code check the flags to see what needs to happen. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
| PhilTilson Newbie Joined: 15/11/2015 Location: United KingdomPosts: 35 |
Thanks for those thoughts. I will make some modifications and let you know what happens! |
||||
Grogster![]() Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9755 |
Best of luck. ![]() Please do feel free to ask if you have any other questions or problems. Smoke makes things work. When the smoke gets out, it stops! |
||||
| PhilTilson Newbie Joined: 15/11/2015 Location: United KingdomPosts: 35 |
OK - that seems to have solved the original problem, but...! It has introduced others. Rather than deluge you with detail, let me just ask a question: if you have several pages of controls displayed at one time and you output something to the screen, which page does it affect? The first one listed? The last? All of them? What is now happening is that the initial menu display is fine. I then go into the animated mimic display page and that is fine too - and it includes the battery and time elements that were on the menu page (see the pictures above). However, when I return to the menu page, these have disappeared. And when I go to the other pages, they don't appear either. It's as though running the animated display has overwritten the time and date areas and these are now lost for good. Any ideas? |
||||
| Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1646 |
While I completely agree with the concepts of handling interrupts as explained very well above (again). Geoff also has it covered in the Micromite manual. There can be exceptions... I have a couple of programs where an interrupt is called by operating a push button. The interrupt routine is a configuration utility and while it is running the main program is suspended. The configuration utility changes some variables, VAR SAVEs them and returns to the main program. Care must be taken so that the main program does not do anything stupid when it is returned to. Bill Keep safe. Live long and prosper. |
||||
Grogster![]() Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9755 |
Your DoDisp sub is PROBABLY where the problem is, in combination with your use of CLS to clear the screen. In a GUI, you don't really use CLS to clear the screen, you DISABLE the GUI controls you DON'T want to see at any given point, or use GUI pages as you have started to do. You can't really mix GUI controls and standard drawing controls. From the advanced manual, page 38: [Quote=Advanced Manual] There are two types of objects that can be on the screen. These are the GUI controls and the basic drawing objects (PIXEL, LINE, TEXT, etc). Mixing the two on the screen is not a good idea because MMBasic does not track the position of the basic drawing objects and they can clash with the GUI controls. As a result, unless you are prepared to do some extra programming, you should use either the GUI controls or the basic drawing objects – but you should not use both. So, for example, do not use TEXT but use GUI CAPTION instead. If you only use GUI controls MMBasic will manage the screen for you including erasing and redrawing it as required, for example when a virtual keyboard is displayed. Note that the CLS command (used to clear the screen) will automatically set any GUI controls on the screen to hidden (ie, it does a GUI HIDE ALL before clearing the screen). The main problem with mixing basic graphics and GUI controls occurs with the Text Box and Number Box controls which display a virtual keyboard. This can erase any basic graphics and MMBasic will not know to restore them when the keyboard is removed.[/Quote] I encourage you to read and re-read the 'Advanced Graphics Programming Techniques' section of the Micromite Advanced manual starting at page 35, until you understand all the important points made in that section. They really are important, so as to save you mental stress with GUI programming. Put simply, if you use ANY of the GUI controls, then EVERYTHING you see on the screen should be a GUI control, and not a mix of GUI controls and standard drawing commands. Smoke makes things work. When the smoke gets out, it stops! |
||||
| disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 1044 |
This from the MM+ manual page 40 might provide an answer. When you use a CLS to erase the schematic it is also hiding the controls on all the currently selected pages. This hide of the controls on page 9 would still be in effect when page 9 is re-selected as part of the main screen. The command GUI SHOW ALL could be used after the CLS to undo the unintended HIDE of the controls. You could also draw a full size BOX the background colour instead of using CLS. Note that the CLS command (used to clear the screen) will automatically set any GUI controls on the screen to hidden (ie, it does a GUI HIDE ALL before clearing the screen). F4 H7FotSF4xGT |
||||
| panky Guru Joined: 02/10/2012 Location: AustraliaPosts: 1116 |
Another option is to create a GUI SETUP that just has a black on black displaybox the full dimensions of the screen then create a subroutine that re-draws all you non GUI display and optionally, waits on a touch flag to exit.. In your main loop where you detect touches, on selection of the non GUI display, set the page that has the black on black displaybox, call your display-non-gui sub to draw all the non GUI stuff and exit when the touch flag is set. You can finish up by selecting the black on black page setup and assigning a null ("") to the displaybox which will then wipe out all your non-GUI stuff on the display. Finally, switch back to your GUI menu page. panky. ... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it! |
||||
| CaptainBoing Guru Joined: 07/09/2016 Location: United KingdomPosts: 2171 |
As an aside here. This is an example of why you should consider a state machine for your code... you have so many things firing in the background and doing stuff it makes it difficult to debug. With FSM, any interrupt simply sets a flag to record that it happened. The main thread does the actual work (by checking if a flag is set) and so you know exactly what is in charge of what - and more importantly when. |
||||
| PhilTilson Newbie Joined: 15/11/2015 Location: United KingdomPosts: 35 |
Many thanks to all who have replied. The problem is now solved. The main point I had failed to appreciate was the one raised by Disco - that CLS hides the controls! I also take Grogster's point about mixing GUI and text on the page. Unfortunately, I can't see a way round it for my requirement. The only way I can get the animated display is to create a font and 'write text' to the screen continuously. But I need the GUI elements for other things, so... I suppose I could use bit blitting - but I never really got the hang of that even when I was programming 8080 processors in the late 1970s! |
||||
| KeepIS Guru Joined: 13/10/2014 Location: AustraliaPosts: 1945 |
I agree there are times when you have to use Text writes for speed as GUI text elements are too slow in some projects. I agree with CaptainBoing and just capture the keypress in a Touch ISR and then handle it in the main loop in a controlled fashion. If for some reason I must use CLS to get rid of a lot of non GUI elements without effecting GUI controls on a Page, I select an "unused" GUI page first: PAGE 6 'not used and I don't even declare it CLS PAGE 1 'GUI page NANO Inverter: Full download - Only Hex Ver 8.1Ks |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |