Shop OBEX P1 Docs P2 Docs Learn Events
May I make a first request? — Parallax Forums

May I make a first request?

parskoparsko Posts: 501
edited 2006-09-07 16:48 in Propeller 1
Calling on Paul Baker, the newest member of the Parallax family.· Congrats sir.· I have a request of you that I have been waiting for the right moment to ask, and this seems appropriate.· In the previous post:

http://forums.parallax.com/showthread.php?p=589773

you state.....
Paul Baker (Parallax) said...
Im not sure whats going wrong with you program, it very well may be the spin code thats misbehaving, I'll share my code but it uses a lot of non-standard tricks which would take a while to explain:

:hptr         mov       :hptr, par                      'use this loc as ptr to hub mem
              mov       :i, #CogBufSz2                  'reinit counter
              wrlong    :d_inc, :hptr                   'write non-zero to signal start
              add       :hptr, #1                       'inc hub pointer
 
:writeloop    wrlong    fbufstart, :hptr                'write long to main memory
              add       :writeloop, :d_inc              'inc buffer pointer
              add       :hptr, #4                       'inc hub pointer 1 long
              djnz      :i, #:writeloop                 'empty entire buffer              

Now that it is practically your job to explain this stuff (I know, it's voluntary), would you care to explain what is going on here in more detail??· I have since figured out how to pass an array to an assy COG, but everytime I read this forum post, I keep telling myself to ask about this section of code, cause it looks like some lean clever code...

-Parsko

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2006-09-07 14:09
    I know you sent this to Paul, but this code fragment is straightforward if you take it one instruction at a time. What's missing is the value of :d_inc, but I assume it's a long with a one value shifted to the destination field of an instruction (1 << 9).

    :hptr   mov     :hptr,par           ' This instruction just copies the value in par over top of itself.  It's a "one time only" thing
                                                  '  just to save a location and make use of a local label rather than a global assembly label.
              mov     :i,#CogBufSz2   '  This initializes the loop counter with the number of longs to transfer (excluding the start flag)
              wrlong  :d_inc,:hptr      '  When the first long of the buffer area (the start flag) is set to a non-zero, this signals that
                                                  '  the transfer has started.  PAR contains the address of this buffer (and here is in :hptr).
              add       :hptr,#1          '  This increments the buffer pointer.  It probably should increment the pointer by 4, not by 1
                                                 '  since there was a long stored here.  I'm not sure what the HUB does with an incorrect address
                                                 '  (one that's not a multiple of 4 with a wrlong instruction).  It probably ignores the low order bits.
    :writeloop wrlong fbufstart,:hptr  ' The starting address in the cog buffer is "fbufstart".  This copies the long to HUB RAM.
              add       :writeloop,:d_inc   ' Modify the previous instruction by adding a one to the destination address field (to get
                                                  '  "fbufstart+1", "fbufstart+2", etc.)  Note that cog addresses are always long addresses.
              add       :hptr,#4          ' Increment the buffer pointer to the next long in HUB RAM.
              djnz      :i,#:writeloop  '  Continue until all longs have been transferred
    
    


    This would be clearer if the HUB RAM pointer were stored in a separate location and if the initialization code at the beginning
    also initialized :writeloop like with a "movd :writeloop,#fbufstart" with the instruction at :writeloop written as
    "wrlong 0-0,:hptr". That makes it clearer that this instruction is modified, but takes an extra instruction. Unfortunately,
    doing any kind of indexing of the destination or source fields requires instruction modification on the Propeller. It works great, but can be confusing if you don't document it carefully.

    Post Edited (Mike Green) : 9/7/2006 2:16:28 PM GMT
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-09-07 16:48
    Mike has a good understanding of the code, d_inc is indeed defined as 1<<9 which is the first bit of the destination field within the instruction.

    I·used the code in a digital storage scope object (which should be one of the first objects I release, 1 mode works, I'm working on the other two modes).·So I was trying to squeeze everything into as small of a memory footprint as possible to provide as many memory locations for the data buffer as possible.

    Also the code is designed to be executed through once then stop. I employed several tricks such as using an initalization instruction for a working variable as the variable's location as well. This is what I was doing with the :hptr location.

    Thanks for pointing out the adding 1 to the hub pointer after first use, I intended it to be declared as a byte variable followed by an array of longs, but looking at the full code, I noticed this wasn't the case. I will have to modify the code either to declare it that way (and use wrbyte) or add 4.

    The comments are the working comments and will be expanded before the object's release.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.

    Post Edited (Paul Baker (Parallax)) : 9/7/2006 4:52:55 PM GMT
Sign In or Register to comment.