Shop OBEX P1 Docs P2 Docs Learn Events
Accurate Timekeeping — Parallax Forums

Accurate Timekeeping

SRLMSRLM Posts: 5,045
edited 2009-01-18 05:56 in Propeller 1
Hi,

I'm working on a clock project, and I'm looking for input on the execution of spin code. I wrote the bit of code below, and it's launched into a new cog and I just read the variables (hour, minute, and second) as needed from other parts of the program. However, I suspect that the spin execution code and the time it takes will be a problem. Even if it misses a single clock cycle every time, that adds up the longer the project runs. I'd like to avoid that if possible. Any ideas on how to make it determinate and execute in constant time?

PUB Clock
  repeat
    repeat until hour => 12 'hour
      repeat until minute => 60 'min
        repeat until second => 60 'sec
          waitcnt(clkfreq + cnt)
          second++
        second := 0
        minute++
      minute := 0
      hour++
    hour := 0




Thanks!

Comments

  • KyeKye Posts: 2,200
    edited 2009-01-17 04:37
    Just use the cnt register and compute your time from that. It will be more accurate than keeping your own clock.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • mirrormirror Posts: 322
    edited 2009-01-17 04:45
    PUB Clock | clk
      clk := cnt
      repeat
        repeat until hour => 12 'hour
          repeat until minute => 60 'min
            repeat until second => 60 'sec
              clk += clkfreq
              waitcnt(clk)
              second++
            second := 0
            minute++
          minute := 0
          hour++
        hour := 0
    
    


    This will be a good start in making your clock as accurate as the crystal.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • SRLMSRLM Posts: 5,045
    edited 2009-01-17 06:05
    Won't the line "clk += clkfreq" take some amount of clock clycles to execute, and therefore throw it off? Then each line that increments a variable would take a little bit of time, along with the waitcnt. So should I have something like this:

    PUB Clock | clk
      clk := cnt
      repeat
        repeat until hour => 12 'hour
          repeat until minute => 60 'min
            repeat until second => 60 'sec
              clk += clkfreq - 12
              waitcnt(clk)
              second++
            second := 0
            minute++
            clk -= 12
          minute := 0
          hour++
          clk -=12
        hour := 0
        clk -= 12
    
    



    But what should I replace 12 with?
  • mirrormirror Posts: 322
    edited 2009-01-17 06:11
    clkfreq is a constant. With a 5 MHz crystal at PLLx16 its value is 80MHz.
    So, every time clk += clkfreq is executed, the value of clk is increased by 80M.
    WaitCnt will wait until the value of CNT = clk.

    There's a good description (including pictures) in the Propeller Manual for WaitCNT.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • SRLMSRLM Posts: 5,045
    edited 2009-01-17 06:28
    The problem (at least the one that I'm seeing [noparse]:)[/noparse] isn't that clkfreq is a constant, it's that the code execution takes time that's not accounted for. For example, inside the second loop are the following values that determine the number of clock cycles that it takes to execute.

    Repeat command with variable comparison (? number of clock cycles)
    addition and subtraction, assignment (? number of clock cycles)
    waitcnt command execution (? of clock cycles)
    clkfreq constant (clkfreq number of clock cycles)
    increment operator (? number of clock cycles)

    I can infer that the there must be at least clkfreq number of cycles in the above command, and some number more to execute all the other commands. My question is: how do I get that number, and make it stay the same every time?
  • mctriviamctrivia Posts: 3,772
    edited 2009-01-17 06:42
    yes the command takes time. no you do not need to account for it. by subtracting 12 you will make your clock run slightly fast. since no longer how long it takes to run your code(assuming it takes less then 80,000,000 cycles it will wait until the last time used +80,000,000 not the current time so your code will start exactly 1sec apart each time.
  • SRLMSRLM Posts: 5,045
    edited 2009-01-17 06:46
    Seems I was a bit hasty... All it took was a shove (a hard one, too!) to the waitcnt manual page, and lo and behold, a whole section on constant time. Also, it took a slightly different frame of thought.

    PUB Clock | currentClk
      
      currentClk := cnt
      repeat
        waitcnt(currentClk += clkfreq)
        second++
        fixMainClock
    
    



    The method fixMainClock is simply a method that rolls the numbers over so I don't get 60 seconds displayed. Thanks for all the help! [noparse]:)[/noparse]
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-01-17 08:10
    How about using the timer-object from the obex

    it's always a good thing to make a quick search with some keywords in the obex

    Anyway by creating methods on your own you have learned a lot about the use of the systemcounter

    best regards

    Stefan
  • SRLMSRLM Posts: 5,045
    edited 2009-01-17 17:04
    From what I can tell, the timer object doesn't take into account code execution time. It also has some weird variable: tix and TIX_DLY...
  • edited 2009-01-18 05:56
    For examples of timekeeping without losing clock cycles, see Propeller Education Kit Labs: Fundamentals page 62.

    http://www.parallax.com/Portals/0/Downloads/docs/prod/prop/Web-PELabsFunBook-v1.0.pdf·(6.93 MB)

    Full text and source code is available from: www.parallax.com -> Propeller -> Downloads & Articles

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andy Lindsay

    Education Department
    Parallax, Inc.

    Post Edited (Andy Lindsay (Parallax)) : 1/18/2009 6:03:34 AM GMT
Sign In or Register to comment.