downloading the program.
We could, of course, have stated the value directly
but here is a case for writing code that explains itself. In
this case, we take the number of system counter ticks in
one second and divide by one million to get the number
of ticks in one microsecond. Now we multiply by 10 to
get the number of ticks in 10 microseconds. This may
at first seem like an arbitrary value, but it isn’t. More on
Let’s drop into the main loop. Its purpose is to read
the color setting from the hub RAM and then jump to the
handler that sets the LED to that color.
rdlong color, colorAddr
mov tmp1, color
max tmp1, #3
add tmp1, #jmpcolor0
jmpcolor0 jmp #ledoff
jmpcolor1 jmp #ledgreen
jmpcolor2 jmp #ledyellow
jmpcolor3 jmp #ledred
The first part is easy with rdlong; this lets us read
a value from the hub RAM into a cog variable.
What follows is the equivalent of a PBASIC or SX/B
BRANCH instruction. The color value is copied into
tmp1. Now, tmp1 should be something between zero
and three, but as good programmers we don’t take
chances and will do a bit of error trapping; in this case,
we limit the value of tmp1 to three by using the max
And now for a little tricky stuff: We add the starting
location (cog RAM) of a table of jmp instructions to the
value of tmp1 and then jump to the result. When tmp1 is
zero, we will end up jumping to ledoff; when tmp1 is
three, we will end up jumping to ledred. We could have
used cmp (compare) and if_e jmp with each value, but
this version of the code is a little cleaner, especially with
long tables. Note that I’ve added extra labels to the table
Okay, let’s control the LED — it’s nothing more that
setting the direction of current flow (if any) through it.
andn outa, gMask
andn outa, rMask
or outa, gMask
andn outa, rMask
add rgCntr, #1
cmp rgCntr, #16 wc
mov rgCntr, #0
andn outa, gMask
or outa, rMask
waitcnt loopTimer, us010
To turn an output pin off, we need to set its driver to
zero and the andn (and not) instruction — when used with
a mask — takes care of that for us. As I stated the last time,
Propeller owes many of its features to the success of the
BASIC Stamp and, believe it or not, the &/ (and not)
operator is part of PBASIC 1.0 — the language that runs
on the original BASIC Stamp released in 1993!
The andn instruction actually does two things: it inverts
the bits of the second value and then ANDs the two values
together. The result is written back into the first value. So,
we take a mask that has one bit set that represents the pin
we want to affect. By inverting this mask, we now have a
value that is all ones except for the bit that represents our
pin — this bit is set to zero. By and-ing the outputs register
(outa) with the inverted value, our pin is set to zero and all
others are preserved. So, to turn off the LED we use andn
to write zeroes to the green and red control bits in outa.
With both pins set to the same level, no current flows and
the LED is off. The code for green and red should be easy
to follow: Turn one pin on and the other off — this falls
right into the no-brainer basket. But what about yellow?
I stated earlier that we have to run the green side of
the LED more cycles than the red to create a color that
approximates yellow. With my LED, I found that 15 cycles
of green to one cycle of red looked good. So, when we
jump to ledyellow we’re going to increment a cycle
counter (rgCntr) and check to see if it has reached 16.
While rgCntr is less than 16, we jump to the green
handler; when rgCntr hits 16, we drop through, reset the
counter, and then jump to the red handler.
Another thing we have to get used to when using the
Propeller is that the C (carry) and Z (zero) flags are not
automatically updated as with other controllers (e.g., SX).
The upshot is that we can maintain the flags through
other instructions and not have to worry about them
being clobbered. The downside is, of course, that we have
to remember to tell the assembler to enable them.
You’ll see wc — called an effect — at the end of the
cmp line in the yellow handler; this will write the carry
flag based on the result of the compare. The compare
instruction works very much like sub except that it doesn’t
affect the first value. When the first value is less than the
second, the carry flag will be set (1).
Do yourself a favor and put one of those sticky flags
on Table 5-2 in the Propeller manual; this table lists the
aliases for the various combinations of C and Z flags that
can be used to conditionally control instructions. One of
the aliases for the carry flag being set is if_b which is short
for IF BELOW. As you can see, we’ve applied this to the
jmp that follows the compare to make it conditional.
When the value of rgCntr is below 16, then we jump to