Sid,
I looked your code over. And generally, the critique that you have lower methods calling higher ones (that in turn call the lower ones that call the higher... ad infinitum and then STOP) is correct.
Here's what you should do: In menu, use a repeat until some condition for which you want everything to stop. Then in the lower methods, drop the calls to menu. Just let them come back naturally.
I suggest that you learn the CASE construct which is perfectly suited for sorting out keypresses.
PUB menu ·· text.out(0) ·· text.out(13) ·· key.clearkeys ·· cnto := cnt ·· readadc ·· readclock2 ·· menu1 ·· repeat ···· if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9 ······ waitcnt(clkfreq + cnt) ······ menu ···· if key.gotkey ······ cmds
I am quite familiar with the CASE statement.· However, I have found no particular advantage in using it.· On the couple if times I have checked, it uses the same amount of memory as the comparable "if" statements.
I have noted that sometimes the program will lock up on the repeat statement waiting for:
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9 ······ waitcnt(clkfreq + cnt) ······ menu
to become true.· I have let the program sit and eventually it cycles, taking various times, sometimes a minute, once as long as 5:30.· Admittedly, the "true' window is quite small.· Hopefully this will improve when I got to a 30-second window - I really don't know.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
to become true is a bit annoying.· Is there some way I could set one of the counters, say ctra, to 0 and then have the program refresh when ctra is equal to a pre-defined constat, such as time1 = 400_000_000?
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
Sid, no, you still have the concept all wrong. You have the MENU method calling itself!! And you cannot have MENU call CMDS because CMDS calls MENU.
I just figured out the flaw in your thinking: You are trying to use a call to another method like a GOTO. It is certainly not a GOTO, it is more like a subroutine call. Subroutines cannot call themselves and cannot call other subroutines that call the original caller. Wow, that was even hard to type. <grin>
Stop worrying about saving memory in order to get this to work. The problem is not a shortage of memory. The problem is that your methods (subroutines) are never reaching thier own end and returning to the original caller normally. Therefore your stack goes haywire and crashes your Prop.
And since you are having stack problems, I would not trust any symptoms you see as having any particular meaning. When you stack goes berzerk, lots of wierdness will happen that seems totally unrelated.
I don't want to sound harsh to you, Sid, you but need to get your mind right before you can come close to fixing this program. The problems here are not a simple fix by changing a couple of lines of code. Please re-read my two posts, stare at Fred's spaghetti chart, and repeat to yourself "a method call is not a GOTO" until you have the required epifany.
Sorry, Stan.· I do not know how to do what you are saying.· I have attached a copy of the program I am presently running.· If you have time to fix it, fine.· If not, then I'll just keep on using what I have and reboot every 151 cycles.· I've solved the problem of the program pausing while waiting for
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
to become true.· See Line 153.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
The concept of a method/function is that you call it, some code is executed and then the program returns to the point where the program was called.
So in your menu function it does not make any sense to call menu, it would make more sense to put the contents of menu in one big loop and have the second loop where you are waiting for z== 72_00 to end when z=72_00 (use a repeat until loop) this will automatically loop back around to the start of the code in menu.
pub menu
repeat
some code
some more code
repeat until z == 72000
if key.gotkey
cmds
And then rather than trying to call menu from cmds (because menu is where cmd was called from) do:
if cmd == "f"
return
Just to try and clarify what stan was saying, writing call menu is not the same as writing goto menu if that were possible. When you call a function it executes the code in the function until the end of the function or until a return command, then the program jumps back to where it was called from.
Graham
Post Edited (Graham Stabler) : 10/8/2007 4:46:52 PM GMT
That's correct the alarm function would be called, then it would return back to the cmd function then the cmd function would return to the menu function.
This is what is called program flow, the program flows into a function and then returns back. Unless you are starting a new cog (which allows parallel flows) this is how it always works.
I think you have just got yourself mixed up because you use functions all the time.
Sid,
Take a look at how your initialize routine makes a series of calls (usually masked as assignments). For instance:
long[noparse][[/noparse]ldr#videoPtr] := ldr.allocatePRI(ldr#videoSize) ' Allocate work area for video
Control goes out to the called module's routine (in this example, allocatePRI in OSloader) and comes back. Your own code should do the same -- you call the routine (invoke the name), it finishes, control comes back.
And don't mistake the fact that because initialize is using objects that you loaded (defined) that your own routines are somehow different. Everything is invoked (called) the same way, and returns the same way.
Why would you want to call the function you are already in? That was the point of putting a loop in the function so it automatically repeats when it gets to the end. I gave a very clear example of this.
If you don't want a loop in the function then the call to the function must be in some other loop. Very commonly you will have a function called main which is the main program loop from which various functions are called. So it could be something like this:
pub main
do some initialization
repeat
call a function
menu
pub menu
some code
return
Never mind, Graham - I found the problem.· I was not clearing z to 0.· I added;
z := 0
right after the first repeat and now it is working OK.· I'm running the program to see if it locks up ater X cycles.· It's up to 170 cycles and still going.· I'll let you know if it locks up.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
Graham, it has cycled over 500 times - looks like everything is OK.· Now to·tidy up the program and set the cycle time to what I want.· Thank you very much.· Your very lucid explanation if what I should be doing was invaluable.
Till next time.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
Graham, I tidied up my program - found a few more bad "menu" calls and fixed those.· Started running the program yesterday afternoon on a short refresh cycle, and this morning it has completed over 13,800 consecutive·refreshes.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ Yesterday is history, tomorrow is a mystery, and today is a gift.
Comments
I looked your code over. And generally, the critique that you have lower methods calling higher ones (that in turn call the lower ones that call the higher... ad infinitum and then STOP) is correct.
Here's what you should do: In menu, use a repeat until some condition for which you want everything to stop. Then in the lower methods, drop the calls to menu. Just let them come back naturally.
I suggest that you learn the CASE construct which is perfectly suited for sorting out keypresses.
Fred
PUB menu
·· text.out(0)
·· text.out(13)
·· key.clearkeys
·· cnto := cnt
·· readadc
·· readclock2
·· menu1
·· repeat
···· if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
······ waitcnt(clkfreq + cnt)
······ menu
···· if key.gotkey
······ cmds
I am quite familiar with the CASE statement.· However, I have found no particular advantage in using it.· On the couple if times I have checked, it uses the same amount of memory as the comparable "if" statements.
I have noted that sometimes the program will lock up on the repeat statement waiting for:
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
······ waitcnt(clkfreq + cnt)
······ menu
to become true.· I have let the program sit and eventually it cycles, taking various times, sometimes a minute, once as long as 5:30.· Admittedly, the "true' window is quite small.· Hopefully this will improve when I got to a 30-second window - I really don't know.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
to become true is a bit annoying.· Is there some way I could set one of the counters, say ctra, to 0 and then have the program refresh when ctra is equal to a pre-defined constat, such as time1 = 400_000_000?
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
I just figured out the flaw in your thinking: You are trying to use a call to another method like a GOTO. It is certainly not a GOTO, it is more like a subroutine call. Subroutines cannot call themselves and cannot call other subroutines that call the original caller. Wow, that was even hard to type. <grin>
Stop worrying about saving memory in order to get this to work. The problem is not a shortage of memory. The problem is that your methods (subroutines) are never reaching thier own end and returning to the original caller normally. Therefore your stack goes haywire and crashes your Prop.
And since you are having stack problems, I would not trust any symptoms you see as having any particular meaning. When you stack goes berzerk, lots of wierdness will happen that seems totally unrelated.
I don't want to sound harsh to you, Sid, you but need to get your mind right before you can come close to fixing this program. The problems here are not a simple fix by changing a couple of lines of code. Please re-read my two posts, stare at Fred's spaghetti chart, and repeat to yourself "a method call is not a GOTO" until you have the required epifany.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Stan Dobrowski
if cnt =>cnto + clkfreq*4 and cnt<cnto + clkfreq*9
to become true.· See Line 153.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
So in your menu function it does not make any sense to call menu, it would make more sense to put the contents of menu in one big loop and have the second loop where you are waiting for z== 72_00 to end when z=72_00 (use a repeat until loop) this will automatically loop back around to the start of the code in menu.
And then rather than trying to call menu from cmds (because menu is where cmd was called from) do:
Just to try and clarify what stan was saying, writing call menu is not the same as writing goto menu if that were possible. When you call a function it executes the code in the function until the end of the function or until a return command, then the program jumps back to where it was called from.
Graham
Post Edited (Graham Stabler) : 10/8/2007 4:46:52 PM GMT
if·cmd·==·"f"
···return
Suppose I wanted to do something if cmd == "f", like jump to a method named "alarm".· Would I write:
if·cmd·==·"f"
·· alarm
···return
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
This is what is called program flow, the program flows into a function and then returns back. Unless you are starting a new cog (which allows parallel flows) this is how it always works.
I think you have just got yourself mixed up because you use functions all the time.
Graham
PUB menu
· z := 0
· text.dec(z)
· repeat
··· text.out(0)
··· text.out(13)
··· key.clearkeys
··· y := y + 1
··· text.dec(y)
··· readadc
··· readclock2
··· menu1
··· repeat
····· z := z + 1
····· if key.gotkey
······· cmds
··· until z == 72_000
The program locked up on the second cycle.· Then I wrote:
Pub start1
·· menu
PUB menu
· z := 0
· text.dec(z)
· repeat
··· text.out(0)
··· text.out(13)
··· key.clearkeys
··· y := y + 1
··· text.dec(y)
··· readadc
··· readclock2
··· menu1
··· repeat
····· z := z + 1
····· if key.gotkey
······· cmds
··· until z == 72_000
··· start1
Is that acceptable?
Sid
···
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
Take a look at how your initialize routine makes a series of calls (usually masked as assignments). For instance:
long[noparse][[/noparse]ldr#videoPtr] := ldr.allocatePRI(ldr#videoSize) ' Allocate work area for video
Control goes out to the called module's routine (in this example, allocatePRI in OSloader) and comes back. Your own code should do the same -- you call the routine (invoke the name), it finishes, control comes back.
And don't mistake the fact that because initialize is using objects that you loaded (defined) that your own routines are somehow different. Everything is invoked (called) the same way, and returns the same way.
Fred
Why would you want to call the function you are already in? That was the point of putting a loop in the function so it automatically repeats when it gets to the end. I gave a very clear example of this.
If you don't want a loop in the function then the call to the function must be in some other loop. Very commonly you will have a function called main which is the main program loop from which various functions are called. So it could be something like this:
Graham
PUB menu
· z := 0
· text.dec(z)
· repeat
··· text.out(0)
··· text.out(13)
··· key.clearkeys
··· y := y + 1
··· text.dec(y)
··· readadc
··· readclock2
··· menu1
··· repeat· until z == 72_000···
····· z := z + 1
····· if key.gotkey
······· cmds
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
z := 0
right after the first repeat and now it is working OK.· I'm running the program to see if it locks up ater X cycles.· It's up to 170 cycles and still going.· I'll let you know if it locks up.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
Graham
Graham
Till next time.
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·
I'd like to see your new code to compare with the old.
Fred
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
Going back to your original problem what you could do is make the time out period a multiple of the refresh time
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Yesterday is history, tomorrow is a mystery, and today is a gift.
That is why they call it the present.
Don't have VGA?
Newzed@aol.com
·