Parallax Propeller Book - Programming Part 3

Spin Programming

Prerequisites:


Equipment:


Objective:


Methods and Cogs

Methods


Introduction:

Objects are organized into code building blocks called Methods.

In Spin, method names can be used to pass program control and optionally parameter values from one method to another.

When one method uses another method’s name to pass it program control, it’s called a method call.

When the called Method runs out of commands, it automatically returns program control and a result value to the line of code in the Method that called it.

Depending on how a Method is written, it may also receive one or more parameter values when it gets called.

Common uses for parameter values include configuration, defining the method’s behavior, and input values for calculations.

Methods can also be launched into separate Cogs so that their commands get processed in parallel with commands in other Methods.

The Spin language has commands for launching Methods into Cogs, identifying Cogs, and stopping Cogs.

When Spin Methods are launched into Cogs, Global variable arrays have to be declared to allocate memory for the methods to store return addresses, return values, parameters, and values used in calculations.

This memory is commonly referred to as a as stack space.

Following projects will demonstrate techniques for writing methods, calling methods, passing parameters to methods, and returning values from methods.

They also demonstrate using method calls in commands that launch instances of methods into separate Cogs, along with an overview of estimating how much stack space will be required for one or more Spin Methods that get executed by a given Cog.


Project #4.3-1 Step One - Basic Spin Object

To control the Output on Port P26 we will use the circuit in Figure 3-7a or in Figure 3-7b.

Port Output HI
Fig 3-7a LED Status Indicator for Port Output HI
Port Output HI
Fig 3-7b LED Status Indicator for Port Output HI

'' AnotherBlinkerMRX.spin 

PUB Blink | port, rate, reps

  port := 26                           ' assign LED port
  rate := clkfreq/3                    ' assign rate = 3Hz
  reps := 19                           ' assign reps (repetitions)
  dira[port]~~                         ' Set port to OUTPUT
  outa[port]~                          ' Set port LO

  repeat reps * 2                      ' Define loop repetitions
    waitcnt(rate/2 + cnt)              ' Wait for 1/2 of cycle
    !outa[port]                        ' Toggle port


Above Object (AnotherBlinkerMRX.spin) makes LED on Port P26 blink 19 times at 3 Hz frequency, the output to P26 is basically a "square wave" at 3 Hz with 50% duty cycle. Run the program to verify that if functions properly.


If you are using QSB run 4.3-1_AnotherBlinkerMRX-QSB.spin instead, which makes LED on Port P16 blink.


Project #4.3-2 Step Two - Spin Object with Two Methods

Now we add another Public Method that waits for push-button press on P10 and then calls the above PUB Blink Method.

To read the Input of P10 we will use the circuit in Figure 3-10.

Switch with Down Up Resistor
Fig 3-10 Switch with Pull Down Resistor

We will also use CON block to define the Ports for Monitor LED (ledA) on P27 and input push-button (button) on P10.

This added method is PUB Main.


'' CallBlinkMRX.spin

CON
  ledA = 27                         ' assign port for Monitor LED
  button = 10                       ' assign port for push button

PUB Main
  repeat
    outa[ledA] := dira[ledA] := 1   ' Set [ledA] to OUTPUT HI
    repeat until ina[button]     ' Wait until [button] is pressed
    outa[ledA] := 0                 ' Set [ledA] LO
    Blink                           ' Call Blink method
    waitcnt(clkfreq/2*3 + cnt)   ' Wait before repeating loop 
                                 ' 1.5 seconds
PUB Blink | port, rate, reps    ' Define parameters used in Blink
  port := 26                        ' assign port for ledB
  rate := clkfreq/3         ' assign rate (number of clock ticks)
  reps := 9                         ' assign reps (repetitions)
  dira[port]~~                      ' Set [port] to output
  outa[port]~                       ' Set [port] LO
  repeat reps * 2   ' Set loop to number of repetitions (reps * 2)
    waitcnt(rate/2 + cnt)           ' Wait for rate/2
    !outa[port]                     ' Toggle [port]


This Application now has CON block and two PUB Methods.

The first PUB Main calls the PUB Blink after the condition in the repeat loop is satisfied, that is whenever the push-button on Port P10 is pressed.

Once the PUB Blink Method executes, the program control is returned to the PUB Main Method's next statement: waitcnt(clkfreq/2*3 + cnt)

After the 1.5 second wait delay the program loops back to the Start of the repeat command.


If you are using QSB run 4.3-2_CallBlinkMRX.spin instead.

On QSB the Ports are P17 for LED-A, touch pad is P1 and the LED-B is P16.


Project #4.3-3 Step Three - Application with Two separate Spin Objects


