Shop OBEX P1 Docs P2 Docs Learn Events
passing arrays to assembly and back — Parallax Forums

passing arrays to assembly and back

swampie777swampie777 Posts: 33
edited 2009-08-24 18:21 in Propeller 1
How can I pass an array to assembly and back? I want to read several ports, place the values in an array and do something with them once back in spin code.

Thanks,

Swampie777

Comments

  • AlsowolfmanAlsowolfman Posts: 65
    edited 2009-08-21 20:12
    i am pretty sure this is correct, but i'm sure that someone will be able to give you something more helpfull

    if you have a single array you can give its address as the par of the cognew statement

    cognew(@work, @array)

    in the cog you need to use self modifying code, and the movs, or movd for move source and move destination. an example of this is
              mov hub_array_pointer, par
              mov cog_array_pointer, #cog_array  ' the # symbol gives the cog address of that data
    :loop   movd :next, cog_array_pointer
              add cog_array_pointer, #1  ' you add 1 to cog addresses since the register is longs
    :next  rdlong 0-0, hub_array_pointer
              add hub_array_pointer, #4  ' you add 4 for the hub because its addresses are bit sized, so you need to go 4 bits forward to get to the next long
              jmp #:loop
    
    




    cog_array long 0[noparse][[/noparse]10]

    you have to have the :loop separated from : next by one instruction because the data from the next instruction is loaded before the current instruction finishes

    for retrieving code from the hub you will use movd because the cog is your destination, for manipulating the data in the cog you will use movs because the cog is your source. then for sending back to the hub you will use movd again because hub operations are strange and the hub address is always in the source field.



    for more look at page 21 of the pdf attached here http://forums.parallax.com/forums/default.aspx?f=25&m=209237

    Post Edited (Alsowolfman) : 8/21/2009 8:24:53 PM GMT
  • SRLMSRLM Posts: 5,045
    edited 2009-08-21 21:56
    Wolf man is correct. Basically, there isn't really a concept of "array" in pasm. Instead, you simply move a series of single values about as necessary.
  • swampie777swampie777 Posts: 33
    edited 2009-08-24 13:11
    Alsowolfman said...
    you have to have the :loop separated from : next by one instruction because the data from the next instruction is loaded before the current instruction finishes
    I didn't understand this part. If you need an instruction to finish ( pipelined I assume) why not use a nop?

    In my current application I'm reading two pins for a high level, recording the clock counts by difference( one at a time) and trying to pass the results back to spin. I have the spin code in a loop to grab 16 values. I get 16 unique first values, and 16 copies of the first second value.
    {{ dual-pulse-read.spin }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    VAR
            long stack[noparse][[/noparse]72]
            
            long xxx1[noparse][[/noparse]2]
            long iii
            long Idx
            long xsum
            long iii2
            long xsum2
            long Cog  
            
    OBJ
      Num   :       "Numbers"
      TV    :       "TV_Terminal"
      vp    :       "Conduit"
      
    PUB Main
      xxx1[noparse][[/noparse]0] := -1
       Idx :=0
      xxx1[noparse][[/noparse]1]  := -1
     vp.share(@xxx1,@Cog)
    Num.Init              'Initialize Numbers   
    TV.Start(12)          'Start TV Terminal
     Cog := cognew(@pulse_,@xxx1)
    ' TV.Str(Num.ToStr(Cog, Num#DDEC))
    ' TV.Out(13)
       
              repeat while Idx < 16
      
               xxx1[noparse][[/noparse]0] := -1
               
                 repeat  while xxx1[noparse][[/noparse]0] == -1
                 if Idx > 0
                  TV.Str(Num.ToStr(xxx1[noparse][[/noparse]0], Num#DDEC))                                     
                  '/*TV.Out(13) */
                  TV.Str(Num.ToStr(xxx1[noparse][[/noparse]1], Num#DDEC))                                                   
                  TV.Out(13)
                  
               Idx++
            cogstop(Cog)
             
    DAT
    pulse_                  org        0
                                                                             
    :loop                   waitpeq   zero,mask
                            waitpne   zero,mask
                            mov       xx1, cnt
                            waitpeq   zero,mask
                            mov       yy1, cnt
                            sub       yy1, xx1
                            wrlong    yy1, PAR
                            add       parplus4, PAR                                                       
                            waitpeq   zero,mask2
                            waitpne   zero,mask2
                            mov       xx2, cnt
                            waitpeq   zero,mask2
                            mov       yy2, cnt
                            sub       yy2, xx2
                            wrlong    yy2,parplus4
    :here                   jmp       #:loop
    zero           long    0
    pfour          long    4
    mask           long    |<25
    lll            long    0
    mask2          long    |<24
    parplus4       long    4
    xx2            res     1 
    yy2            res     1 
    xx1            res     1 
    yy1            res     1 
    Mem            res     1
    

    If I run a program to just collect one value from one pin at a time the magnitudes compare correctly with the above code and with the oscilloscope outputs.
  • AlsowolfmanAlsowolfman Posts: 65
    edited 2009-08-24 17:58
    you are correct about the pipeline, in most cases i put something other than nop to make the code faster.


    you need to define parplus4 before the loop, every cycle you get an additional par added to it, so
    loop1 parplus4= par + 4
    loop2 parplus4=par+par+4
    ...
  • jazzedjazzed Posts: 11,803
    edited 2009-08-24 18:21
    You can pass an array "by reference" ... this is the idea of how ... code is not tested

    con ' clock stuff handled separately ...
      ALEN = 10
    
    var
      word myarray[noparse][[/noparse]ALEN]
    
    pub start
      cognew(@pasm, @myarray)
    
    dat
      pasm  org 0
      jmp   #:mainloop
      aptr  long 0
      tmp   long 0
      len   long 0
    
    ' this would run constantly ...
    ' you can add a flag from spin to start the process on demand
    '
    :mainloop
      mov     aptr, par   ' get array address
      mov     len, #ALEN ' set array length
    
    ' array read/modify/write loop
    '
    :loop
      rdword  tmp, aptr   ' read value from "myarray"
      ' do something to tmp here
      wrword  tmp, aptr   ' write modified value back to "myarray"
      add     aptr, #2    ' increment pointer by 2 to get next myarray address
      djnz    len, #:loop ' do it for all array entries
    
      jmp     #:mainloop  ' repeat process
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    --Steve

    Propeller Tools
Sign In or Register to comment.