Shop OBEX P1 Docs P2 Docs Learn Events
Menu timout — Parallax Forums

Menu timout

TCTC Posts: 1,019
edited 2017-03-30 13:18 in Propeller 1
Hello all,

I am working on a menu for a propeller project. But I am having trouble getting a menu timeout to work correctly. It will work sometimes, but then there are times where it will timeout way to fast. I have the timeout set for about 10-ish seconds. The timeout will reset when an encoder is turned. but there are times it will timeout in a second or less. Could someone please help me out with this problem? Here is what I am doing now. One thing the code cant do is pause (no "waitcnt").

Thanks
TC
var
  long  TimeOut
  long  MenuMaxTimeOut
  long  EncoderValue
  long  EncoderPos(2)

OBJ
  encoder  :  "Quadrature_Encoder" 

PRI
  MenuMaxTimeOut := clkfreq * 10 - 3016
  TimeOut := cnt
  repeat
    read_encoder
    "SOME CODE"
    if cnt > TimeOut + MenuMaxTimeOut
      "GOTO ANOTHER MENU SCREEN"

PRI read_encoder | temp
  temp := EncoderValue + encoder.ReadDelta(0)
  if temp <> EncoderValue
    TimeOut := cnt
  EncoderValue := temp

Comments

  • kwinnkwinn Posts: 8,697
    The problem is with the rollover of the "cnt" or "TimeOut + MenuMaxTimeOut" from $FFFFFFFF to $00000000.

    Simpler to change the "repeat" to a "repeat until" or similar.
  • TCTC Posts: 1,019
    kwinn wrote: »
    The problem is with the rollover of the "cnt" or "TimeOut + MenuMaxTimeOut" from $FFFFFFFF to $00000000.

    Simpler to change the "repeat" to a "repeat until" or similar.

    That was my first attempt, but the menus have different things in them. So one menu would be the correct time, while others would be a lot faster. That is when I thought of keeping track of the "cnt" counter. That way, no matter how long or short the menu is, the timeout would be about the same.
  • max72max72 Posts: 1,155
    you could also switch the test:
    if cnt - timeout > menumaxtimeout
    

    I usually test it with a small range.

    Consider your cnt can span from -3 to +3

    menumaxtimeout is 3

    cnt rolls over (after 3 it becomes -3 and starts over)

    If timeout is 2 adding menumaxtimeout you get -2
    you check if cnt > -2, and if you just read timeout you are +3 and you get the shorter timeout

    If you test the difference, cnt is +3 and timeout is +2, cnt - timeout = 1 so the test fails.

    If cnt is -3 (roll over) cnt - timeout is 2 so you avoid the rollover trap.

    Not sure if it is clear..
    Massimo




  • kwinnkwinn Posts: 8,697
    Not clear on what you mean. Does the "SOME CODE" section take you to different menus based on the encoder reading?
  • TCTC Posts: 1,019
    max72 wrote: »
    you could also switch the test:
    if cnt - timeout > menumaxtimeout
    

    I usually test it with a small range.

    Consider your cnt can span from -3 to +3

    menumaxtimeout is 3

    cnt rolls over (after 3 it becomes -3 and starts over)

    If timeout is 2 adding menumaxtimeout you get -2
    you check if cnt > -2, and if you just read timeout you are +3 and you get the shorter timeout

    If you test the difference, cnt is +3 and timeout is +2, cnt - timeout = 1 so the test fails.

    If cnt is -3 (roll over) cnt - timeout is 2 so you avoid the rollover trap.

    Not sure if it is clear..
    Massimo

    I do understand it. It makes sense. I was thinking of it all wrong. Thanks.

    kwinn wrote: »
    Not clear on what you mean. Does the "SOME CODE" section take you to different menus based on the encoder reading?

    The "SOME CODE" is writing all the text to the display, monitor the encoder select button, and change the screen to match what the encoder is doing. Like highlighting "YES", "NO", "MAYBE", etc... with every click of the encoder. I did not want to post the full code since there is a lot there.

  • JonnyMacJonnyMac Posts: 9,104
    edited 2017-03-31 00:09
    If you have a spare cog, you could add this at the bottom of your listing
    var
    
      long  bstack[16]
      long  millis
    
    
    pri background | t
    
      t := cnt
      repeat
        waitcnt(t += MS_001)
        ++millis
    
    The only thing I like about the Arduino is the millis() function -- this does the same thing except that millis is a global variable and you can change it from any cog that knows where millis is.

    When the encoder changes, do this:
      millis := 0
    
    To check for a time-out:
      if (millis => 10_000)
        time_out_repsonse
    
    If you don't want to disturb millis you can using like the cnt register:
      t0 := millis
    
    then...
      if ((millis - t0) => 10_000)
        time_out_repsonse
    
    You can do a lot of work in 1ms. I have a background cog that runs millis, a game timer, reads two shift-registers, plays monotonic music, and debounces a couple of direct inputs -- and I still have time leftover. You'll want to make a bigger stack when you start adding more "background" processes.
  • jonnymac wrote: >>
    var
    
      long  bstack[16]
      long  millis
    
    
    pri background | t
    
      t := cnt
      repeat
        waitcnt(t += MS_001)
        ++millis
    

    In JonnyMac's code suggestion (see above), the MS_001 constant should/can be defined as:
    CON
      _clkmode = xtal1 + pll16x                                     
      _xinfreq = 5_000_000                                          ' use 5MHz crystal
    
      CLK_FREQ = (_clkmode >> 6) * _xinfreq                         ' system freq as a constant
      MS_001   = CLK_FREQ / 1_000                                   ' ticks in 1ms
      US_001   = CLK_FREQ / 1_000_000                               ' ticks in 1us
    

Sign In or Register to comment.