Shop OBEX P1 Docs P2 Docs Learn Events
Spin: assigning a LONG into a BYTE — Parallax Forums

Spin: assigning a LONG into a BYTE

BasearsaBasearsa Posts: 5
edited 2013-03-24 23:57 in Propeller 1
Update: The code as supplied here actually does produce a blinking light.

This is my first forum post. I recently bought a Propeller, and have been having fun making LEDs blink.

Today I attempted something like the following, and was surprised that my LED did not turn on:
VAR
  byte _elements[10]
PUB Main
    repeat i from 0 to 9
        _elements[i] := True
    dira[0]~~
    outa[0]~~
    repeat

I eventually learned that my repeat block was never finishing. Changing my byte array to a long array resulted in expected output, as did replacing "True" with a number such as 1.

What is happening here? Is the propeller halting execution? It makes sense that a True being 0xffffffff cannot fit into a byte. I tried wrapping my repeat loop in a method and using the "\method" syntax to trap any implicit ABORT that might be happening, but that did not work. Perhaps I am not using the abort facilities correctly.

I suppose in this case I'll chose some other value to represent a TRUE and FALSE here, and then remember not to do a direct comparison with the real TRUE/FALSE constants later. Is there a more recommended approach to storing boolean values in a BYTE?

Comments

  • varnonvarnon Posts: 184
    edited 2013-03-23 22:27
    I think the answer is that true is -1. That simply doesn't fit into a byte.
    I always use 0 for false and 1 for true. Why is -1 true anyway? I'm sure there is a good reason, but it seems kind of strange.
  • JonnyMacJonnyMac Posts: 9,191
    edited 2013-03-23 23:20
    When you attempt to copy a larger variable into a smaller, the larger will get truncated. If, for example, you move -1 into a byte the value you get back is 255 because a byte is not signed. You can use the sign extension operators to recover that if you want. Just understand that in a byte you'll be limited to -128 to +127, but to use a signed value you'll have to move it back to a long.
    Why is -1 true anyway?

    All bits are set. False is $00000000, True is $FFFFFFFF

    In Spin, any non-zero value will evaluate as true.
  • Heater.Heater. Posts: 21,230
    edited 2013-03-23 23:55
    Varnon
    Why is -1 true anyway?

    In normal language "not true" is the same as "false" and "not false" is the same as "true".

    Let's say you only have one bit you have that "false" is represented by 0. Then for "true" we have "not false" or ~0 which is 1.

    When you have 32 bits of 0s for false then true becomes !0 which is 32 bits of 1s. Or $FFFFFFFF has hexadecimal.

    It just so happens that $FFFFFFFF in decimal is -1.

    Not so strange after all.

    Problems can arise when comparing values against true. That's because Spin treats any non-zero value as true in conditional statements. So things like 3 are also true even if the don't equal the defined value of true.
  • AribaAriba Posts: 2,690
    edited 2013-03-24 10:55
    Basearsa wrote: »
    This is my first forum post. I recently bought a Propeller, and have been having fun making LEDs blink.

    Today I attempted something like the following, and was surprised that my LED did not turn on:
    VAR
      byte _elements[10]
    PUB Main
        repeat i from 0 to 9
            _elements[i] := True
        dira[0]~~
        outa[0]~~
        repeat
    

    I eventually learned that my repeat block was never finishing. Changing my byte array to a long array resulted in expected output, as did replacing "True" with a number such as 1.

    What is happening here? Is the propeller halting execution? It makes sense that a True being 0xffffffff cannot fit into a byte. I tried wrapping my repeat loop in a method and using the "\method" syntax to trap any implicit ABORT that might be happening, but that did not work. Perhaps I am not using the abort facilities correctly.

    I suppose in this case I'll chose some other value to represent a TRUE and FALSE here, and then remember not to do a direct comparison with the real TRUE/FALSE constants later. Is there a more recommended approach to storing boolean values in a BYTE?

    With a variable i declared, the example works fine.
    VAR
      byte _elements[10]
    
    PUB Main : i
        repeat i from 0 to 9
            _elements[i] := True
        dira[16]~~
        outa[16]~~
        repeat
    
    I have only LEDs at pin 16..23, so I have changed the pin number.

    Andy
  • BasearsaBasearsa Posts: 5
    edited 2013-03-24 11:05
    JonnyMac wrote: »
    When you attempt to copy a larger variable into a smaller, the larger will get truncated. If, for example, you move -1 into a byte the value you get back is 255 because a byte is not signed.

    When I attempt to assign TRUE to a byte value to my repeat loop never exits. Truncation is what I was expecting to happen.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-03-24 11:10
    Basearsa wrote: »
    When I attempt to assign TRUE to a byte value to my repeat loop never exits. Truncation is what I was expecting to happen.

    Code?
  • BasearsaBasearsa Posts: 5
    edited 2013-03-24 11:10
    Ariba wrote: »
    With a variable i declared, the example works fine.

    The code I provided was a simplification of what I'm trying to do. Indeed, when I plug in this exact example into the IDE I get the expected behavior.
  • BasearsaBasearsa Posts: 5
    edited 2013-03-24 11:29
    I think I understand where my error is. Sorry for uploading a simplified example without actually testing it!

    It seems that when I write TRUE to an element of a BYTE array a LONG value is written to memory starting from the address of the BYTE.

    Here is an example which I have tested:

    Main.spin
    obj
        buffer : "BoundedBuffer"
    PUB Main
        buffer.start(10)
    
    
        dira[0]~~
        outa[0]~~
        repeat
    

    BoundedBuffer.spin
    CON
        MAX_SIZE = 10
    VAR
      byte _size
      byte _elements[MAX_SIZE]
      byte _index
    
    PUB Start(size) | i
        _index := 0
        _size := size
    
    
        if _size <= 0
            Return False
        if _size > MAX_SIZE
            Return False
    
    
        repeat i from 0 to _size - 1
            _elements[i] := True
    

    The code as it is written does not produce a lit LED. When I modify the VAR block in BoundedBuffer.spin such that _elements is declared after _index the light blinks. Am I correct that I must be overwriting memory?
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-03-24 15:43
    I'm not positive since I stopped looking once I saw the "<=" assignment, but I think you'll have more success using the comparison "=<". It's a Spin thing. If it ends with "=" it's an assignment.
  • kuronekokuroneko Posts: 3,623
    edited 2013-03-24 16:57
    To expand a bit further on the <=/=< issue, the first comparison determines that 10 is not less than 0 (FALSE, 0) and also assigns said value to _size. Further down your repeat loop will therefore run from 0 to -1, IOW it will set _elements[0] and _elements[-1] (same as _size) to 255 which in turn will mess up the exit condition handling for said repeat loop leading to further memory corruption.
  • BasearsaBasearsa Posts: 5
    edited 2013-03-24 23:57
    Thanks for your help. I haven't had a chance to work on this yet, but my incorrect use of the <= operator must be the problem. I don't know if I would have found the answer without it being pointed out.
Sign In or Register to comment.