Shop OBEX P1 Docs P2 Docs Learn Events
Spin Zone #10, January 2011 — Parallax Forums

Comments

  • localrogerlocalroger Posts: 3,452
    edited 2011-01-04 17:12
    Pretty good article, thanks for the link.

    I do notice that he mentions the variance in practice between using PAR to "properly" pass values to PASM routines and just "poking" the vals in. I've taken pretty much to using the poke before launch method, because it saves lots of both Hub and Cog RAM, making it the superior method, period. But he has a valid point that it makes PASM code harder to use with other languages.

    However, you can get around that too! If you make the first instruction of the Cog image a jump (which you then later use as the always-needed TMP var), followed by an ordered array of parameters, you can poke the parameter values into your PASM image from any language as long as you have the indeces.
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2011-01-04 17:44
    Excellent article!!

    OBC
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-04 17:56
    But he has a valid point that it makes PASM code harder to use with other languages.

    To be honest -- and I always try to be -- it wasn't my point; it was in fact made by another (perhaps RossH) vis-a-vis C and other languages that are popping up for the Propeller. Like you, Roger, I had gotten very used to poking values into my PASM code before launching, but now, since I may want to experiment with Catalina and other languages, I'm trying to write my objects so that they will work as universally as possible. It's a little extra work but a one-time thing (hopefully).

    @OBC: Thanks, pal!
  • Cluso99Cluso99 Posts: 18,069
    edited 2011-01-05 15:53
    Great work Jon. It's nice to see articles being published in mags to get others interested in the prop.
  • HumanoidoHumanoido Posts: 5,770
    edited 2011-01-06 05:21
    Really great article - this is a main source of learning!
  • ericballericball Posts: 774
    edited 2011-01-06 07:21
    Two other reasons to use a parameter block instead of poking values directly:
    1. Dynamic updates. Although it may be very rare to change some of the parameters for tv.spin there may be programs where that feature is useful.
    2. Avoids startup collisions. cognew takes ~8K cycles to load the cog. So bad things could happen if two SPIN objects both start the same cog at the same time, or one object invokes the start more than once in quick succession.
  • Heater.Heater. Posts: 21,230
    edited 2011-01-06 07:39
    ericball,

    Not so fast...

    Let's assume we are comparing localrogers's POKE technique vs passing a parameter block via PAR.

    Both require a parameter block to be set up prior to launching a COG. It's just that localroger requires defining it at the start of the PASM block itself.

    So...

    1)Dynamic updates.
    I presume that means changing parameters whilst the COG is running.

    I believe this is better done through a mailbox interface, if it is ever required, rather than the initial parameter block. Mostly restarting the COG entirely with new params is as good away as any.

    2) Avoids startup collisions.

    Perhaps true, but start up collisions are still possible with a PAR block unless the user remembers to use a different PAR block space for each COG started. Which is more waste of memory.

    Might as well remember to wait a few microseconds whilst a COG is loading its params before starting the next one.
  • potatoheadpotatohead Posts: 10,261
    edited 2011-01-06 11:34
    Well, restarting the cog with new parameters assumes the process can tolerate that.

    What about a video driver? We are reaching a point now where we've got a lot of modes and signal options and resolutions available to us. If that COG is simply watching it's parameters, where ever they are, another process written in basically anything can just write a value, perhaps read one back, but maybe not, and the behavior changes. Say a driver goes from bitmap mode at low resolution, to text, or that maybe uses color redirection. Simply updating a value somewhere is nice and clean, and in the case of the color redirection, something that is very useful at runtime.

    A restart requires a break in the signal, which isn't always desirable, that's all.

    I like the idea of being able to just have the values in the COG image, but that kind of all breaks down when one wants to load the cog into a buffer, start it, then erase the buffer for another one.

    Seems to me, being able to specify where that parameter block lives gets around that nicely. Just pass PAR, then the cog can operate relative to that for inputs and outputs. Ideally then, the COG image would never change, consuming it's unknowns from PAR, or offsets to whatever is in PAR. Applicable to multi-cog tasks as well.
  • RS_JimRS_Jim Posts: 1,768
    edited 2011-01-18 12:07
    Great article! Question for Jonny. Where to find the __PASM_subs.spin.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-18 14:13
    Thanks, Jim. Perhaps I forgot to attach that file -- here you go.
  • RS_JimRS_Jim Posts: 1,768
    edited 2011-01-19 05:03
    Thanks Jon. BTW, tomorrow I will be visiting your famous customer in Anaheim and will be curious as to where I might encounter some of your handywork.
    RS_Jim
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-19 07:04
    Most of it is seasonal and was just taken down. If you have kids and are in an area called Pixie Hollow (where Tinkerbell lives), look up -- if you see twinkling flowers (sometimes they're not on until it's dark), those are controlled with SXes. In Small World there are a set of praire dogs that randomly pop up that are controlled with a BASIC Stamp 1 (Prop-1 Controller) with a code base I wrote for the park. Have fun.
  • lardomlardom Posts: 1,659
    edited 2011-01-19 07:50
    JonnyMac, thanks for the tutorial. Your use of blinking LEDs is perfect for learning PASM. I could read the code because you spelled it out. I thought the article was rich with stuff worth knowing. Another example was finding out that constants are calculated at compile time. The light went on in my head when I read that. Your discussion of scope was something I wished I had known while I was struggling with my now finished project.
    I wish there was a forum for students of PASM. I, for one, could more rapidly absorb the lessons of accomplished engineers once I learn C-A-T. The Propeller lab manual is indespensable but it only teaches Spin.
    I wanted to ask if the #4 in the following snippet is a standard of some sort?
    add     tmp1, #4
    
  • homosapienhomosapien Posts: 147
    edited 2011-01-19 08:21
    I wanted to ask if the #4 in the following snippet is a standard of some sort?
    Code:
    add tmp1, #4
    Larry


    Larry,

    He is simply advancing to the beginning of the next LONG in memory (4 bytes = 1 long)

    -h
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-19 08:22
    I wanted to ask if the #4 in the following snippet is a standard of some sort?

    Depends on context. For example, in this snippet the PASM code is retreiving two timing values (ticks in milliseconds, ticks in microseconds) and then saving the addresses of two working variables. All of the hub (Spin) elements are longs so we have to add 4 (there are four bytes in a long) to the address (in tmp1) to get the address of the next element. The base address of the Spin variables in passed in par.
    dat
    
                            org     0
    
    entry                   mov     tmp1, par                       ' start of structure
                            rdlong  ms001, tmp1                     ' read ticks per ms
                            add     tmp1, #4
                            rdlong  us001, tmp1                     ' read ticks per us
                            add     tmp1, #4
                            mov     cmdpntr, tmp1                   ' save address of cmd
                            add     tmp1, #4
                            mov     rsltpntr, tmp1                  ' save address of cmdresult
    
  • lardomlardom Posts: 1,659
    edited 2011-01-19 09:09
    I'm smiling at my computer screen...
  • potatoheadpotatohead Posts: 10,261
    edited 2011-01-19 09:16
    Cog addressing is on a LONG basis, and HUB addressing is on a BYTE basis.

    In general,

    RDBYTE would be associated with add tmp, #1

    RDWORD is add tmp, #2

    RDLONG is add tmp, #4.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-19 09:26
    Thanks for that follow-up -- I should have stated that in my earlier post.
  • RS_JimRS_Jim Posts: 1,768
    edited 2011-01-20 04:48
    Thanks Jon,
    will look for prarrie dogs in small world. I doubt we will see the twinkling flowers. This is a brief trip with a very senior citizen so travel within the park will be limited.
    RS_Jim
  • MacTuxLinMacTuxLin Posts: 821
    edited 2011-01-20 07:11
    Hey Jonny,
    Great article, simple & concise. You ought to write a book on PASM for Spinners :)
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-01-20 15:48
    I'm working on a project that has "An Introduction to PASM" in it, but I'm really not a PASM master. Thankfully, PASM's design makes it accessible enough to guys like me.

    Thank you for your kind comment.
  • bsnutbsnut Posts: 521
    edited 2011-01-20 16:30
    It's another great article well done. This and PropBasic makes it simple & concise.
  • agsags Posts: 386
    edited 2011-02-09 09:29
    I've read (& re-read) the article (nice job), am relatively new to Propeller/PASM, and have successfully coded using both par and "poking". (Just to be sure I understand the terminology, is "poking" the method of declaring a named address in the DAT block, initializing that to some value in SPIN code, then launching a cog running PASM which will then have a named cog register containing the initialized value, which can be read & modified by PASM but is no longer accessible by SPIN?) I'm trying to get my head around this discussion and several things continue to elude me. I ask for clarification and am not intending to argue with those that have a greater understanding than I. Please help me be a better Prophead...
    localroger wrote: »
    I've taken pretty much to using the poke before launch method, because it saves lots of both Hub and Cog RAM, making it the superior method, period.

    If my definition of "poking" (above) is correct, then this method requires memory in hub RAM and cog RAM. Assuming n long values to be passed, a single SPIN object launching multiple PASM cogs would have n longs total in the SPIN cog and each spawned PASM cog would have n longs. With the par method, there will again be n longs in the SPIN cog and n longs per PASM cog to hold the local value. The difference I see is that each PASM cog requires extra instructions to calculate offset from the par address and rdlong into local cog RAM. Are the addidional instructions the incremental memory consumption being claimed? Putting the issue of ease of PASM code reuse with languages other than SPIN (which is beyond my understanding at this point), it seems then that the deciding factor would be: if the value can be determined before the PASM cog is launched, and does not need to be changed/queried by the SPIN code after launch, use the "poke" method. If the value cannot be calculated before the PASM cog is launched, or if the value needs to be read/modified by the SPIN code after launch, use the par method. Does this sound reasonable? Am I missing something?
    localroger wrote: »
    But he has a valid point that it makes PASM code harder to use with other languages.
    However, you can get around that too! If you make the first instruction of the Cog image a jump (which you then later use as the always-needed TMP var), followed by an ordered array of parameters, you can poke the parameter values into your PASM image from any language as long as you have the indeces.

    As I said, this is beyond me at this point - however, if any brave soul would like to take a shot at explaining further, I'd be grateful.
    ericball wrote: »
    Two other reasons to use a parameter block instead of poking values directly:
    1. Dynamic updates. Although it may be very rare to change some of the parameters for tv.spin there may be programs where that feature is useful.

    Yes, I (think I) understand, and agree. That does require some kind of polling/messaging that the PASM code implements in order to "see" that the value has been changed by the SPIN cog, correct?
    ericball wrote: »
    2. Avoids startup collisions. cognew takes ~8K cycles to load the cog. So bad things could happen if two SPIN objects both start the same cog at the same time, or one object invokes the start more than once in quick succession.

    I'm totally stymied regarding the first clause above. How is it possible for any configuration of any code start the same cog at the same time? Wouldn't one fail? I must be missing some key knowledge here.

    This comment does lead me to what might be the point (which I missed): if two instances of the same SPIN object each launch a PASM cog, and try to "poke" different values using DAT locations, there could be a conflict since while the VAR space is unique per SPIN object instance, the DAT space is shared. Is that what I'm missing? This in contrast to the par method, which uses a memory location in VAR, which is unique and not subject to collision.

    Still missing something on the second point too: two successive calls to start a new PASM cog would both pick up the same "poked" values, wouldn't they? What's the mechanism for conflict here? This does beg a related question that I've search the Propeller Manual for without success: does the SPIN cognew (or coginit) call return before the cog has been launched? If so, then I suppose if the "parent" SPIN object were to want to provide different values to be "poked" into the two "child" PASM cogs, the launch/modify-poked-values/launched sequence could pose a problem. Is that what's being discussed here? (I have presumed that the coginit/cognew SPIN instruction did not return until the launch was completed).
    Heater. wrote: »
    ...
    1)Dynamic updates.
    I presume that means changing parameters whilst the COG is running.

    I believe this is better done through a mailbox interface...

    I've searched unsuccessfull for more on the "mailbox" technique. Would someone point me towards further explanation on that? My guess at this point is that is something like a compound command (possibly passed with a "cmd" word through the par address) that might contain a "PO Box" (where it should go) and contents (the value used to update the PASM cog). Is this close?


    Thanks to anyone that attempts to help explain this.
Sign In or Register to comment.