Shop OBEX P1 Docs P2 Docs Learn Events
Question about djnz — Parallax Forums

Question about djnz

SSkalkoSSkalko Posts: 9
edited 2011-04-14 03:17 in Propeller 1
Trying to get this chuck of code to work, the idea is the aDAT pin cycles twice, then the aSER pin cycles 24 times then waits for the aDAT pin to cycle again.
:loop1  mov              bitcount,               #24
           waitpeq         aDAT,                   aDAT
           waitpne         aDAT,                   aDAT
           waitpeq         aDAT,                   aDAT
           waitpne         aDAT,                   aDAT
:loop2  xor                outa,                   aSER
           waitcnt          cnt,                    delay
           xor                outa,                   aSER
           waitcnt          cnt,                    delay
           djnz              bitcount,               #:loop2
           jmp               #:loop1
        
          waitpeq         $,                      #0
        
delay                   long    200 

There is more code before the posted chunk that works fine.
Any help would be appreciated.

Comments

  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-12 15:29
    To me it looks like you're not setting up your waitcnt properly. Waitcnt waits for the counter to reach the value specified, then adds the argument to that value when the wait is finished.

    So, to wait 10 cycles, you do this:
      mov      waitTime, #10
      add      waitTime, cnt  'add the current value of the counter
      waitcnt  waitTime, #0
    

    If you wanted to wait 10 cycles, then run some code, then wait for exactly 100 cycles from when you started, you do this:
      mov      waitTime, #10
      add      waitTime, cnt
      waitcnt  waitTime, #90   'add 90 cycles to the waitTime when it's finished
    
      nop
      nop  ' real code that takes less than 90 cycles goes here
      nop
    
      waitcnt  waitTime, #0    'wait for the 10 + 90 cycle time to elapse
    

    So I think in your case, you want:
            mov      waitTimer,  delay
            add      waitTimer,  cnt
    
    :loop2  xor      outa,       aSER
            waitcnt  waitTimer,  delay   'add more delay to the existing timer
            xor      outa,       aSER
            waitcnt  waitTimer,  delay   'and again...
            djnz     bitcount,   #:loop2
            jmp      #:loop1
    
    

    It's also worth noting that the delay "begins" from the moment you read the previous count value. In my code, I'm adding the counter after setting the delay time, so the delay is counting from the instruction where the add takes place.

    Some people prefer this:
    mov   waitTime, cnt
    add   waitTime, delay
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-12 18:11
    JasonDorie wrote: »
    To me it looks like you're not setting up your waitcnt properly.
    Seconded. There are waitpxxs in front so you can't/don't know beforehand what the first target will be.
    JasonDorie wrote: »
    So, to wait 10 cycles, you do this:
      mov      waitTime, #10
      add      waitTime, cnt  'add the current value of the counter
      waitcnt  waitTime, #0
    
    That's a rather odd example don't you think?
  • mparkmpark Posts: 1,306
    edited 2011-04-13 08:06
    kuroneko wrote: »
    That's a rather odd example don't you think?

    Why do you say that?
  • PublisonPublison Posts: 12,366
    edited 2011-04-13 08:25
    OT: Happy Birthday Micheal!
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-13 16:56
    mpark wrote: »
    Why do you say that?
    Simply because this fragment delays for 14+n cycles (19 in this case). Probably not important to the OP though, I guess it's just me again :)
    mov      waitTime, #5{14} + 5
      add      waitTime, cnt  'add the current value of the counter
      waitcnt  waitTime, #0
    
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-13 17:05
    I actually thought it was weird because it was waiting for 10 cycles, which is not nicely divisible by the instruction timings. I was just using a convenient number for the purpose of illustration. :)
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-13 17:11
    JasonDorie wrote: »
    I was just using a convenient number for the purpose of illustration. :)
    I know, I was just in the wrong mood. As for 10 cycles ... what about this (completely OT):
    nop
    waitpne $, #0
    
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-13 17:23
    I have no idea what that does - It looks dangerous to me. :)
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-13 17:42
    Let's get back on topic.

    @SSkalko: What about this:
    :loop1          waitpeq aDAT, aDAT
                    waitpne aDAT, aDAT
                    waitpeq aDAT, aDAT
                    waitpne aDAT, aDAT
    
                    mov     bitcount, #24*2         ' double loop count -> xor
    [COLOR="red"]                mov     cnt, cnt
                    add     cnt, #9
    [/COLOR]:loop2          waitcnt cnt, delay
                    xor     outa, aSER
                    djnz    bitcount, #:loop2
    
                    jmp     #:loop1
            
    delay           long    200
    
    It makes sure that your initial waitcnt target is one which can be reached in a reasonable time frame, i.e. is known.
  • homosapienhomosapien Posts: 147
    edited 2011-04-13 20:10
    mov cnt, cnt
    add cnt, #9

    Need some in-line comments here, this is as twisted as the
    waitpne $, #0
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-13 20:23
    homosapien wrote: »
    Need some in-line comments here ...
    Let's start with the waitpne. It waits until dst is not equal ina & #0. The dst slot refers to here which is address of the current instruction. Which means it's effectively using the binary pattern for the waitpne instruction which is not equal 0. Therefore this instruction completes immediately with its minimum timing of 6 cycles.

    As for waitcnt, maybe you feel more comfortable with this version:
    mov temp, cnt
    add temp, #9
    
    The #9 makes sure that an immediately following waitcnt just falls through (6 cycles). Any other value (greater 8) will do. I prefer it this way. Using cnt in the dst slot refers to its shadow register (i.e. is as good as temp).
  • homosapienhomosapien Posts: 147
    edited 2011-04-13 20:41
    yes, yes, this is of course all well known, simple child's play really......

    I was just wondering how you got the posted lines of code to show in red. :smile:
  • mparkmpark Posts: 1,306
    edited 2011-04-13 21:30
    kuroneko wrote: »
    Simply because this fragment delays for 14+n cycles (19 in this case). Probably not important to the OP though, I guess it's just me again :)
    mov      waitTime, #5{14} + 5
      add      waitTime, cnt  'add the current value of the counter
      waitcnt  waitTime, #0
    

    Please walk me through this. Where does "5{14} + 5" come from?

    (@Publison: Thanks! How did you know?)
  • kuronekokuroneko Posts: 3,623
    edited 2011-04-14 03:17
    mpark wrote: »
    Please walk me through this. Where does "5{14} + 5" come from?
    The minimum delay for those 3 instructions is 14 (4+4+6). 6 cycles are achieved by either using
    mov     cnt, #5{14} + 0
    add     cnt, cnt
    waitcnt cnt, #0
    
    or
    mov     cnt, cnt
    add     cnt, #9{14} + 0
    waitcnt cnt, #0
    
    So 5{14} + 5 is just a way of saying that 5 cycles are used to guarantee the minimum 14 cyles ({14} being a comment) and the other 5 cycles are extra delay (14 -> 19).
Sign In or Register to comment.