ADVENTURES IN PROPELLER PROGRAMMING
clock and shift/load lines are tied together. The
interesting bit is that the serial output from the upper
chip feeds a serial input pin on the lower chip. These
connections essentially create one 16-bit shift register
from two '165s. Of course, we can extend this to 24 or
even 32 inputs if desired. It is electrically possible to have
more than four '165s connected in a chain but I never do
that — it doesn't make sense given the 32-bit values used
by the Propeller.
Now for the action. The read() method will allow us
to read from a chain of one to four 74HC165s. The
method takes two parameters: the bit orientation
(MSBFIRST or LSBFIRST) and the number of devices
outa[load] := 1
dira[load] := 1
pub read(mode, count) | in165
count <<= 3
If you look closely, you can see that input 15 is
nearest to the Qh (SOUT) pin used as the I_DAT
connection to the Propeller; if we add another '165, that
will change to input 23 (MSB of a 24-bit group), etc.
Keep this in mind when planning your designs and input
assignments; the inputs are shifted into the Propeller
outa[load] := 0
outa[load] := 1
Finally, the purpose of the 3.3K resistor in the
SOUT line is to allow a VDD of five volts. The 3.3K
resistor limits the current into the 3.3V Propeller pin
to a safe level.
in165 := 0
in165 := (in165 << 1) | ina[dta]
outa[clk] := 1
outa[clk] := 0
if (mode == LSBFIRST)
in165 ><= count
For those with PBASIC or SX/B experience, you're
familiar with the SHIFTIN command. We don't have that
in the Spin language, so we'll use a bit of code to create
its equivalent. The object code for reading from one to
four 74HC165s consists of a whopping two methods.
That's right ... two. Some newcomers might think why
bother putting so little code into a separate object file.
The point of an object file is to simplify code re-use;
copy-and-paste is for the birds!
At the top of the method, we convert the byte count
to bits by multiplying by eight. As eight is a power of
two, we use a left shift instead of multiplication. Shifting
is much faster when we can use it.
The start() method takes our I/O pin assignments
and configures them for use:
The shift/load line is taken low to transfer the inputs
to the internal holding register, then returned high to put
the '165 back into shift mode.
pub start(dpin, cpin, lpin)
longmove(@dta, @dpin, 3)
The inputs will be collected in a variable called
in165. This is a local variable, so we need to clear it to
zero before use. Local variables come from the stack and
could have anything in them (locals are not initialized to
zero like globals).
dira[dta] := 0
outa[clk] := 0
dira[clk] := 1
A repeat loop takes care of grabbing the bits. Note
that the first line of the loop is doing two things: It starts
by left-shifting the value in in165 to make room for the
new bit; then it moves the state of the data pin to the
in165.bit0. The clock line is taken high, then back low to
get the next bit.
This method takes three parameters: the data pin, the
clock pin, and the shift/load pin. The pins are copied to
global variables within the object using longmove. There
is no error checking for valid pin numbers, so do be
mindful of your assignments.
The normal configuration for using 74HC165s is
MSBFIRST (1) as in Figure 1. Let's say for the sake of a
circuit you wanted to flip those on end, such that what
was input 15 becomes input 0, and vice-versa. No
problem! Simply set the mode to LSBFIRST (0). The bits
will be flipped by using Spin's reverse operator (><).
The data pin is configured as an input, the clock pin
as an output/low, and the shift/load line as an
output/high. That last section puts the '165 chain into
shift mode where data can be transferred from the
holding registers into the Propeller.
As you can see, the mode affects all bits returned.
What if we just wanted to flip the lower eight bits
of the inputs? We can do that; it just takes one more line
buttons := ins.read(ins#MSBFIRST, 2)
buttons.byte ><= 8
January 2014 13