Shop OBEX P1 Docs P2 Docs Learn Events
non hardcoded micro seconds delay in pasm. — Parallax Forums

non hardcoded micro seconds delay in pasm.

tonyp12tonyp12 Posts: 1,951
edited 2011-09-05 16:56 in Propeller 1
I think it's good to actually calculate how many ticks there are in a microsecond.
And not take for granted the prop is running at 80mhz and also that it could change during runtime.
Especially if you are writing a driver that should work at most clock speeds.

hint: delay122 is not exactly 122uS but close.
To get extact value of it calc 19531 /2 (rounded down) /80 = 122.0625 uS
And so on for the next values,
using previous rounded down value /2 (rounded down)/80

With a slow running prop the error can be larger, but can be calculated.
main          rdlong    delay244,#0                     'get System Hz (how many ticks in 1sec)
              shr       delay244,#12                    'div by 4096 = 244 uS 
              mov       delay122,delay244
              shr       delay122,#1                     'divide by 2 = 122 uS
              mov       delay61,delay122
              shr       delay61,#1                      'divide by 2 = 61 uS
              mov       delay30,delay61
              shr       delay30,#1                      'divide by 2 = 30.5 uS
              mov       delay15,delay30
              shr       delay15,#1                      'divide by 2 = 15 uS
              mov       delay7,delay15
              shr       delay7,#1                       'divide by 2 = 7.5 uS
              mov       delay4,delay7
              shr       delay4,#1                       'divide by 2 = 4 uS
              mov       delay2,delay4
              shr       delay2,#1                       'divide by 2 = 2 uS
              mov       delay1,delay2
              shr       delay1,#1                       'divide by 2 = 1 uS
              min       delay1,#5                       'never let it go below 5 ticks

   ' example: sometimes you have to add up a few delays to get the time you want.

              mov       cnt,delay122                    'prepare a 200us delay, letting Latch go low.
              add       cnt,delay61                     '122+61+15= 198 (~200)
              add       cnt,delay15    
              andn      outa,CLKpin                     'set pin low  
              add       cnt, cnt                        'add cnt to shadow cnt     
              waitcnt   cnt, delay244                   'wait 200us, add 300us to cnt when done.
              add       cnt, delay61                    '244+61= 305 (~300)
              or        outa,CLKpin                     'set pin high. 
              waitcnt   cnt, #0                         'wait 300uS
              ...
              ...

delay244      res       1
delay122      res       1
delay61       res       1 
delay30       res       1    
delay15       res       1   
delay7        res       1    
delay4        res       1 
delay2        res       1
delay1        res       1 

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2011-09-05 14:02
    To be honest, I don't get the point of this thread!

    Using clkfreq is not a hardcode! The compiler takes care of having the right value in it according to the clock-settings. The clock-frequency is a variable placed at the beginning of RAM. I don't remember what happens if you change the clock-settings on the fly - but worst case is that you have to maintain it with the code that changes the clock-settings.

    What I also do not understand is, why don't you use 2^x values instead?
    256, 128, 64, 32, 16, 8, 4, 2, 1
    with these you can sum up any integer delay you want exactly!
  • tonyp12tonyp12 Posts: 1,951
    edited 2011-09-05 14:12
    If your cog is a driver and have no control over what speed the prop is running at and
    that it can change at anytime even after the cog have started (you may trying to save power)

    How could that cog update it's delays? to still be based on time (microseconds) and not hardcoded ticks.
    Sure it does not happened often, maybe because most drivers are hardcoded at the time of compile.

    I'm using 2^x values, but with integer math using shifts the values gets rounded down.

    I calculated that I get these numbers after I do the first >12 (based on 80mhz)
    19531.. ~244
    9765.. ~122
    4882.. ~61
    2441.. ~30.5
    1220.. ~15
    610.. ~7.5
    305.. ~4
    152.. ~2
    76.. ~1

    But I think I will skip this checking and only check if system clock is below 10mhz and go to sleep (as user is probably running from battery)
    and periodically check if back to faster mode, as my driver does not work at those slow speed anyway.
    main          rdlong    sysclk,#0                       'get System Hz (how many ticks in 1sec)
                  mov       cnt,sysclk                      'in case we will wait 1sec
                  shr       sysclk,#23 wz                   'mimimum speed we can handle is around 8mhz
            if_nz jmp       #fastenough
                  add       cnt,cnt                         'add cnt to shadow cnt.
                  waitcnt   cnt,#0                          'wait 1 second
                  xor       outa,CLKpin                     'send a 1sec pulse
                  jmp       #main                           'jump back and try again.         
    fastenough    mov       digit,#6                        'we have 6 digits to multiplex
    


    But how do I include clkfreq in pasm for in time of compile?

    delay1 long clkfreq/1_000_000 'DOES NOT WORK (??)

    This works:
    But I guess the values are set during runtime?, that's better.
    Are the locations modified just before the cog gets the data?
    How good is spin math? as a large div and then mul could create rounding errors.
    PUB Display (text)
        delay1 := clkfreq/1_000_000
        delay15 := clkfreq/1_000_000 *15
        delay30 := clkfreq/1_000_000 *30
        delay200 := clkfreq/1_000_000 *200
        delay300 := clkfreq/1_000_000 *300
        cognew(@asm_entry, text)   'launch assembly program in a COG 
        ...
    DAT org
        ...
    delay1        long      0-0
    delay15       long      0-0
    delay30       long      0-0
    delay200      long      0-0
    delay300      long      0-0
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-09-05 16:56
    Tony, with all the code up front and given the frequency of potential clkfreq changes wouldn't it be easier to include a division routine (clkfreq/n)?
Sign In or Register to comment.