Shop OBEX P1 Docs P2 Docs Learn Events
Array of objects question — Parallax Forums

Array of objects question

jazzedjazzed Posts: 11,803
edited 2008-03-23 22:31 in Propeller 1
Anyone care to explain why I don't get·6 "Hello World!" lines from this spin program ?

CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
' _clkmode = xtal1 + pll8x
' _xinfreq = 10_000_000
OBJ
  s[noparse][[/noparse]6]: "FullDuplexSerial"
PUB main | ii
  repeat ii from 0 to 5
    s[noparse][[/noparse]0].start(31,30,0,28800)
  s[noparse][[/noparse]0].rx ' pause for user
  repeat ii from 0 to 5
    s[noparse][[/noparse]ii].str(string("Hello World!",$d))


TIA

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

Traffic is slow at times, but Parallax orders·always get here fast 8)

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-23 16:50
    The separate FullDuplexSerial objects are really separate. They each have to be initialized and have to be on separate I/O pins. They each take a cog as well. In your case, you're initializing the first one, but attempting to use all of them.
  • jazzedjazzed Posts: 11,803
    edited 2008-03-23 17:17
    Ok, If I change the original code to listing below, I can see data being transmitted on pins 1-5.

    Why is it that if i use one set of pins, the output fails to print one line ?

    If I change "s[noparse][[/noparse]ii].start(ii+5,ii,0,28800)" to "s[noparse][[/noparse]ii].start(31,30,0,28800" for example,
    I get "Hei" and that's it.

    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    ' _clkmode = xtal1 + pll8x
    ' _xinfreq = 10_000_000
    OBJ
      s[noparse][[/noparse]6]: "FullDuplexSerial"
    PUB main | ii
      ii := 0
      s[noparse][[/noparse]ii].start(31,30,0,28800)
      s[noparse][[/noparse]ii].rx ' pause for user
      s[noparse][[/noparse]ii].str(string("Hello World!",$d))
      repeat ii from 1 to 5
        s[noparse][[/noparse]ii].start(ii+5,ii,0,28800)
      repeat
        repeat ii from 1 to 5
          s[noparse][[/noparse]ii].str(string("Hello World!",$d))
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

    Traffic is slow at times, but Parallax orders·always get here fast 8)
  • hippyhippy Posts: 1,981
    edited 2008-03-23 17:48
    All outputs from individual cogs are OR'd so unless each cog is outputting exactly the same on its own TX pin the combined TX will be corrupted. Also, Pin 31 TX is active-low / idle-high so whenever one cog isn't transmitting the line will remain high.

    The "Hei" is the start of the first s[noparse][[/noparse]ii].str(...) before you kick the next cogs into action with their start(). As soon as they kick in they force Pin 31 high, corrupting the last character you saw and putting the line high.

    That's my 'best guess' anyway.
  • jazzedjazzed Posts: 11,803
    edited 2008-03-23 18:24
    Thanks Mike and Hippy.

    From a high level the answers are clear. There are some ASM questions related to this whose answers are unclear:

    1. If i declare variables in the DAT section as is done in the serial object, are these considered global or local?
    On the transmit side of the object as in the example above, the variables seem to be mutually exclusive.

    2. Is the RES declaration for variables in the serial object making the variables local to cog ram ?

    3. If I use selfmodifying code in an ASM object pointing to RES or LONG data, will this change be only local to the COG?

    TIA

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

    Traffic is slow at times, but Parallax orders·always get here fast 8)
  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-23 19:19
    Variables declared in a VAR section are unique to each instance of an object.
    Variables declared in a DAT section are common to all instances.

    You have to remember that a cog is started by copying a block of 512 longs to the cog's memory from hub memory. The last 16 longs are special registers which are zeroed if they're read/write, but the cog goes through the motions of copying 512 longs. If the data in hub memory is less than 512 longs, whatever stuff is beyond is copied anyway. BYTE / WORD / LONG actually allocate space in hub memory and initialize it (as do instructions). RES just advances the cog memory address so labels get declared properly in cog memory, but there's no storage actually allocated or initialized. That's why RES has to be last in the DAT section.

    When the code actually executes, any use of RES or LONG data is cog memory. The only way to access hub memory is with the hub instructions (RDxxxx / WRxxxx).
  • jazzedjazzed Posts: 11,803
    edited 2008-03-23 19:50
    Mike, this is all correct as far as I can tell and useful infomation. I truly appreciate your time and insight.

    However, unless the FullDuplexSerial.spin ASM variables in the DAT section are mutually exclusive,
    I don't see how 6 separate instances of the object could work correctly. Please explain.

    If the cog is started by copying a block of longs, then how can the DAT section variables be common?
    I know from experience that DAT variables are common. This is very confusing.

    Also if a block is copied for the cog, I assume all code would be mutually exclusive at run time; correct?
    I am very concerned about self-modifying code only being changed within one cog and not others.

    TIA

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

    Traffic is slow at times, but Parallax orders·always get here fast 8)
  • OwenSOwenS Posts: 173
    edited 2008-03-23 20:24
    DAT variables are common for SPIN programs, since the programs themselves never touch cog memory (Except for accessing registers such as INA, OUTA, DIRA and for maintaining their internal state)

    Assembly instructions all operate on cog local variables except for the WRLONG/WRWORD/WRBYTE instructions, which write to hub ram, and RDLONG/RDWORD/RDBYTE instructions, which read from hub ram.

    Any changes in cog ram do not affect those in hub ram. Any changes in hub ram don't affect cog ram.

    Any values that are specific to a single instance of a spin object will be stored in a VAR section, and a pointer to them passed to the cog when it is started.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-23 20:34
    Again, once the DAT information is copied to the cog, the cog is on its own. It has no access to the internals of any other cog and, like I said, the only access to hub memory is with the RDxxxx / WRxxxx instructions. The reason I mentioned about the DAT section being shared is that it is shared. Usually it only contains constant information, so that doesn't matter. As an example, I'm working on a multi-file version of the SD card FAT file system routines. Each instance (VAR) contains an I/O buffer and some variables that describe the current file position and status. There's a shared area that contains another I/O buffer used to access the directory and variables used to describe the current volume.
  • jazzedjazzed Posts: 11,803
    edited 2008-03-23 20:53
    Thanks guys.

    So DAT vars are common for SPIN (hub), but not ASM (cog). Former is supported by tons of experience; the latter is still questionable. Yes RD/WR* instructions clearly access hub memory ... no questions there [noparse]:)[/noparse]

    I'll continue on the thesis that once a cog is started, it's DAT instructions and variables are his/her own and no other cog accesses them (i must have a bug in my asm project that fools me into believing otherwise). Thanks for your patience [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

    Traffic is slow at times, but Parallax orders·always get here fast 8)
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-23 21:27
    This may sound like splitting hairs, but it's not fully accurate to say DAT variables are not common in ASM. What Mike was saying is that if a DAT location is part of the 496 LONG locations following the start of a assembly routine, once the cog is loaded, the copy of the location becomes it's own entity within the cog, however the original·remians shared. It all depends on how the memory location is used. If a memory location is altered (in·a non-read-modify-write manner)·in preperation for that location to be loaded into a cog via cognew or coginit, then the location is used in non-shared manner. However if the location is altered in the normal course of operation either in spin or via wrlong/rdlong, etc, that alteration will be seen by all instances and is therefore shared.

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

    Parallax, Inc.

    Post Edited (Paul Baker (Parallax)) : 3/23/2008 9:36:08 PM GMT
  • jazzedjazzed Posts: 11,803
    edited 2008-03-23 22:31
    Thanks Paul. Your explanation is mostly consistent with what I'm seeing.
    Looking at the FullDuplexSerial code however, some variables t1,t2,etc... are
    manipulated by rd/wr* instructions, so that is still an open question for me.

    Nevertheless ... I am very happy now because ...
    In the program I'm developing, I changed the variables that I want to keep local
    from initialized "var long x" to "var res 1" and the scope appears to be cog local now.
    Too bad I had to add zeroing code at startup for the RES variables ... oh well.

    Thanks Guys.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    jazzed·... about·living in·http://en.wikipedia.org/wiki/Silicon_Valley

    Traffic is slow at times, but Parallax orders·always get here fast 8)
Sign In or Register to comment.