November 24, 2024, 10:57:10 PM

News:

You can now use Vixen to program your Prop-1 and Prop-2 controllers!  Get started quickly and easily, without having to learn PBASIC.  Details in the Library forum.


PINS syntax question

Started by Jeff Haas, October 03, 2015, 06:18:23 PM

Previous topic - Next topic

Jeff Haas

I'm stuck on the use of PINS.  There are some demo programs for the Prop-1 and the Trainer that use PINS to update the outputs, like this one:


' =========================================================================
'
'   File...... Branch LEDs
'   Purpose... Demonstrate two different types of behavior depending on button press
'   Author....
'   E-mail....
'   Started...
'   Updated...
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================

' -----[ Program Description ]---------------------------------------------
' Install Prop-1 Trainer on a Prop-1.

' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  Sio             = 7                     ' SETUP = UP; no ULN
SYMBOL  Trigger         = PIN6                  ' SETUP = DN


' -----[ Constants ]-------------------------------------------------------


SYMBOL  Yes             = 1
SYMBOL  No              = 0

SYMBOL  TrOn            = 1                     ' active-high trigger
SYMBOL  TrOff           = 0

SYMBOL  IsOn            = 1                     ' active-high I/O
SYMBOL  IsOff           = 0

SYMBOL  Baud            = OT2400


' -----[ Variables ]-------------------------------------------------------

SYMBOL  last            = B2                    ' for debounce loop
SYMBOL  idx             = B3

SYMBOL  lottery         = W5


' -----[ Initialization ]--------------------------------------------------

Power_Up:
  ' put code here that only happens at power-up/hard reset

Reset:
  PINS = %00000000                              ' all off
  DIRS = %00111111                              ' P5..P0 are outputs


' -----[ Program Code ]----------------------------------------------------

Main:
  BRANCH Trigger, (Ping_Pong, Scrambler)        ' jump based on trigger


Ping_Pong:
  IF last = 0 THEN PP_Next                      ' if still pp, skip
    idx = 0                                     ' reset to start of cycle

PP_Next:
  DEBUG "idx: ", #idx, " "
  READ idx, PINS                                ' copy pattern to pins
  idx = idx + 1 // 10                           ' update, wrap around
  PAUSE 350                                     ' sequence timing delay
  last = 0                                      ' mark running pp sequence
  GOTO Main                                     ' re-test trigger


Scrambler:
  DEBUG "idx: ", #idx, " "
  FOR idx = 1 TO 3                              ' big scramble
    RANDOM lottery
  NEXT
  PINS = lottery                                ' random value to pins
  PAUSE 100
  last = 1                                      ' mark running scrambler
  GOTO Main


' -----[ Subroutines ]-----------------------------------------------------


' -----[ User Data ]-------------------------------------------------------

Ping_Leds:
  EEPROM (%00000001, %00000010, %00000100, %00000001, %00001000, %00000010)

Pong_Leds:
  EEPROM (%00100000, %00010000, %00001000, %00000100, %00000010, %00000001)


There's one use of PINS in PP_Next and another in Scrambler. 

But take a look at this code, it's stripped down to the basics and I can't figure out why the LED doesn't light in Task_1.  Without that use, the program works fine - you press the button on the Trainer and it branches correctly, lighting the LED - but I know I'm tired and missing something.

' =========================================================================
'   File......   1 to 6 in order.bs1
'   Purpose...   Test BRANCH in order, based on BRANCH example in Help file
'   Author....   Jeff Haas
'   E-mail....
'   Started...   10/3/2015
'   Updated...
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================

' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  Trigger         = PIN6                   ' SETUP = DN


' -----[ Constants ]-------------------------------------------------------

SYMBOL  IsOn            = 1                     ' for active-high in/out
SYMBOL  IsOff           = 0

' -----[ Variables ]-------------------------------------------------------

SYMBOL  idx        = B3
SYMBOL  timer      = B2

' -----[ Initialization ]--------------------------------------------------

  PINS = %00000000                              ' all off
  DIRS = %00111111                              ' P5..P0 are outputs


' -----[ Program Code ]----------------------------------------------------

Main:

Check_Trigger:

  PAUSE 5                                       ' loop pad
  timer = timer + 5 * Trigger                   ' update timer
  IF timer < 50 THEN Check_Trigger             ' wait for 0.1 sec input

  DEBUG "idx: ", #idx, " "
  BRANCH idx, (Task_0, Task_1, Task_2, Task_3, Task_4, Task_5)  ' branch to task
  DEBUG "BRANCH target error..."        ' ... unless out of range
  DEBUG CR, CR

