Shop OBEX P1 Docs P2 Docs Learn Events
Odd delay behaviour — Parallax Forums

Odd delay behaviour

kenmackenmac Posts: 96
edited 2007-08-24 11:01 in Propeller 1
Hi folks,
I have run into an odd ocurrence when using a calculated delay.
The following is a simple example:
con
  _clkmode = xtal1 
  _clkfreq = 5_000_000

pub start
  dira[noparse][[/noparse]16]~~
  uSdelay(10)                      ' 10uS delay
  outa[noparse][[/noparse]16]~~
  repeat


pub uSdelay(DelayuS)            'Delay for # of microseconds
  waitcnt(((clkfreq/1_000_000) * DelayuS) + cnt)



With the code shown above, the LED on Pin 16 never turns on.
If I change the value upwards from the (10) it only comes on when the parameter = 77.
If I replace the calculated delay with a straight forward absolute delay, there is no problem at all.

Comment?

I'm using the Propstick.

kenmac

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Perth, Western Australia
Time Zone = GMT + 8

Comments

  • deSilvadeSilva Posts: 2,967
    edited 2007-08-23 07:32
    This is EXACTLY as it has to be (though I do not believe the last statement of your posting. smile.gif )

    You clock your Prop with 5 MHz (PLL1X), which means that the most simple SPIN instruction needs around 80 mys (it needs around 5 us with 80 MHz)
    So you have no chance to wait for less!

    As you say 77 us does fine, you have exactly meassured, what the second part of WAITCOUNT (i.e. WITHOUT the division, which will take YEARS) takes.

    When you want to say only 770 us works fine, then the division is added to the instruction time, which however is against common knowledge, as this is why you write ... + CNT rather than CNT+... to avoid this.

    And the LED will OF COURSE shine, but only after 16*23 = 368 seconds. The young persons are sooo impatient these days ....

    Post Edited (deSilva) : 8/23/2007 6:19:27 PM GMT
  • KaioKaio Posts: 253
    edited 2007-08-23 10:00
    kenmac,

    you are not setting right the clock to use. It should look like the following for maximum speed.
    _clkmode = xtal1 + pll16x
    
    
  • kenmackenmac Posts: 96
    edited 2007-08-23 10:52
    OK, this started when I was trying the PE-Lab/Counters/RC Timer program.

    It uses the following code[noparse]:([/noparse]Clk = 80mHz)

    waitcnt(clkfreq/100_000 + cnt)
    



    which is supposed to be 10uS. (It eventually exits after 53 seconds!)

    It sets the time of charging the capacitor, which really doesn't require much time at all.
    When running the code, it didn't seem to exit this timer and thus I started to investigate.
    I tried the uSdelay method, which just happened to be listed in the same Object, but it didn't work either.

    That's when I asked the questions in this thread.
    Unfortunately, I used a 5mHz example.

    kenmac

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Perth, Western Australia
    Time Zone = GMT + 8
  • KaioKaio Posts: 253
    edited 2007-08-23 12:25
    kenmac,

    as deSilva has explained your expression containing a division takes to much time. As the clockfreq is not changed at runtime you could use the result of division as constant.
    waitcnt((constant(clkfreq/1_000_000) * DelayuS) + cnt)
    
    

    Post Edited (Kaio) : 8/23/2007 12:35:31 PM GMT
  • KaioKaio Posts: 253
    edited 2007-08-23 17:28
    Fred,

    sorry, but your calculation is wrong. Please be aware that clkfreq and _clkfreq have different meanings (p. 176 manual).

    And the system counter wraps after 53 seconds at 80 MHz.

    @kenmac
    Without your multiply for µs the waitcnt uses 381 system clocks (p. 323 manual). This is approximately 5 µs. The multiply takes again 5 µs. So I think the smallest time could be 10 µs if you would use a constant as I mentioned before.
  • deSilvadeSilva Posts: 2,967
    edited 2007-08-23 18:20
    Kaio said...
    (constant(clkfreq/1_000_000)
    No this wil not work, as CLKFREQ is not a constant, but a variable computed by the interpreter; it also can change during the program if you modify your clock settings!
  • Fred HawkinsFred Hawkins Posts: 997
    edited 2007-08-23 19:07
    kaio,
    Alas, more reading to do. (Which I did. _clkfreq and clkfreq may be different values but in this trivial program I think they can be considered the same.)

    So how fast does the counter wrap at 5 Mhz?


    Post Edited (Fred Hawkins) : 8/23/2007 7:18:57 PM GMT
  • deSilvadeSilva Posts: 2,967
    edited 2007-08-23 19:28
    I said 238 s in my first posting, but it is of course twice as much..
  • KaioKaio Posts: 253
    edited 2007-08-24 09:53
    deSilva,

    you are right, CLKFREQ can not be used as a constant. I know that the CLKFREQ can be changed during the runtime, but I was thinking if kenmac doesn't do that the result of division is constant.

    @Fred
    Regarding the counter wrap at 5 MHz I would say it must be 16 times, while the quotient of 80 / 5 equal 16. So it should be nearly 859 seconds. That's a long time if you want to see a LED blinking. lol.gif

    @kenmac
    From the discussions before I end up of the following code.
    Note: I haven't tested the code yet.
    CON
      uS = 80 'clock counts for 1 µs, assuming clkfreq is 80 MHz
    
    
    pub uSdelay(DelayuS)            'Delay for # of microseconds
      waitcnt((DelayuS #> 10) * uS + cnt)  'minimum 10 µs
    
    



    Thomas
  • deSilvadeSilva Posts: 2,967
    edited 2007-08-24 11:01
    You can try to tune it further. Note that SPIN TAKES TIME.
    When you expect to wait 10 us it will be around 30 us, when you say "50" it will be around "70"... You can compensate for it by subtracting a specific value (around 20, but maybe even 50) from your parameter. You have to calibrate it by e.g. toggling a pin and measuring the frequency. Note that pin-toggling takes time as well (10 us or more...)
Sign In or Register to comment.