Stamp
The first command is “V” for Version. This feature
may be important if we develop a piece of control software that can work with multiple control devices; getting
the version (hence, available features) from the connected device will prevent possible incompatibility issues.
Show_Version:
TX_STR Version
GOTO Main
Boy, that was tough, wasn’t it? Since we’ve already
covered sending strings, there’s really nothing else to
cover.
Next is “G” for Get Ports Status. This command will
return the status of the 16 output ports in this form:
Status = 00000000 00000000
Note that what follows “Status =” are the actual states
of the pins, where “1” is on and “0” is off, and the display
is MSB to LSB. What we need to do here is create a subroutine that will transmit a value as a binary string, much
the way the PBASIC BIN8 modifier does.
First, the Get_Ports code:
Get_Ports:
TX_STR PortStatus
TX_BIN8 PortHi
TX_BYTE “ “
TX_BIN8 PortLo
TX_STR CRLF
GOTO Main
And now the TX_BIN8 subroutine that is used by
Get_Ports:
TX_BIN8:
temp3 = __PARAM1
FOR temp4 = 1 TO 8
IF temp3.7 = 1 THEN
TX_BYTE “1”
ELSE
TX_BYTE “0”
ENDIF
temp3 = temp3 << 1
NEXT
RETURN
F
o
r
E
l
e
c
t
r
o
n
i
c
s
NUTS & VOLTS
E
v
e
r
y
t
h
i
n
g
The TX_BIN8 subroutine, of course, expects a value
to be sent; this will be saved in temp3. Using a
FOR-NEXT loop, the bits are examined from MSB to LSB. If
the bit is set, then we use TX_BYTE to send “1” — otherwise we send “0.” Since temp3 is a work variable and
doesn’t need to be preserved, the code is simplified by
looking only at the MSB. In order to examine all of the
bits, temp3 is shifted left each time through the loop. This
moves the next bit into the MSB.
Okay, now that we can see the outputs, how do we
change them? The program supports three different
methods of updating the outputs: all 16 at once, the high
72
and low groups, or individual port bits. Let’s start with all
ports using the “S” (Set All Ports) command:
Set_Ports:
TX_STR Pad
PortHi = RX_BIN8
TX_BYTE “ “
PortLo = RX_BIN8
TX_STR CRLF
GOTO Main
For the Set_Ports code, we need a routine that is the
complement of TX_BIN8 — in this case, it’s RX_BIN8.
This will allow use to receive a value expressed in binary
form, and is used to accept values for the high port (RC)
and low port (RB) separately. A space is transmitted after
the receipt of the PortHi value to indicate a new input
(for PortLo).
RX_BIN8:
temp3 = 0
FOR temp4 = 1 TO 8
temp5 = RX_BYTE
IF temp5 >= “0” THEN
IF temp5 <= “1” THEN
temp3 = temp3 << 1
IF temp5 = “1” THEN
INC temp3
ENDIF
ELSE
EXIT
ENDIF
ELSE
EXIT
ENDIF
NEXT
RETURN temp3
We start by clearing temp3, which will ultimately hold
the return value. Then we set up a FOR-NEXT loop to get
eight bits. A character is retrieved from the serial port and
checked to see if it’s a valid binary digit: “0” or “1.” If it is,
then the return value is shifted left and the new bit value
is added to the return variable. Shifting left means
that the routine is expecting the value to be transmitted
MSB first.
The FOR-NEXT loop takes advantage of EXIT to terminate early if a non-binary character is sent before the
end of the loop. This allows us to enter the minimum
number of bits required to express the value. If, for example, we enter “1111” and then press space, the value 15
will be returned to the caller.
There are two additional commands, “H” and “L,”
that allow the user to set the high and low ports independently. Those routines are simply subsets of the Get_Ports
code.
I think the trickiest aspect of this program is the code
for “P” (Set Individual Port), that allows the user to specify a port number (1 to 16) and its condition (0 for off, 1
for on). For this code, we’ll need a routine that will accept
a decimal value: RX_DEC2.
SEPTEMBER 2005