Shop OBEX P1 Docs P2 Docs Learn Events
Small Program Problem — Parallax Forums

Small Program Problem

NewzedNewzed Posts: 2,503
edited 2007-10-11 13:09 in Propeller 1
I have a program for the DS1307 and the MCP3004 which is working fine.· When I start the program, the VGA displays the current time and then the Menu.· It then goes to my Getchoice method where it waits for me to select an option by pressing one of 7 keys.· Each time I select an option, the time is again displayed when the selected instruction has been completed.

I would like to insert an instruction at the beginning of the Getchoice routine that says:

"if no key is pressed within 30 seconds go to menu"

The problem is I don't know how to write that in SPIN.

Any suggestions?

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
·
«1

Comments

  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-10-05 15:06
    Don't you just use the relevant function in the vga object you are using? For example in the graphics object there is a text function as used in the demo.

    Graham
  • RaymanRayman Posts: 14,162
    edited 2007-10-05 15:31
    I'd just save the current CNT before entering a wait loop that keeps polling the keyboard until the current CNT equals original plus 30 seconds.
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-05 17:09
    Note that CNT aliases within 40 seconds @ 80MHz. It is best to implement an independant clock. Pefect if you can spend a COG for it. Ariba made a most ingenious suggestion some weeks ago using two unused counters for a true hardware clock precisely running for days!
  • RaymanRayman Posts: 14,162
    edited 2007-10-05 17:26
    What? It takes CNT ~54 seconds to roll over at 80 MHz...
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-05 17:39
    Don't split hairs smile.gif
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-10-05 19:45
    Well I'm confused, I can't imagine Sid not knowing how to do either part, the timing or the display, perhaps its the concept of a time out that's the trouble.

    As I've said before "you can do it!"

    Graham
  • NewzedNewzed Posts: 2,503
    edited 2007-10-05 20:06
    I have no problem with cnto := cnt.· I use it extensively in my timing applications.

    I·can make the VGA redisplay with the new current time every 5, or 10, or 30 or whatever.· What I can not do is "interrupt" the waitcnt statement with a keypress that will execute the desired option.· I even used a
    "if key.gotkey" statement after the waitcnt but the program did not execute it.· So that is my problem.· Now.....any new suggestions?

    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
    ·
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-05 20:10
    Dont "wait" at all!
    Just loop until the CNT you are waiting for goes by....
    And call key.gotkey in that loop.

    Note: Don't use something as " > CNT" or so to end the loop ... This is the tricky part smile.gifsmile.gif
  • NewzedNewzed Posts: 2,503
    edited 2007-10-05 20:25
    deSilva, I wrote:

    ·· key.clearkeys
    ·· repeat
    ···· waitcnt(clkfreq*10 + cnto)
    ···· if key.gotkey
    ······ cmds
    ···· menu
    ·······
    PUB cmds
    ·· cmd := key.gotkey··
    ·· if cmd == "a"
    ···· alarm
    ···· (and so on)

    The VGA redisplays every 10 seconds - that's fine - but, if I press a key during the waitcnt, the program ignores the "if key.gotkey".· What I want to happen is that the VGA will redisplay every 10 seconds, but if I press a key - and it may be 30 minutes later - I want the program to interrupt the waitcnt statement, or, failing that, wait until the waitcnt statement is completed, then go to the option I want.· I don;'t seem to be able to do that.

    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
    ·
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-05 20:28
    As Graham, I have full trust that you can manage it. Just follow my advice and replace the WAITCNT by a SPIN loop....
  • Graham StablerGraham Stabler Posts: 2,507
    edited 2007-10-05 20:44
    yep you are basically creating your own command called waitcntunlesssomeonepressesakey
  • NewzedNewzed Posts: 2,503
    edited 2007-10-05 21:07
    Got it!!· I wrote:

    ·· cnto := cnt
    ·· key.clearkeys
    ·· repeat
    ···· repeat 1
    ······ waitcnt(clkfreq*5 + cnto)
    ···· if key.gotkey
    ······ cmds
    ···· repeat 1
    ······ waitcnt(clkfreq*10 + cnto)
    ···· if key.gotkey
    ······ cmds
    ···· menu
    ·······
    PUB cmds
    ·· cmd := key.getkey··
    ·· if cmd == "a"
    ···· alarm
    ·· if cmd == "s"
    ···· setclock

    Works just fine.· When I press a key I have to wait for the active waitcnt to complete but that is not a problem.· If necessary, I can change the waitcnt statement toi a smaller value, then just increase the number of iterations until I get the time I want.

    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 StablerGraham Stabler Posts: 2,507
    edited 2007-10-06 00:32
    Why not take Desilva's advice its just a matter of looping until either (cnt == clkfreq*5 + cnto) or a key is pressed then the response is instant, using waitcnt doesn't make sense.

    Graham
  • NewzedNewzed Posts: 2,503
    edited 2007-10-06 12:05
    Graham, could you write that loop for me? I can't seem to get it right.

    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
    ·
  • NewzedNewzed Posts: 2,503
    edited 2007-10-06 13:41
    Never mind, Graham.· I finally worked it out.

    I had written:

    ·· repeat
    ···· if cnt·== cnto + clkfreq*5
    ······ menu
    ···· if key.gotkey
    ······ cmds

    The program would respond to a keypress but it would never go to menu.· I finally realized that "if cnt·== cnto + clkfreq*5·" was the problem.· The chnces of cnt precisely equalling cnto + clkfreq*5 were extremely remote, so I gave it a windown and wrote:

    · repeat
    ···· if cnt·=> cnto + clkfreq*5·amd cnt<clkfreq*6
    ······ menu
    ···· if key.gotkey
    ······ cmds

    Now it works, but this creates another problem.· After about 45 or 46 iterations the screen starts garbling a bit - I get rows of dots and the letters become distorted, then the screen goes to a multicolored display and locks up.· I have to reset to continue.· I think the stack that holds the return· markers is overflowing and locking up the program.· Any idea how to fix that?· It occurred to me that if I could have the program automatically reset itself every 35 or so iterations that would solve the problem, sort of.··I think the state and direction of Pin 10 - Resn - is input high.· Suppose I connect Pin X to Pin 10 and set it to:

    dira[noparse][[/noparse]X] := 0
    outa[noparse][[/noparse]X] := 1

    Then I write:

    if y == 35······ (y is my counter)
    · dira[noparse][[/noparse]X] := 1
    · outa[noparse][[/noparse]X] := 0
    · waitcnt(clkfreq/1000 + cnt)
    · dira[noparse][[/noparse]X := 0
    · outa[noparse][[/noparse]X] := 1

    Would that not reset the Propeller?

    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
    ·
  • RaymanRayman Posts: 14,162
    edited 2007-10-06 13:46
    Maybe something along these lines would work:

    cnto := cnt
    dt:=0
    key.clearkeys
    repeat until (dt>clkfreq*5)
    dt:=cnt-cnt0
    if (key.gotkey)
    quit
    if (key.gotkey)
    cmds
    menu
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-06 13:56
    Newzed;
    (a) This here makes little sense
    if cnt => cnto + clkfreq*5 amd cnt<clkfreq*6
    

    even when i substitute AND for "amd". The main problem is, when you do not post an exact copy of your code, the tiny mistake responsible for your problems can never be spotted!

    (b) Consider that CNT wil run up to POSX and then from NEGX downto zero again. That is why I called it "the tricky thing"... The < and > Operations however work in "signed" mode. But is is feasible after a little bit thinking...

    (c) Never - I repeat NEVER - accept a not understood program behavior and "work around". You can "work around" when ypou have understood the problem. So there is no reason why a stack should overflow or whatever. LOOK FOR the real cause!!

    (d) There is a special instruction to reset the Prop from program code (REBOOT)
  • NewzedNewzed Posts: 2,503
    edited 2007-10-06 15:06
    deSilva, thanks for the REBOOT tip - it works fine and gives me a temporary workaround.

    I am not an expert programmer.· In fact, I'm not even a very good programmer.· I wouldn't have a clue where look to find the problem that occurs after 45 or so iterations.· In case you have the time to look, I have attached a copy of my program.

    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
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-06 15:34
    It is quite complex code, but it sems you keep calling "menu" form the most obscure places, adding stack layer to stack layer. So it collapses after some 40 or fifty "menu" have ben allocated to the stack... You must RETURN from those calls!

    Have a look into a somewhat obscure feature of SPIN called "aborting"....
  • NewzedNewzed Posts: 2,503
    edited 2007-10-06 21:10
    deSilva, if I wrote "return menu" instead of "menu" would that alleviate the problem?

    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
    ·
  • deSilvadeSilva Posts: 2,967
    edited 2007-10-06 21:17
    Probably not, as the "menu" itself will not return in the first place. Just go through your code with a piece of paper and a pencil and draw how (and when) your stack is growing:
    (1) initialize
    (2) start
    (3) iI2cScan -- returns
    (3) menu
    (4) readclock2
    (5) menu1


    etc. etc.

    Post Edited (deSilva) : 10/6/2007 9:22:00 PM GMT
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-06 22:34
    I don't see what the problem is here. You have a thirty second timer. If it counts down, you do the main menu routine. If a keypress is detected (something gets to buffer),
    you reset the timer. You test the character for validity. If it's bad, you throw it away. If it's a menu call, you execute the appropriate item.

    Seems like a straightforward case construct to me, where exceeding the timer is one of the cases.
  • NewzedNewzed Posts: 2,503
    edited 2007-10-06 22:48
    The problem is I have two "if" statements.· I have to tell each where where to go·in case ·the statement is true.· After about 40 iterations I run out of call stack space and the program locks up.· So far I have not been able to find a way to avoid the lockup.

    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
    ·
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-06 23:31
    Still don't see why you run out of stack space. It looks like this to me:
    487 x 631 - 5K
  • NewzedNewzed Posts: 2,503
    edited 2007-10-07 14:17
    I finally found the problem - it is memory.· I remembered a similar problen from some time ago.· When I compiled the original program, the screen said I had 3080 free longs.· i went thru the program and shortened it as much as I could, then recompiled.· The screen said I now had 3274 free longs.· I ran the program again and this time I was able to get 69 iterations before the program locked up instead of 40.· I'll review the program again but there is only so much I can shorten it and still have it operate properly.· When I have done that, I'll just set my counter to reboot at an appropriate point.· As far as I can see, there is no other alternative.

    Now......can anyone explain why this happens when the screen said I have 3080 free longs?

    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
    ·
  • Stan671Stan671 Posts: 103
    edited 2007-10-07 19:56
    deSilva said...
    It is quite complex code, but it sems you keep calling "menu" form the most obscure places, adding stack layer to stack layer. So it collapses after some 40 or fifty "menu" have ben allocated to the stack... You must RETURN from those calls!
    Sid, what deSilva is saying here is that you have·methods calling other methods that then execute the original·method again.· So, the Prop is running around in circles, never actually finishing a method·and releasing the stack space.

    For example, The MENU·method calls READCLOCK2 which calls MENU1 when in turn calls MENU again.· Or READCLOCK2 calls CMDS which calls MENU again.· You have a child·method calling it's own parent.· This creates a circular reference that never ends - until the Prop crashes because it runs out of stack space.

    Make a chart·with all of your methods listed.· Now draw arrows from each method to all of the other methods it executes.· It should become clear from the arrows that you have certain situations where execution will travel around in a circle back to a method that is already running.

    Fixing this is not a case of adding a few RETURN commands.· You need to rethink the structure and hierarchy of your methods so that there are no circles.· You cannot end all of your child methods by calling MENU.· You have to let the child method finish and return back to its parent.

    It is not a memory size (free space) problem.· The amount of free space just determines how long you can go before crashing.· You have to stop the circular references that are eating the memory.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Stan Dobrowski

    Post Edited (Stan671) : 10/7/2007 8:00:58 PM GMT
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-07 20:46
    Thanks Stan, I wondered how we could get here.
  • NewzedNewzed Posts: 2,503
    edited 2007-10-07 22:20
    Stan, the problem is that I want to refresh the screen with the temperature and time every x seconds.· I also want the option of selecting a menu option during x.· To do this I must have two "if' statements, and I have to tell the program where to go in case either "if" statement is true.· You have a copy of my program.· If you can show me how to do this without overflowing the call stack, I'll take my hat off to you.· I'm not a very good programmer, so I did it the only way I could think of.· And please don't tell me to read certain sections of the Propeller Manual.· I am 85 years old and way past my peak of learning.

    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
    ·
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-10-07 23:10
    Taking a look.

    One suggestion, not particularly material but saves space:


    ' Check to see if DS1307 is working 
    if DS1307Object.isStarted == true 
       text.str(string("DS1307 Present",10,13)) 
       waitcnt(clkfreq + cnt)  
       menu 
    else 
       text.str(string("DS1307 Missing",10,13)) 
       waitcnt(clkfreq+cnt) 
       menu 
    
    [b]both sides of the if do the same waitcnt, menu 
    
    factor thus: 
    [/b]
    ' Check to see if DS1307 is working 
    if DS1307Object.isStarted == true 
       text.str(string("DS1307 Present",10,13)) 
    else 
       text.str(string("DS1307 Missing",10,13)) 
    waitcnt(clkfreq+cnt) 
    menu
    

    Post Edited (Fred Hawkins) : 10/7/2007 11:15:38 PM GMT
  • NewzedNewzed Posts: 2,503
    edited 2007-10-07 23:39
    Thanks, Fred.· That saved 2 longs.

    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
    ·
Sign In or Register to comment.