Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 17:15 12 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : How to clear graphics from screen

Author Message
PhilTilson
Newbie

Joined: 15/11/2015
Location: United Kingdom
Posts: 35
Posted: 10:51pm 22 Feb 2019
Copy link to clipboard 
Print this post

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: Australia
Posts: 1044
Posted: 11:48pm 22 Feb 2019
Copy link to clipboard 
Print this post

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.


Edited by disco4now 2019-02-24
F4 H7FotSF4xGT
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 07:09am 23 Feb 2019
Copy link to clipboard 
Print this post

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:

  Quote   PAGE 7,11,12 'Edit Database, final confirmation, EXIT/DELETE/SAVE buttons
GUI Interrupt EXIT_DELETE_SAVE
Timer=0
Do
If LCD_EXIT then
LCD_EXIT=
0
If DEBUG then print "EXIT button touched.(write new entry)"
Y=
1
EXIT Do
ENDIF
If LCD_SAVE then
LCD_SAVE=
0
If DEBUG then print "OK button touched.(write new entry)"
SYSMSG$=
"WRITE FILE: "+INDEX$+" - "+NME$+", "+NUM$+" "+AREA$
If DEBUG then print SYSMSG$
If SYSLOG then WRITE_SYSLOG(SYSMSG$)
CTRLVAL(ADWI)=
"SAVING..." 'Wait caption for PAGE 3 on next line
PAGE 3 'Show wait message while file is written to card
CHDIR "\DATABASE"
Open INDEX$ for Output as #4
print #4,NME$
print #4,NUM$" "+AREA$
Close #4
Y=
1
EXIT Do
ENDIF
If LCD_DELETE then
LCD_DELETE=
0
PAGE
7,5,4 'Edit Database, Confirm, EXIT/OK buttons
GUI Interrupt EXIT_OK
Do
If LCD_EXIT then
LCD_EXIT=
0
If DEBUG then print "EXIT button touched.(delete entry)"
Y=
1
EXIT Do
ENDIF
If LCD_OK then
LCD_OK=
0
If DEBUG then print "OK button touched.(delete entry)"
CTRLVAL(ADWI)=
"DELETE ENTRY..."
PAGE
3
CHDIR
"\DATABASE"
On Error Skip
KILL INDEX$
If MM.ERRNO then WRITE_ERRLOG("Atempt to delete non-existant entry - "+INDEX$)
SYSMSG$=
"Entry DELETED - "+INDEX$
If DEBUG then print SYSMSG$
If SYSLOG then WRITE_SYSLOG(SYSMSG$)
Y=
1
EXIT Do
ENDIF
If Timer>=SSDELAY*2 then Y=1
If Y then EXIT Do
LOOP
ENDIF
If Timer>=SSDELAY*2 then Y=1
If Y then EXIT Do
LOOP
On Y GOTO START


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:

  Quote  Sub EXIT_DELETE_SAVE 'Touch interrupt for database editor buttons
LCD_EXIT=0:LCD_DELETE=0:LCD_SAVE=0
Select Case Touch(REF)
Case BU_DB_EXIT
LCD_EXIT=
1
Case BU_DB_DELETE
LCD_DELETE=
1
Case BU_DB_SAVE
LCD_SAVE=
1
End Select
End Sub



...and the EXIT_OK buttons on any page interrupt is:
  Quote  Sub EXIT_OK 'Touch interrupt for EXIT and OK buttons on any page
LCD_EXIT=0:LCD_OK=0
Select Case Touch(REF)
Case BU_EXIT
LCD_EXIT=
1
Case BU_OK
LCD_OK=
1
End Select
End Sub



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. Edited by Grogster 2019-02-24
Smoke makes things work. When the smoke gets out, it stops!
 
PhilTilson
Newbie

Joined: 15/11/2015
Location: United Kingdom
Posts: 35
Posted: 11:08am 23 Feb 2019
Copy link to clipboard 
Print this post

Thanks for those thoughts. I will make some modifications and let you know what happens!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 11:18am 23 Feb 2019
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 35
Posted: 03:47pm 23 Feb 2019
Copy link to clipboard 
Print this post

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: Australia
Posts: 1646
Posted: 12:36am 24 Feb 2019
Copy link to clipboard 
Print this post

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 Zealand
Posts: 9755
Posted: 02:06am 24 Feb 2019
Copy link to clipboard 
Print this post

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.Edited by Grogster 2019-02-25
Smoke makes things work. When the smoke gets out, it stops!
 
disco4now

Guru

Joined: 18/12/2014
Location: Australia
Posts: 1044
Posted: 02:30am 24 Feb 2019
Copy link to clipboard 
Print this post

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: Australia
Posts: 1116
Posted: 06:23am 24 Feb 2019
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2171
Posted: 10:38am 24 Feb 2019
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 35
Posted: 12:35pm 24 Feb 2019
Copy link to clipboard 
Print this post

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: Australia
Posts: 1945
Posted: 10:28pm 24 Feb 2019
Copy link to clipboard 
Print this post

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


Edited by KeepIS 2019-02-26
NANO Inverter: Full download - Only Hex Ver 8.1Ks
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025