Now we add a parameter transfer from the first object that calls the Blink Method. Blink (ledB, rateC, repsC) and we also need to change the PUB Blink | port, rate, reps to: PUB Blink (port, rate, reps), this indicates that those parameters will be transferred into this Method in the method call.


'' CallBlinkMRX2.spin
CON
  _clkmode = xtal1 + pll16x     ' System clock → 80 MHz
  _xinfreq = 5_000_000

  ledA = 26                         ' assign port for Monitor LED
  button = 10                       ' assign port for push button

  ledB = 27                          ' assign port for ledB
  rateC = (80_000_000/3)  ' assign rate Constant 
                             '(number of clock ticks)
  repsC = 9               ' assign reps Constant (repetitions)

PUB Main
  repeat
    outa[ledA] := dira[ledA] := 1    ' Set [ledA] to OUTPUT HI
    repeat until ina[button]         
                               ' Wait until [button] is pressed
    outa[ledA] := 0                  ' Set [ledA] LO
    Blink (ledB, rateC, repsC)       ' Call Blink method
    waitcnt(clkfreq/2*3 + cnt)  
                        ' Wait before repeating loop 1.5 seconds

PUB Blink (port, rate, reps)   ' Define parameters used in Blink
  
  dira[port]~~                     ' Set [port] to output
  outa[port]~                      ' Set [port] LO
  repeat reps * 2    'Set loop to number of repetitions (reps * 2)
    waitcnt(rate/2 + cnt)          ' Wait for rate/2
    !outa[port]                    ' Toggle [port]


If you are using QSB run 4.3-3_CallBlinkMRX2.spin instead.

On QSB the Ports are P16 for LED-A, touch pad is P0 and the LED-B is P17.


Project #4.3-4 Step Four - Application with Two separate Spin Objects

Now we are ready to "separate" the PUB Blink Method from the Application into an independent Object. We will name it: BlinkMRXmethod.spin


'' BlinkMRXmethod.spin 
PUB Blink (port, rate, reps)    ' Define parameters used in Blink
  
  dira[port]~~                           ' Set [port] to output
  outa[port]~                            ' Set [port] LO
  repeat reps * 2    'Set loop to number of repetitions (reps * 2)
    waitcnt(rate/2 + cnt)                ' Wait for rate/2
    !outa[port]                          ' Toggle [port]

Now we make few changes in the original CallBlinkMRX.spin Application that contained the two PUB Methods and we will make this new Application call this now separate Object.

Once compiled the functionality of the new CallBlinkMRXmethod.spin Application will be the same.

So that the application would function properly we need to define the Propeller chip's clock frequency and the assign the proper number of ticks to the [rate] in CON block, this is because we can not use clkfreq in the CON definition.

We also need to assign an alias to the called object, in this case we will refer to the BlinkMRXmethod.spin with alias of Blinker .

The OBJ block is used for this alias definition assignment:

OBJ
  Blinker   :       "BlinkMRXmethod"  

Note that in the definition the .spin is omitted.


Important !

The called Object (BlinkMRXmethod.spin) MUST be saved in the same computer file folder where the Application that calls it (CallBlinkMRXmethod.spin) is also saved.

If both Objects are not in the same computer file folder, an error will be generated during Compile.


'' CallBlinkMRXmethod.spin
CON
  _clkmode = xtal1 + pll16x     ' System clock → 80 MHz
  _xinfreq = 5_000_000

  ledA = 27                     ' assign port for Monitor LED
  button = 10                   ' assign port for push button

  ledB = 26                     ' assign port for ledB
  rateC = (80_000_000/3)        ' assign rate constant 
                              ' (number of clock ticks) 3Hz
  repsC = 9                   ' assign reps constant (repetitions)

OBJ
  Blinker   :   "BlinkMRXmethod"   ' assign alias to called object
  
PUB Main
  repeat
    outa[ledA] := dira[ledA] := 1      ' Set [ledA] to OUTPUT HI
    repeat until ina[button]      ' Wait until [button] is pressed
    outa[ledA] := 0                    ' Set [ledA] LO
   Blinker.Blink(ledB, rateC, repsC) 
                              ' Call Blink method in Blinker alias 
    waitcnt(clkfreq/2*3 + cnt)
                          ' Wait before repeating loop 1.5 seconds

Run the CallBlinkMRXmethod.spin application to verify that if functions properly.

In the top right pane of the Propeller Tool you should see how the two Objects are nested:

Propeller Tool view BlinkMRX
Propeller Tool view of BlinkMRX



Under Construction
Currently this page is still under development, so please check back periodically for new links to pages as we add them to this list.

Links to related Webpages

Click the link in the list below to navigate to a detailed webpage about the listed subject.


Parallax Propeller Book - Table of Content