Saturday, February 4, 2012

Learned something new about Spin

I did a little study related to my previous post where I was befuddled about parameter passing in Spin for the Propeller.  To review...

Passing parameters to a method looks like this

  BYTE a
  WORD b
  LONG c

foo(a, b, c)

On the receiving end, we declare foo like this

PUB foo(x, y, z)

This is confusing to me when compared to other languages.  On the calling end, I can declare the size of the data.  I am passing a byte, word and long to foo.  On the receiving end, x, y and z are all longs.  Furthermore, if you declare any local variables, they are longs too.  For example:

PUB FOO(x, y, z) | i, j, k

So, when you pass a parameter, regardless of the size of the data, it is first converted to a long and the called method will receive it as a long.

However, you can also pass an address as a parameter.  Remember, my example was passing my callsign, locator, power and the symbol table to my encodeWSPR method.  This example is working:

  BYTE sym[162]

  WSPR : "ko7mWSPREncode"

WSPR.encodeWSPR(string("KO7M "), string("CN87"), 27, @sym)

While this version yielded different results:

  mycall BYTE "KO7M ", 0
  myloc BYTE "CN87", 0
  mypwr BYTE 27

WSPR.encodeWSPR(@mycall, @myloc, @mypwr, @sym)

The issue here is that I am trying to make this same method handle two different format parameters.  Namely, the third parameter is the WSPR power setting.  In the first example, I am passing the value 27 in the parameter list.  This gets converted to a long and assigned to the third parameter in the call to encodeWSPR.  It then needs to be treated as a long value in the method.  In the second example, I am passing the address of a byte containing the power value.  The address gets converted to a long and assigned to the third parameter.  In the method, I have to then treat it as the address of a byte rather than as a long value.  For example:

encodeWSPR(call, loc, power, sym) | pwr

pwr := BYTE[power]

So, the reason my encodeWSPR was returning different results is that I was using the power parameter in different ways while the method was expecting to receive a long containing the value, not the address of it.  Bonehead...

So, I have to decide which way it is going to be as it cannot be both in the same method.  I can provide other methods that allow either kind of parameter to be passed or separate methods to set each parameter even.  My inclination is to pass the power by value rather than by reference.  Any preferences?


  1. "By reference" (in any programming language) gives you more flexibility over "by value", at the cost of forcing you to be more careful how you write your code, since your called functions can potentially introduce alterations into data defined by the calling function.

    In summary: Spin is weird, arbitrary and (IMHO) encourages confusing code to be written. Thank Gracey for PASM!

  2. Indeed! It is a bit strange, for sure!