Shop OBEX P1 Docs P2 Docs Learn Events
Assembly, shared memory, multiple Cogs — Parallax Forums

Assembly, shared memory, multiple Cogs

WurlitzerWurlitzer Posts: 237
edited 2011-08-06 11:43 in Propeller 1
Sorry, I'm thick today (well maybe more than today). I have an application which will require 5 or more cogs (some with SPIN others in Assy) to read and write to a common Byte Array[noparse][[/noparse]100] in Main RAM.

I cannot get my head around how to assure all cogs know the starting address address of this common array. Does it require the array to be declared in the Top Object then have the Top Object call all the subseqent "CogNew(@SpinOrAssyObjectName,@@ByteArray[noparse][[/noparse]0])" and then the PAR register in each cog will contain the proper starting address?

I don't have any worries in this program regarding conflicting writes I just need to be able to read/write to any element in this 100 element ByteArray from any cog.

Thanks

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2006-12-15 20:18
    There are several ways you can do this:

    1) In your routine to start these cogs, assign the address of this array to a long word in the assembly code for the cog like:
    PUB start
       arrayAddr := @ByteArray
       c := cognew(@routine,parameters)
    DAT
                      org      0
    routine       '... stuff
                     rdbyte   temp,arrayAddr   ' This reads ByteArray[noparse][[/noparse]0] into temp
    '... stuff
    arrayAddr    long    0
    
    


    2) In your start routine, pass the address of the array as the parameter for the PAR register:
    PUB start
      c := cognew(@routine,@ByteArray)
    DAT
                       org      0
    routine        rdbyte  temp,PAR       ' This reads ByteArray[noparse][[/noparse]0] into temp
    
    


    To read other bytes from the array, move the address to a temporary location and add the index to the temporary, then use rdbyte to read from the resulting address. To write to a byte, use wrbyte instead. Be careful in that a cog could read a byte, do some computation on it and write it back while some other cog wrote a value to the same byte between the first cog's read and write.
  • WurlitzerWurlitzer Posts: 237
    edited 2006-12-15 20:50
    Thanks Mike, I''ll try these suggestions tonight. Because of how the data is produced and consumed, I will not have any issues with write/read conflicts.

    Again, thanks for the very quick reply.
  • Mike GreenMike Green Posts: 23,101
    edited 2006-12-15 21:11
    Noticing your other messages about your organ controller ... Unless you have a need for really raw speed or very precise timing, there's very little you can't do with just SPIN. Try to keep the assembly stuff simple and straightforward.
  • WurlitzerWurlitzer Posts: 237
    edited 2006-12-16 13:37
    Mike, a couple of processes in the pipe organ require rapid processing. Scanning the keyboards and pedal boards (61 clocks and compares, writing new data to the array) then updating each pipe driver board (96) clocks and sending the MIDI commands certainly pushed the BasicX-24 to its limit as I wanted to update the entire process·at a minimum of 100 X per second.

    Obviously, the propeller (minus the MIDI communication) can handle the processes above without a problem using SPIN. The oddball MIDI baud rate (~~32Kbaud) requires the higher speed provided by assembly and the communication baud rate to the pipe chamber will be much higher.

    Where the Propeller chip (in assembly) shines in this application is when a Combination Action·button is pressed. It is possible the state of 200+ stop tabs will change simultaneously·and I have to determine what MIDI messages need to be sent to Record that change while at the same time not slowing down the data stream for the playing notes. I have come up with a method to reduce the data sent during this event in record or received in playback by 95% but it requires some very quick processing prior to sending the MIDI message.

    I will also be recording/playback in MIDI via an SD card for those times I do not want to take the time to boot up my PC.

    There are other systems on the market that fall short in performance, IMO, for this application. Some you can hear the playing notes slow down when a Combination Action button is pressed. They also are very complicated with hundreds of ICs. And, lets face, it some of this is simply a great way to learn Propeller programming.

    It is people like you Mike (and others) that make this possible because of your willingness to share your expertise. Thanks.
  • parskoparsko Posts: 501
    edited 2006-12-16 14:47
    Wurlitzer,

    I haven't read any of the other responses, but wanted to make a quick suggestion. You'd have no problem if you can coordinate your programming so each variable in the array is only read and written to once. Never have more than one application write or read to each variable. Follow this rule and you'll be fine.

    -Parsko
  • WurlitzerWurlitzer Posts: 237
    edited 2006-12-16 17:52
    Correct Parsko!

    Part of the 100 byte array is a circular queue and only the console (keyboard, pedal, stop tabs) routine writes to the circular queue.·Two other COGs routines simply read this queue and send any derived MIDI messages to a transmit queue (1 per COG). One of these 2·COGs sees both transmit queues and has the task of sending the data to the serial out routine/COG. As long as my serial out routine is functioning the 2 transmit queues will be serviced faster than they can fill. If my serial routine fails, the organ still plays but does not record and at that point the last thing I would be worried about is the transmit queues.

    Thank you for your interest and comments.
  • zpuazpua Posts: 33
    edited 2011-08-06 11:43
    Mike,

    Does the code below making any senses? I want to array to cog 2 when cog 1 stop

    t:=0
    repeat I From 0 To 180
    Array1:=t

    Debug.str(string(13,"counter="))
    Debug.dec(t)
    Debug.str(string(13,"Sin(t)="))
    'C:=((b/2)*(t/200))
    'd:=fMath.FSqr(C)
    A:=fMath.Sin(fMath.Radians(fMath.FFloat(t)))
    debug.str(fstring.FloatToString(A))
    Array2[J]:=A
    t:=t+1
    waitcnt(clkfreq+cnt)
    'ReceiveArray (@Array1,@Array2)
    cogstop(0)


    PUB Start2(I,J):Success


    Stop
    success:=( cog :=cognew(ReceiveArray(@long[Array1][5],@long[Array2][20]), @Stack1)+1)

    PUB Stop

    If cog
    cogstop(cog~-1)

    PUB ReceiveArray(temp1, temp2)

    debug.start(31, 30, 0, 38400)
    debug.tx(13)
    waitcnt(clkfreq+cnt)
    temp2:=Array2[5]
    debug.str(string(13,"x="))
    'debug.dec(temp2)
    debug.str(fString.FloatToString(temp2))
Sign In or Register to comment.