Shop OBEX P1 Docs P2 Docs Learn Events
If Thens getting stuck behind waitcnts — Parallax Forums

If Thens getting stuck behind waitcnts

mattbutskomattbutsko Posts: 8
edited 2011-10-11 19:07 in Propeller 1
So I'm still working on that clock, and it's really coming along, but I've got a slight problem. I enabled two buttons that change the hours and minutes. Problem is, in order to make the time change slow enough, I have to add to waitcnt commands inside the buttons' IFs. This causes the limiter if blocks to get stalled, which allows 13 to be seen briefly before changing to 1. (the limiter checks to see if the clock is displaying 13:00 and changes it to display 1:00 instead.) Since it get's stuck behind the "waitcnt(clkfreq/3 + cnt)", you still see 13:00 for a third of a second before it changes over to 1:00.

Is there any way I can run the checkers without them getting delayed? Preferably without launching a new cog altogether? Thanks for looking.
PUB changetime
 dira[24..25] := %00
 repeat
  if ina[25] == 1
      hours01 +=1
      waitcnt(clkfreq/3 + cnt) 
  if ina[24] == 1
      minutes01 +=1
      waitcnt(clkfreq/5 + cnt)     
  if minutes01 == 10
        minutes10+=1
        minutes01 := 0
  if minutes10 == 6                
        minutes10 := 0                  
  if hours01 == 10
        hours01 := 0
        hours10+=1 
  if hours10 == 1                 ' Keeps the time from going past 12 o'clock
      if hours01 == 3
        hours10 := 0
        hours01 := 1 

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-10-06 10:37
    Instead of incrementing the minutes or hours first, then checking for special cases, you need to combine the two so there's never an invalid time like:
    if hours01 == 9
       hours01~
       hours10++
    elseif hours10 == 1 and hours01 == 2
       hours10~
       hours01 := 1
    else
       hours01++
    
    You'd do the same sort of thing for the minutes.

    Note: I assume that you've got some other cog that's continually updating the display from the hours10, hours01, etc. variables. There's still a very short window between the changes to each of the two digits where the display cog may briefly flash the wrong digit combination sometimes. This is where the semaphores (lockXXX statements) are intended to be used. Another option is to store all the 4 digits in one long and update it all at once. That way the display cog will only see correct digit combinations since the whole long is updated in a single operation.
  • JonnyMacJonnyMac Posts: 9,202
    edited 2011-10-06 10:42
    I'm not sure how you're using this method, but here's a different whack at it
    pub change_time
    
      dira[HR_BTN..MN_BTN] := %00                                   ' force to inputs
    
      repeat
        if ina[HR_BTN..MN_BTN] == %00                               ' no press
          quit
    
        if ina[HR_BTN]
          hours += 1
          if (hours == 13)                                          ' keep 1 to 12
            hours := 1
    
        elseif ina[MN_BTN]
          minutes := minutes + 1 // 60                              ' keep 0 to 59
    
        waitcnt(clkfreq / 3 + cnt)                                  ' wait 1/3s
    
  • frank freedmanfrank freedman Posts: 1,983
    edited 2011-10-06 12:24
    Are you using the waitcnt as a debounce method? If so, considering a)moving the waitcnt up one spot to below the if statement, and b)after doing the wait, check to see if it is really a switch press. Then do the h/m increments with either a precheck to see if you are at the upper limit before incrementing the value (IMHO better way) or test for upper limit exceeded and then in either case, roll over to min value. Otherwise fall through to just increment to next value.

    Just thoughts,

    Frank
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-10-06 19:44
    Here's how I would do the waiting - make it based on a counter, so you can wait in little bits at a time while still allowing the rest of the routine to run and update:
    PUB changetime | waitCtr
     dira[24..25] := %00
     waitCtr := 0
    
     repeat
      if( ina[24..25] <> 0 )
        if( waitCtr == 0 )
          if ina[25] == 1
              hours01 += 1
              waitCtr := 100
          if ina[24] == 1
              minutes01 +=1
              waitCtr := 100
        else
          waitCtr -= 1
          waitcnt( clkfrq/1000 + cnt )
    
      if minutes01 == 10
            minutes10+=1
            minutes01 := 0
      if minutes10 == 6                
            minutes10 := 0                  
      if hours01 == 10
            hours01 := 0
            hours10+=1 
      if hours10 == 1                 ' Keeps the time from going past 12 o'clock
          if hours01 == 3
            hours10 := 0
            hours01 := 1
    

    In addition, if you use a single minute value and hour value, you could do your increments like this:
      minute += 1
      if( minute > 59 )
        minute := 0
        hour := (hour + 1) // 12   {use the modulo operation to limit from 0 to 11, instead of 1 to 12}
    
      {now extract the 1's and 10's for minute and hour digits}
      minute01 := minute // 10
      minute10 := minute / 10
    
      hour01 := (hour+1) // 10
      hour10 := (hour+1) hour / 10
    

    That way you only have to handle a single roll-over. The modulo operation (which I *think* is //) returns the remainder of a division. So, 62 modulo 60 is 2, 14 modulo 10 is 4, and so on. By keeping the "hour" value from 0 to 11 you can use the modulo operation to handle wrapping it around instead of using an if statement.
  • mattbutskomattbutsko Posts: 8
    edited 2011-10-11 19:07
    Hey thanks for the pointers. I've reworked the method and I no longer have the issue, thansk for the help, you were all pretty much spot on.
Sign In or Register to comment.