Next_Task:
  idx = idx + 1 // 6                    ' force idx to be 0..5
  GOTO Main


Task_0:
  DEBUG "BRANCHed to Task_0", CR
  PIN5 = IsOff                       
  PIN0 = IsOn
  GOTO Next_Task

Task_1:
  DEBUG "BRANCHed to Task_1", CR
'  PIN0 = IsOff
'  PIN1 = IsOn
  READ idx, PINS
  GOTO Next_Task

Task_2:
  DEBUG "BRANCHed to Task_2", CR
  PIN1 = IsOff
  PIN2 = IsOn
  GOTO Next_Task

Task_3:
  DEBUG "BRANCHed to Task_3", CR
  PIN2 = IsOff
  PIN3 = IsOn
  GOTO Next_Task

Task_4:
  DEBUG "BRANCHed to Task_4", CR
  PIN3 = IsOff
  PIN4 = IsOn
  GOTO Next_Task

Task_5:
  DEBUG "BRANCHed to Task_5", CR
  PIN4 = IsOff
  PIN5 = IsOn
  GOTO Next_Task

JonnyMac

October 03, 2015, 07:41:47 PM #1 Last Edit: October 04, 2015, 10:12:36 AM by JonnyMac
Let me explain the magic of PINx variables (PINS, PIN0..PIN7) -- start with the fact that these are variables that are connected to IO points. When using any PINx variable in code...

ITS PLACEMENT RELATIVE TO THE = SIGN IS KEY.

(Yes, I used the separate line and SHOUTED for dramatic effect).

When we are using the PINx variable as an output, it must appear on the LEFT side of the = sign when used in an assignment, as in

  PIN0 = 1

(This is valid syntax, yet stylistically lacking). In this case, we are writing 1 to the PIN0 variable. What happens? Well, if that IO point has been made an output (e.g., DIR0 = 1) the pin 0 will go high. In fact, the HIGH 0 command in PBASIC is translates to:

  PIN0 = 1
  DIR0 = 1


As you can see, HIGH is easier (but is slower if the pin is already an output).

Now, for the other side. When a PINx variable appears on the RIGHT side of the = sign in an assignment, or as a source parameter of another command, it is treated as an input by the code. This creates a number of problems. A common mistake is doing something like this

  HIGH PIN5

This does not in fact make output 5 go high. What does, then? It's either 0 or 1 depending on the state of PIN5. In this case the compiler says, "Okay, take the input level of PIN5 (which is binary and can only be 0 or 1) and use that as the pin to make high."

Here's another common error

  SEROUT PIN7, Baud, ("EFX-TEK Rocks!")

This will typically try to do the SEROUT on PIN 1 because PIN 7 is usually pulled high for Open True communications.

In you the program you referenced, there is this line of code:

  READ idx, PINS

In this case, PINS is a destination parameter because READ takes the value at idx (the EE address) and copies it to the destination variable (PINS in this case).

Keys:
  -- When a PINx variable is on the right side of =, or used as a source parameter (e.g, when the code needs a pin # for the command), it's treated like an input
  -- When a PINx variable is on the left side of =, it is treated like an output (DIRx register must be set to act on IO pins)

Mastering the PINx variables of the BS1 is the trickiest part of it. Chip realized this when developing the BS2, hence separated names INS and OUTS to replace PINS -- this makes context easier to code and understand.

Finally, in the blurb you say you're having trouble with:

Task_1:
  DEBUG "BRANCHed to Task_1", CR
'  PIN0 = IsOff
'  PIN1 = IsOn
  READ idx, PINS
  GOTO Next_Task


You're using READ but there is no EEPROM table in you code. By default the compiler writes 0s to unused EE addresses, so in your program, this:

  READ idx, PINS

...is doing this:

  PINS = 0
Jon McPhalen
EFX-TEK Hollywood Office

Jeff Haas

Thank you!  I had read the Help file, the Basic Stamp manual, and your sticky post at the top of this forum and didn't find that explanation.  You should make your post above another sticky.

After a break, I added the EEPROM table to the code, updated the directive, and all is working.

Thanks for taking the time to explain in such detail - and also for not just giving me the solution.  I always enjoy working through these things and learning the details.