Shop OBEX P1 Docs P2 Docs Learn Events
This shoud be easy, but... — Parallax Forums

This shoud be easy, but...

ArchiverArchiver Posts: 46,084
edited 2003-12-04 16:52 in General Discussion
This is a code style question. I know how to drive a pin low on the BS2. In3
= 0 or LOW 3 does the trick for pin 3. But if I want to be clear, I write

MyOutputPin CON 3
...
LOW MyOutputPin

Ok.. but if I want it to set to an arbitrary value, it's not so clear what
to do. What I want is...

SETPIN MyOutputPin, newValue 'SETPIN doesn't exist, but I wish it did

Now I know I can do
OUT3 = newValue
or even
MyOutputPinIs VAR IN3 'alias
MyOutputPinIs = newValue

but that leaves me with two definitions

MyOutputPin CON 3 '3
MyOutputPinIs VAR IN3 '3 again

to be tweaked whenever I move things around. That's not exactly the end of
the world, but it's still ugly. Is there an elegant solution?


Unrelated question: is there a document that describes the bytecode that the
BS2 interprets? I'd like to look into writing a compiler for a language less
like Basic that works with a BS2...

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2003-12-03 18:54
    There is a very elegant solution to the problem you outlined. This
    is found in the new compiler, version 2.1 beta available on the
    Parallax web site.

    MyOutputPin PIN 3

    with that established you can do
    high MyOutputPin ' makes it high output
    or
    MyOutputPin=1 ' makes it high output
    or
    INPUT MyOutputPin ' makes it an input
    or
    IF MyOutputPin=1 THEN .... ' tests it as an input
    or
    x = MyOutputPin ' an input value to a variable
    or
    pulsout MyOutputPin,1000 ' a constant 3 for pin number
    or
    pulseout 5+MyOutputPin,1000 ' either pin 5 or 6 depending on in3
    etc.
    note that the last one is tricky. It uses the input state of the pin
    when it is asked to reference it as part of a computation.

    The compiler figures out from the context whether to treat is as a
    variable reflecting the input state of the pin or as a constant
    referring to the pin number.

    There could be weird situations where you are not doing the obvious,
    In this form,
    MyOutputPin pin 3
    INPUT MyOutputPin
    the compiler will treat MyOutputPin as a constant. But suppose you
    really want to read the input state of p3, and then use that to turn
    either p0 or p1 into an input. Then you would have to do it this way:
    INPUT in3 ' would you ever want to do this?!!! maybe
    or this way
    MyOutputPin pin 3
    INPUT MyOutputPin+0 ' treats MyOutputPin as an input
    the computation forces the compiler to treat it as an input. That is
    like the last PULSOUT example above.

    On the other had, the compiler will treat
    MyOutputPin pin 3
    x = MyOutputPin
    as a request to read the input state of pin 3, not as x=3.

    If a pin is configured as an output, command executes that reads the
    pin, it will still actually read the state of the pin, not the state
    of the output register. So if something is forcing the pin
    externally, that is what you will see. The bottom line is, the
    compiler wizard will almost always get it right what you want to do.
    But think about it.

    If you are interested in the bytecode, take a look at Brian Forbes' book.
    http://members.aol.com/stamp2book/
    Also Chuck McManis' essay on the BS1 codes is still a good read, and
    especially so now that Parallax has given the BS1 new life in the new
    compiler.
    http://www.mcmanis.com/chuck/robotics/stamp-decode.html
    It is not as simple as you might think. It is variable length
    bitcode, not bytecode. These documents will let you appreciate the
    condensed thinking that went into cramming the whole interpreter into
    the limited memory of the PIC.

    -- Tracy






    >This is a code style question. I know how to drive a pin low on the BS2. In3
    >= 0 or LOW 3 does the trick for pin 3. But if I want to be clear, I write
    >
    >MyOutputPin CON 3
    >...
    >LOW MyOutputPin
    >
    >Ok.. but if I want it to set to an arbitrary value, it's not so clear what
    >to do. What I want is...
    >
    >SETPIN MyOutputPin, newValue 'SETPIN doesn't exist, but I wish it did
    >
    >Now I know I can do
    > OUT3 = newValue
    >or even
    > MyOutputPinIs VAR IN3 'alias
    > MyOutputPinIs = newValue
    >
    >but that leaves me with two definitions
    >
    >MyOutputPin CON 3 '3
    >MyOutputPinIs VAR IN3 '3 again
    >
    >to be tweaked whenever I move things around. That's not exactly the end of
    >the world, but it's still ugly. Is there an elegant solution?
    >
    >
    >Unrelated question: is there a document that describes the bytecode that the
    >BS2 interprets? I'd like to look into writing a compiler for a language less
    >like Basic that works with a BS2...
  • ArchiverArchiver Posts: 46,084
    edited 2003-12-03 22:45
    You might want to download our latest compiler (Version 2.1, Beta 1) as
    it supports PBASIC 2.5 syntax which has a new definition: PIN. The
    compiler is "smart" to know what you're doing when you use PIN. For
    example:

    MyOutputPin PIN 3

    You can do this:

    LOW MyOutputPin --> the compiler treats as LOW 3

    You can also do this:

    MyOutputPin = 1 --> the compiler treats as OUT3 = 1

    And this:

    status = MyOutputPin --> the compiler treats as status = IN3

    As you noted, you can't pass parameters to your own subroutines in
    PBASIC. But as pointed out in the second example above, you get that
    functionality with PBASIC 2.5.

    Instead of...

    SETPIN MyOutputPin, newValue

    You would use...

    MyOutputPin = newValue

    The only thing you have to make sure of is that DIRS bit for that pin is
    set to 1 to make it an output. Because of the way PIN works, you can
    even do this to handle the DIRS bit:

    DIRS.LOWBIT(MyOutputPin) = 1 --> using your example is the same as
    DIR3 = 1, making the pin an output.

    This is useful if your design changes and you move an output pin. By
    making a single change to your PIN definition, the rest of the program
    follows.

    -- Jon Williams
    -- Applications Engineer, Parallax
    -- Dallas Office





    Original Message
    From: Scott [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=gXxRfy2bDOd9mANyROzRl7djJXFfsWfeqyHxBLUMs8CR6Cxg99edlIHMUp8iNOABhU2lB-8vvxao]scott@m...[/url
    Sent: Wednesday, December 03, 2003 11:45 AM
    To: basicstamps@yahoogroups.com
    Subject: [noparse][[/noparse]basicstamps] This shoud be easy, but...


    This is a code style question. I know how to drive a pin low on the BS2.
    In3 = 0 or LOW 3 does the trick for pin 3. But if I want to be clear, I
    write

    MyOutputPin CON 3
    ...
    LOW MyOutputPin

    Ok.. but if I want it to set to an arbitrary value, it's not so clear
    what to do. What I want is...

    SETPIN MyOutputPin, newValue 'SETPIN doesn't exist, but I wish it did

    Now I know I can do
    OUT3 = newValue
    or even
    MyOutputPinIs VAR IN3 'alias
    MyOutputPinIs = newValue

    but that leaves me with two definitions

    MyOutputPin CON 3 '3
    MyOutputPinIs VAR IN3 '3 again

    to be tweaked whenever I move things around. That's not exactly the end
    of the world, but it's still ugly. Is there an elegant solution?


    Unrelated question: is there a document that describes the bytecode that
    the BS2 interprets? I'd like to look into writing a compiler for a
    language less like Basic that works with a BS2...



    To UNSUBSCRIBE, just send mail to:
    basicstamps-unsubscribe@yahoogroups.com
    from the same email address that you subscribed. Text in the Subject
    and Body of the message will be ignored.


    Your use of Yahoo! Groups is subject to
    http://docs.yahoo.com/info/terms/




    This message has been scanned by WebShield. Please report SPAM to
    abuse@p....
  • ArchiverArchiver Posts: 46,084
    edited 2003-12-03 22:48
    My buddy Tracy pointed out something that I know but didn't think of (it
    has been a long day...):

    Instead of:

    DIRS.LOWBIT(MyOutputPin) = 1

    use...

    OUTPUT MyOutputPin

    Dang ... I hate when I make things harder than they need to be....

    -- Jon Williams
    -- Parallax



    Original Message
    From: Jon Williams
    Sent: Wednesday, December 03, 2003 4:46 PM
    To: basicstamps@yahoogroups.com
    Subject: RE: [noparse][[/noparse]basicstamps] This shoud be easy, but...


    You might want to download our latest compiler (Version 2.1, Beta 1) as
    it supports PBASIC 2.5 syntax which has a new definition: PIN. The
    compiler is "smart" to know what you're doing when you use PIN. For
    example:

    MyOutputPin PIN 3

    You can do this:

    LOW MyOutputPin --> the compiler treats as LOW 3

    You can also do this:

    MyOutputPin = 1 --> the compiler treats as OUT3 = 1

    And this:

    status = MyOutputPin --> the compiler treats as status = IN3

    As you noted, you can't pass parameters to your own subroutines in
    PBASIC. But as pointed out in the second example above, you get that
    functionality with PBASIC 2.5.

    Instead of...

    SETPIN MyOutputPin, newValue

    You would use...

    MyOutputPin = newValue

    The only thing you have to make sure of is that DIRS bit for that pin is
    set to 1 to make it an output. Because of the way PIN works, you can
    even do this to handle the DIRS bit:

    DIRS.LOWBIT(MyOutputPin) = 1 --> using your example is the same as
    DIR3 = 1, making the pin an output.

    This is useful if your design changes and you move an output pin. By
    making a single change to your PIN definition, the rest of the program
    follows.

    -- Jon Williams
    -- Applications Engineer, Parallax
    -- Dallas Office





    Original Message
    From: Scott [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=E1XjpB2VIKR5jQOFRuOZCUdu3hFlaitZiJVmS_t-Ep3pAX5JGB1ucNxNAV4kFZpDUzo_G-Bm2A]scott@m...[/url
    Sent: Wednesday, December 03, 2003 11:45 AM
    To: basicstamps@yahoogroups.com
    Subject: [noparse][[/noparse]basicstamps] This shoud be easy, but...


    This is a code style question. I know how to drive a pin low on the BS2.
    In3 = 0 or LOW 3 does the trick for pin 3. But if I want to be clear, I
    write

    MyOutputPin CON 3
    ...
    LOW MyOutputPin

    Ok.. but if I want it to set to an arbitrary value, it's not so clear
    what to do. What I want is...

    SETPIN MyOutputPin, newValue 'SETPIN doesn't exist, but I wish it did

    Now I know I can do
    OUT3 = newValue
    or even
    MyOutputPinIs VAR IN3 'alias
    MyOutputPinIs = newValue

    but that leaves me with two definitions

    MyOutputPin CON 3 '3
    MyOutputPinIs VAR IN3 '3 again

    to be tweaked whenever I move things around. That's not exactly the end
    of the world, but it's still ugly. Is there an elegant solution?


    Unrelated question: is there a document that describes the bytecode that
    the BS2 interprets? I'd like to look into writing a compiler for a
    language less like Basic that works with a BS2...



    To UNSUBSCRIBE, just send mail to:
    basicstamps-unsubscribe@yahoogroups.com
    from the same email address that you subscribed. Text in the Subject
    and Body of the message will be ignored.


    Your use of Yahoo! Groups is subject to
    http://docs.yahoo.com/info/terms/




    This message has been scanned by WebShield. Please report SPAM to
    abuse@p....


    To UNSUBSCRIBE, just send mail to:
    basicstamps-unsubscribe@yahoogroups.com
    from the same email address that you subscribed. Text in the Subject
    and Body of the message will be ignored.


    Your use of Yahoo! Groups is subject to
    http://docs.yahoo.com/info/terms/




    This message has been scanned by WebShield. Please report SPAM to
    abuse@p....
  • ArchiverArchiver Posts: 46,084
    edited 2003-12-04 16:21
    This sequence:
    MyOutputPin Pin 3
    HIGH MyOutputPin ' makes p3 high output
    HIGH MyOutputPin+5 ' makes p8 high output
    I had said incorrectly, in the second case, the calculation would
    trick the compiler into reading MyOutputPin as an input with a value
    of 0 or 1, and end up making either p5 or p6 high, but that is not
    true. The compiler treats MyOutputPin as a constant=3, in the
    addition and makes p8 high.

    The same thing is true of a command like
    PULSOUT 5+MyOutputPin,1000.
    Where the compiler will treat MyOutputPin as a constant=3 and the
    pulse will appear on p8. If you really want the pulse to be output
    on a pin that depends on the state of a switch attached to
    MyOutputPin, you have to do this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    x =MyOutputPin ' either 0 or 1 depending on input level
    PULSOUT 5+x,1000 ' outputs the pulse on either p5 or p6
    or
    PULSOUT 5+in3,1000 ' that forces it to use the variable in3 and
    put the pulse on either p5 or p6.

    But consider this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    PULSOUT 5,1000*MyOutputPin+100
    In that usage the compiler does in fact treat MyOutputPin as in input
    and reads the 0 or 1 state of the pin and puts out either a short or
    a long pulse on p5.

    The compiler rule seems to be to use the PIN as a constant in
    locations where a pin reference is clearly called for by the syntax,
    but use PIN as a [noparse][[/noparse]0,1] input variable otherwise. But that is not
    quite the rule, I think. Jon pointed out that it is also treated as
    a CONstant when the PIN is an array index.

    For example, Jon pointed out this one:

    MyOutputPin PIN 3
    DIRS.LOWBIT(MyOutputPin) = 1

    A priori, it could either use MyOutputPin=3 and set p3 as an output
    (which is in fact what it does), or it could read p3 as an input and
    set either p0 or p1 as an output (but that is not the way it works).

    Similarly, if you have an array of variables, what happens when a PIN
    reference is used as the index?
    x var byte(16)
    MyOutputPin PIN 3
    x(MyOutputPin)=124 ' puts 124 into x(3)
    x(MyOutputPin+5)=124 ' puts 124 into x(8)
    It treats the PIN as a CONstant when used as the array index. If
    instead you want a program to select an array element depending on
    the state of a pin, you have to do something like this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    idx = MyOutputPin ' reads the state of the pin
    x(idx+5)=124 ' puts 124 into either x(5) or x(6) depending on
    the input from MyOutputPin.

    How about this one?...
    MyOutputPin PIN 3
    lookup
    MyOutputPin,[noparse][[/noparse]0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150],x
    does in fact treat MyOutputPin as an input, and the lookup will
    return either x=0 or x=10.

    And how about this?...
    switchA PIN 4
    switchB PIN 5
    switchC PIN 6

    For i=0 to 2
    INPUT switchA(i) ' does it use CONstant values 4,5,6?
    I don't know.
    debug dec switchA(i),cr ' it does read INput values in4,in5,in6
    next

    And the same on the output side:

    ledA PIN 4
    ledB PIN 5
    ledC PIN 6

    For i=0 to 2
    OUTPUT ledA(i) ' does it use values 4,5,6?
    ledA(i)=0 ' does it refer to out4, out5 and out6, like
    out4(i), & make all leds low?
    next
    ' I haven't tried this one yet, but I wouldn't count on it one way
    or the other without testing


    Enough. Like the subject says, this should be easy. And most of the
    time it is. I really like the new PIN directive. Still, you have
    to think about it, especially if you are doing some kind of indirect
    reference, and like Jon pointed out, you still have to set the
    direction of the pin correctly for assignment statements and for
    commands like IF or BRANCH that don't set the pin direction
    automatically.


    -- Tracy
  • ArchiverArchiver Posts: 46,084
    edited 2003-12-04 16:52
    I did a quick test myself. This little program...

    '{$STAMP BS2}
    '{$PBASIC 2.5}

    Led1 PIN 0
    Led2 PIN 1
    Led3 PIN 2

    Test:
    HIGH Led1
    PAUSE 500
    HIGH Led1 + 1
    PAUSE 500
    HIGH Led1 + 2
    END

    ... does what I expected: it lights LEDs on P0 - P2 in sequence. What I
    found (noting a comment near the bottom of Tracy's post) is that you
    can't use an array index with PIN. Hence,

    '{$STAMP BS2}
    '{$PBASIC 2.5}

    Led1 PIN 0
    Led2 PIN 1
    Led3 PIN 2

    idx VAR Nib

    Test:
    FOR idx = 0 TO 2
    HIGH Led1(idx) ' <-- ERROR
    PAUSE 500
    NEXT
    END

    ... won't compiler or download. But, of course, you can achieve the same
    result like this:

    '{$STAMP BS2}
    '{$PBASIC 2.5}

    Led1 PIN 0
    Led2 PIN 1
    Led3 PIN 2

    idx VAR Nib

    Test:
    FOR idx = 0 TO 2
    HIGH Led1 + idx
    PAUSE 500
    NEXT
    END


    -- Jon Williams
    -- Applications Engineer, Parallax
    -- Dallas Office



    Original Message
    From: Tracy Allen [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=1jLpJxmT5q6eylg5nk6FN1lKFTFCSI_GbXNS0WTkGz2nONJPpd31c8vY9vQHaGkWI7gCyzTR-mSzupzq]tracy@e...[/url
    Sent: Thursday, December 04, 2003 10:22 AM
    To: basicstamps@yahoogroups.com
    Subject: Re: [noparse][[/noparse]basicstamps] This shoud be easy, but...


    This sequence:
    MyOutputPin Pin 3
    HIGH MyOutputPin ' makes p3 high output
    HIGH MyOutputPin+5 ' makes p8 high output
    I had said incorrectly, in the second case, the calculation would
    trick the compiler into reading MyOutputPin as an input with a value
    of 0 or 1, and end up making either p5 or p6 high, but that is not
    true. The compiler treats MyOutputPin as a constant=3, in the
    addition and makes p8 high.

    The same thing is true of a command like
    PULSOUT 5+MyOutputPin,1000.
    Where the compiler will treat MyOutputPin as a constant=3 and the
    pulse will appear on p8. If you really want the pulse to be output
    on a pin that depends on the state of a switch attached to
    MyOutputPin, you have to do this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    x =MyOutputPin ' either 0 or 1 depending on input level
    PULSOUT 5+x,1000 ' outputs the pulse on either p5 or p6
    or
    PULSOUT 5+in3,1000 ' that forces it to use the variable in3 and
    put the pulse on either p5 or p6.

    But consider this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    PULSOUT 5,1000*MyOutputPin+100
    In that usage the compiler does in fact treat MyOutputPin as in input
    and reads the 0 or 1 state of the pin and puts out either a short or
    a long pulse on p5.

    The compiler rule seems to be to use the PIN as a constant in
    locations where a pin reference is clearly called for by the syntax,
    but use PIN as a [noparse][[/noparse]0,1] input variable otherwise. But that is not
    quite the rule, I think. Jon pointed out that it is also treated as
    a CONstant when the PIN is an array index.

    For example, Jon pointed out this one:

    MyOutputPin PIN 3
    DIRS.LOWBIT(MyOutputPin) = 1

    A priori, it could either use MyOutputPin=3 and set p3 as an output
    (which is in fact what it does), or it could read p3 as an input and
    set either p0 or p1 as an output (but that is not the way it works).

    Similarly, if you have an array of variables, what happens when a PIN
    reference is used as the index?
    x var byte(16)
    MyOutputPin PIN 3
    x(MyOutputPin)=124 ' puts 124 into x(3)
    x(MyOutputPin+5)=124 ' puts 124 into x(8)
    It treats the PIN as a CONstant when used as the array index. If
    instead you want a program to select an array element depending on
    the state of a pin, you have to do something like this:
    MyOutputPin Pin 3
    INPUT MyOutputPin ' it is an input
    idx = MyOutputPin ' reads the state of the pin
    x(idx+5)=124 ' puts 124 into either x(5) or x(6) depending on
    the input from MyOutputPin.

    How about this one?...
    MyOutputPin PIN 3
    lookup
    MyOutputPin,[noparse][[/noparse]0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150],x
    does in fact treat MyOutputPin as an input, and the lookup will
    return either x=0 or x=10.

    And how about this?...
    switchA PIN 4
    switchB PIN 5
    switchC PIN 6

    For i=0 to 2
    INPUT switchA(i) ' does it use CONstant values 4,5,6?
    I don't know.
    debug dec switchA(i),cr ' it does read INput values in4,in5,in6
    next

    And the same on the output side:

    ledA PIN 4
    ledB PIN 5
    ledC PIN 6

    For i=0 to 2
    OUTPUT ledA(i) ' does it use values 4,5,6?
    ledA(i)=0 ' does it refer to out4, out5 and out6, like
    out4(i), & make all leds low?
    next
    ' I haven't tried this one yet, but I wouldn't count on it one way
    or the other without testing


    Enough. Like the subject says, this should be easy. And most of the
    time it is. I really like the new PIN directive. Still, you have
    to think about it, especially if you are doing some kind of indirect
    reference, and like Jon pointed out, you still have to set the
    direction of the pin correctly for assignment statements and for
    commands like IF or BRANCH that don't set the pin direction
    automatically.


    -- Tracy


    To UNSUBSCRIBE, just send mail to:
    basicstamps-unsubscribe@yahoogroups.com
    from the same email address that you subscribed. Text in the Subject
    and Body of the message will be ignored.


    Your use of Yahoo! Groups is subject to
    http://docs.yahoo.com/info/terms/




    This message has been scanned by WebShield. Please report SPAM to
    abuse@p....
Sign In or Register to comment.