Shop OBEX P1 Docs P2 Docs Learn Events
Trying to figure out some problems (Dealing with "@" and passing var [Problem s — Parallax Forums

Trying to figure out some problems (Dealing with "@" and passing var [Problem s

James LongJames Long Posts: 1,181
edited 2009-04-17 06:07 in Propeller 1
Ok, so I'm not as versed with the propeller as most are around here, that will be obvious.

Here is what I'm doing, and where my problems occur.

I have a binary file on a SD card, with some format0 midi music. The eeprom has a simple boot loader file.

When booting the main binary gets loaded the and prop is rebooted with the new code. So far so good (it works).

After the reboot, I am trying to read values from a csv into a byte array (these values will be for outputs from the midi music, more on this later). <---- this is not working

After this, the program loads a midi file from a DAT play list. <
this works

Then the program plays the file using Aribas midi player object. While playing the midi file audio, I have a cog that is turning on outputs to a PCF8575 chip.

Right now, I have a lookdown statement that works. If the note comes along that is in the lookdown statement, the output that corresponds to that number will turn on on the PCF8575 (I'm using LED's to know).

I worked for 18 hours yesterday to try and load a byte array with 16 values from a csv file. I have tried so many different versions of doing this I am absolutely confused.

I do not understand when and where the "@" symbol is used with a variable (besides cognew, and DAT). I have to say, I don't know, and really need someone to explain it in a way I'll remember.

Also, I would like to use the lookdown command (because it is fast), but I can't seem to get it to work with a byte array. This may be because it was designed to be used on expressions (not sure if that includes bytes).

Here is some of the code that I have hacked on. It is probably not right. I've changed it so much, I'm not sure what right is any more.


Pub loadScript | _r, _cursor, _cuect, _outnum, _midinote, _out

'' Load the script from the SD card
     _cursor := @cueList                                                     ' Point at the cue list space -cuelist is the 128byte array 
    _r := sd.popen(@ScriptName, "r")                                  ' and open the script file
    if _r < 0                                                                       ' Check for successful open
      disp.cls
      disp.str(string("Config file fail!"))
      waitcnt(clkfreq*3 + cnt)
      abort                                                                          ' and abort if it failed
    disp.cls
    disp.str(string("Loading Config!"))
    waitcnt(clkfreq*3 + cnt)
    '_cueCt := 0
    repeat 
      _outnum := getnum                                                     ' Get the output number
      _midinote := getnum                                                   ' Get the note from the file
      bytemove(_cursor[noparse][[/noparse]_outnum],_midinote,1)                     ' Move the note into the word array
      _cursor += 1                                                              ' Move the cursor to the next values
      _cueCt += 1                                         
      if _cueCt == maxScriptSize                                          ' and be sure we don't overflow, should be 128
      quit
    elseif _cueCt > maxScriptSize
      bigscript                                                                      ' the array - if we do, tell the
      abort                                                                           ' user and abort
    else
      next

PRI getnum | n, num

'' Get a number or letter from the file

  num := 0
  repeat
    n := sd.pgetc                                      ' Get a character
    if n < 0                                               ' Return -1 for end of file
      abort
    case n
      13: quit                                             ' LF and
      44: quit                                             '   comma end a number
      48..57: num := num * 10 + n - 48                     ' Handle a digit
      65..76: num := 0                                         ' Map slat letters A thru L to 1 thru 12
  return num






If I get this part right, then I need to move to the part wher I'm trying to look through these vars.

That is a chore, because culist[noparse][[/noparse]128] needs to be passed to a child object. BLAH!!!

James L

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
James L
Partner/Designer

Lil Brother SMT Assembly Services

Post Edited (James Long) : 4/17/2009 8:11:33 AM GMT

Comments

  • Chris MicroChris Micro Posts: 160
    edited 2009-04-16 18:46
    Somebody said...
    I do not understand when and where the "@" symbol is used with a variable (besides cognew, and DAT). I have to say, I don't know, and really need someone to explain it in a way I'll remember.
    The '@' symbol is used to get the @ddress of a variable.

    this means
    LONG x
    LONG AddressOfx

    x:=1234
    AddressOfx:=@x

    where as "AddressOfx" points to some memery location
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 18:50
    Chris Micro said...
    Somebody said...
    I do not understand when and where the "@" symbol is used with a variable (besides cognew, and DAT). I have to say, I don't know, and really need someone to explain it in a way I'll remember.
    The '@' symbol is used to get the @ddress of a variable.

    this means
    LONG x
    LONG AddressOfx

    x:=1234
    AddressOfx:=@x

    where as "AddressOfx" points to some memery location

    Ok, granted that makes sense.

    When do you use the variable, and when do you use the address?

    This is the major confusion.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • Chris MicroChris Micro Posts: 160
    edited 2009-04-16 18:56
    Somebody said...
    When do you use the variable, and when do you use the address?

    As far as I know you use an address when you want to pass an array to a function.
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 18:58
    Chris Micro said...
    Somebody said...
    When do you use the variable, and when do you use the address?

    As far as I know you use an address when you want to pass an array to a function.

    Is that the only time??

    I have seen code that confuses me in that respect.

    Here is some code that confuses me.

    PRI loadScript | _r, _cursor, _cuect, _cuenum, _delay, _bank, _slat, _cue, _desc1, _desc2
    
    '' Load the script from the SD card
    
      _cursor := @cueList                                      ' Point at the cue list space 
      _r := sdfile.popen(@ScriptName, "r")                     '   and open the script file
      if _r < 0                                                ' Check for successful open
        abort                                                  '   and abort if it failed
    
      _cuect := 0
      repeat                                                   ' Loop through the cues
        _cuenum := getnum                                      ' Get the cue number
        wordmove(_cursor,@_cuenum,1)                           '   and save it in the cue list
        _delay := getnum                                       ' Now get the delay
        wordmove(_cursor+2,@_delay,1)                                
        _bank := getnum                                        ' Get the bank,
        _slat := getnum                                        '   slat,
        _cue := getnum                                         '   and cue and
        _r := (_bank << 8) + (_slat << 4) + _cue               '   pack them into one word
        wordmove(_cursor+4,@_r,1)                                
        IF _bank == 7                                          ' Bank 7 indicates a MIDI file
          _r := getfn                                          '   so read a filename
        ELSE                                                   ' Otherwise
          _desc1 := getnum                                     ' Get the first description number
          _desc2 := getnum                                     '   and the second and 
          _r := (_desc1 << 8) + _desc2                         '   and pack them into a word
        wordmove(_cursor+6,@_r,1)                                
        _cursor += 8                                           ' Move the cursor to the next cue
        
        if _cuenum == 0                                        ' The end of the script is indicated by
          quit                                                 '   a zero cue number
        _cuect += 1                                            ' Count the cues
        if _cueCt == maxScriptSize                             '   and be sure we don't overflow 
          cuetracker.bigscript                                 '   the array - if we do, tell the
          abort                                                '   user and abort
          
      if cueList <> 9999                                    ' Warn the user if their script does 
        cuetracker.nopause                                     '   not start out paused
      cuetracker.cuectmsg(_cuect)                              '   and let them know we got it loaded
    
    
    



    This code is to load a csv file from a SD card. I did not write this code, it is from a Propeller contest project. It evidently worked for the project.

    Let me explain why this confuses me. Wordmove requires two addresses. I understand that _cursor is equal to @cueList. The problem I have with this code, how can _cursor be an array when it is a local variable of only a long? In the VAR section of the Object cuelist is huge.

    Maybe I need to learn more about addresses and understanding them.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services

    Post Edited (James Long) : 4/16/2009 7:13:24 PM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-04-16 19:37
    Hello James,

    the codeline

      wordmove(_cursor,@_cuenum,1)  
    
    



    move only ONE word =16 bit

    it copies the ADRESS of "_cuenum" (the RAM-ADDRESS where the array _cuenum BEGINS) to the variable "_cursor"
    and an adress always fits into one long. This means "_cursor" contains just the RAM-ADRESS that POINTS to the begin of the array

    The rest of the code I do not understand by reading it once or twice.
    And it shows only a part of the program

    what does getnum do in detail?
    what does bigscript do in detail?

    If I would program reading in a CSV-file I would start from scratch
    by using the elementary commands to read single bytes from the SD-card to learn how
    SD-card read and write works

    best regards

    Stefan
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-04-16 19:38
    _cursor is a long variable which holds the adress of the byte array, it's not the byte array itself.
    That's why in wordmove it reads _cursor and not @_cursor even if wordmove expects two adresses.

    let's have a look at the hypotetical memory adresses of the byte array and it's content:
    $1000 "H"
    $1001 "e"
    $1002 "l"
    $1003 "p"
    ....

    _cursor := @byte_array[noparse][[/noparse]0] ' so _cursor has the value $1000 and not "H"

    wordmove( _cursor, @r, 1) would now be the same as wordmove( @byte_array[noparse][[/noparse]0] , @r, 1)

    Pointers can be used the same way as the [noparse]/noparse inside of a function. If you have to pass an array to another function it wouldn't be a good idea to put the whole array on the stack. That's when pointers to are very helpful.
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 19:46
    StefanL38 said...
    Hello James,

    the codeline

      wordmove(_cursor,@_cuenum,1)  
    
    



    move only ONE word =16 bit

    it copies the ADRESS of "_cuenum" (the RAM-ADDRESS where the array _cuenum BEGINS) to the variable "_cursor"
    and an adress always fits into one long. This means "_cursor" contains just the RAM-ADRESS that POINTS to the begin of the array

    The rest of the code I do not understand by reading it once or twice.
    And it shows only a part of the program

    what does getnum do in detail?
    what does bigscript do in detail?

    If I would program reading in a CSV-file I would start from scratch
    by using the elementary commands to read single bytes from the SD-card to learn how
    SD-card read and write works

    best regards

    Stefan

    Stefan,

    Thanks for the help,

    Getnum uses the SD card access object to get characters from an SD file. The Pri method of the first post contains it's code. It gets a character one at a time, until it hits a comma, or a line feed.

    Bigscript is just a method to display to the LCD that the file is too large. (we have received too much information).

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 19:49
    MagIO2 said...
    _cursor is a long variable which holds the adress of the byte array, it's not the byte array itself.
    That's why in wordmove it reads _cursor and not @_cursor even if wordmove expects two adresses.

    let's have a look at the hypotetical memory adresses of the byte array and it's content:
    $1000 "H"
    $1001 "e"
    $1002 "l"
    $1003 "p"
    ....

    _cursor := @byte_array[noparse][[/noparse]0] ' so _cursor has the value $1000 and not "H"

    wordmove( _cursor, @r, 1) would now be the same as wordmove( @byte_array[noparse][[/noparse]0] , @r, 1)

    Pointers can be used the same way as the [noparse]/noparse inside of a function. If you have to pass an array to another function it wouldn't be a good idea to put the whole array on the stack. That's when pointers to are very helpful.

    So we use addresses to move things around and tell other parts of the Spin program where to find the data. But when actually working with the data, we must use the actual var, not it's address. So, I think where I was getting to confused is between the byte and where the byte is located.

    So by your example.

    _cursor := @byte_array[noparse][[/noparse]0] 'would make cursor a value of $1000 <---- we use this to pass out to other methods and objects for them to know where the values are
    _cursor := byte_array[noparse][[/noparse]0] 'would make cursor a value of "H" <---- we use this when the other object/method wants to use the data contained within.

    I see the difference and now I think I can remember that.

    Let me see if I can rewrite the code to reflect what you have stated.

    EDITED slightly to help other people understand if they do not.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services

    Post Edited (James Long) : 4/16/2009 8:11:34 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-04-16 20:32
    No, you don't have to use the actual var name. It's equivalent. If you like pointers you can always work with pointers! And in the function which is called you have to use the pointers! You pass the pointer for several reasons:
    1. If you have an array it would be a waste of stack to put all elements of the array to the stack in a function call -> using a pointer helps
    2. If you call functions of another object this object does not know any of your variables -> using a pointer is the only way to let the object access your variables
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 20:47
    MagIO2 said...
    No, you don't have to use the actual var name. It's equivalent. If you like pointers you can always work with pointers! And in the function which is called you have to use the pointers! You pass the pointer for several reasons:
    1. If you have an array it would be a waste of stack to put all elements of the array to the stack in a function call -> using a pointer helps
    2. If you call functions of another object this object does not know any of your variables -> using a pointer is the only way to let the object access your variables

    For some reason I don't think I have everything totally correct.

    I think I'm getting closer, but still, not sure where the problem lies.

    I'm going to attach the code that is relevant. I would attach the total code, but it is huge, and clanky to go through. I have a lot of cleaning to do of items I'm not using.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 20:53
    I think I'm having problems when I pass the address to the new cog. This has always been a hurdle for me. I'm fine until I need to deal with a new cog.

    
    PUB Main | dispcog
    
      sd.start(@ioControl)                                  'Start SD card driver
      lightout.start(@cueList)                              'Start the outputs and turn the outputs off
      disp.start(7,19200,2)                                 'Start the LCD Display 
      disp.cls               
    
    
    



    The above is where the new cog is called. "lighout" is the following:

    
    PUB Start(cueListaddr) | Out
    
      IO.set_Pins(6,5)
      Out:= %0000_0000_0000_0000
      IO.Initialize
      IO.OUT(ADDR,Out)
      
      cognew(main(@ledstate, @note, cueListaddr), @ledaddr)
      
    PUB main(ledstateaddr, noteaddr, cueListaddr)
    
        Noteout := getled(note, cueListaddr)
        'Noteout := note
        if Noteout == 0
          return
        If ledstate == $90
          noteout -= 1
          LED|= |< noteout
          IO.OUT(ADDR,LED)
        else
          noteout -= 1
          LED&= !|< noteout
          IO.OUT(ADDR,LED)
        noteout~
    
    
    PUB GETLED(Value, cueListaddr)| GETLEDS, revalue
    
        'GETLEDS := lookdown(Value: 74, 73, 72, 70, 69, 68, 67, 65, 51, 53, 56, 58, 60, 61, 62, 63)
        GETLEDS := lookdown(Value: cueListaddr, cueListaddr, cueListaddr, cueListaddr, cueListaddr, cueListad -----code clipped for sanity----) 
    
      {repeat GETLEDS from 1 to 128
        if value == cuelistaddr[noparse][[/noparse]getleds]
          revalue := getleds
          return revalue
          quit
        else
          next}
    
    



    Notice I have some items disabled, for testing purposes. Mostly in the last method.

    
     synth.noteOn(d1,ch,d2)                'Note On
                       'nout := GETLED(d1)  
                       lightout.main($90,d1,@cuelist) 
    
    
    



    The above are the calling routines to the lighout cog.

    I'm so confused.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services

    Post Edited (James Long) : 4/16/2009 9:45:12 PM GMT
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-04-16 21:38
    The lookdown seems to be wrong. You don't want to lookup the adress, but the values stored at the adress , right? ... and the following bytes? words? longs? ... can't find the type in the code snippets.

    Depending on the type you have to use
    ... byte[noparse][[/noparse] cueListaddr ], byte[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], byte[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8]....
    ... word[noparse][[/noparse] cueListaddr ], word[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], word[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8] ...
    or ... long[noparse][[/noparse] cueListaddr ], long[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], long[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8] ...

    byte[noparse]/noparse, word[noparse]/noparse and long[noparse]/noparse in the code section allows you to access any byte, word or long in HUB memory. This is how you can access the value that a pointer points to.
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 21:46
    MagIO2 said...
    The lookdown seems to be wrong. You don't want to lookup the adress, but the values stored at the adress , right? ... and the following bytes? words? longs? ... can't find the type in the code snippets.

    Depending on the type you have to use
    ... byte[noparse][[/noparse] cueListaddr ], byte[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], byte[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8]....
    ... word[noparse][[/noparse] cueListaddr ], word[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], word[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8] ...
    or ... long[noparse][[/noparse] cueListaddr ], long[noparse][[/noparse] cueListaddr ][noparse][[/noparse]7], long[noparse][[/noparse] cueListaddr ][noparse][[/noparse]8] ...

    byte[noparse]/noparse, word[noparse]/noparse and long[noparse]/noparse in the code section allows you to access any byte, word or long in HUB memory. This is how you can access the value that a pointer points to.

    The [noparse]/noparse addresses are in the code, not sure why they don't show.

    But you are right, I do want to address the information contained in the address.

    I didn't think about the "byte" command.

    I'll try that next.

    Am I even passing the parameter right? For some reason I always get confused of how to pass parameters.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • MagIO2MagIO2 Posts: 2,243
    edited 2009-04-16 22:06
    You found a good solution for that by yourself - maybe you did not recognize it yet ;o)

    Add a postfix _addr to the variable name if it is a pointer. Then you simply need to know what the function expects - the real value or an adress.

    If the function wants a pointer, you have to pass @var1 or var1_addr.
    If the function wants a real value, you have to pass var1 or byte[noparse][[/noparse] var1_addr ] or in case of an byte array byte[noparse][[/noparse] var1_addr ][noparse][[/noparse] index ]
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 22:24
    MagIO2 said...
    You found a good solution for that by yourself - maybe you did not recognize it yet ;o)

    Add a postfix _addr to the variable name if it is a pointer. Then you simply need to know what the function expects - the real value or an adress.

    If the function wants a pointer, you have to pass @var1 or var1_addr.
    If the function wants a real value, you have to pass var1 or byte[noparse][[/noparse] var1_addr ] or in case of an byte array byte[noparse][[/noparse] var1_addr ][noparse][[/noparse] index ]

    Ok, so I have added in byte[noparse][[/noparse]cuelist_addr][noparse][[/noparse]x] into the lookdown (changed them all to reflect this)

    Still not sure what is happening.

    I think my newcog calls and method calls passing the parameter are wrong.

    James L

    On a secondary note, do you accept checks for tutoring service?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • James LongJames Long Posts: 1,181
    edited 2009-04-16 23:44
    On a secondary note, would the items stored in cuelist_addr need to be strings?

    In the manual, it states Lookdown uses "Expressions". I wonder if anyone could define that in this instance.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
  • James LongJames Long Posts: 1,181
    edited 2009-04-17 06:07
    I would like to thank everyone who input on my misunderstanding of pointers, addresses, and parameters.

    I finally got the call to work. Not the way I wanted to, but still, it works.

    the part which gave the trouble follows:

    
    repeat 
          _outnum := getnum                                 ' Get the output number
          _midinote := getnum                               ' Get the note from the file       
          bytemove(_cursor,@_midinote,1)                    ' Move the note into the word array 
          _cursor += 1                                      ' Move the cursor to the next values
    
    
    



    I was trying to use _outnum to set the index of _cursor (ie. _cursor[noparse][[/noparse]_outnum] or _cursor[noparse][[/noparse]@_outnum] ). I never got a successful result from doing this. I'm not sure what I was doing wrong, but the method above works the same (well somewhat).

    I appreciate the help, and if any of you need any pcb assembly, let me know.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services
Sign In or Register to comment.