The checksum calculation needs a pointer to the first
byte of the payload and the number of bytes to process.
Why use a pointer when we have a buffer inside the
object? Well, this allows us to build external packets and
send them too. We'll see this in a moment.

c := serial.rxtime(1)
if (c < 0)
return 0
else
rxbuf[len++] := c

If you're new to the Propeller, you may be wondering
why cs isn't explicitly initialized to zero, and why there is
no return. In both cases, the reason is that we're using the
internal result variable that is returned by every method.

pb := serial.rxtime(1)
if (pb < 0)
return 0
else
rxbuf[len++] := pb

The colon (:) in front of cs indicates that we are aliasing
result. A simple loop accumulates the payload bytes, then
we subtract byte 0 of the sum from $FF.

Back in the at_command() method, I made the
decision to flush the serial receive buffer so that I know
the next thing coming in will be the value just requested.

Technically, we can use the Frame ID to sort out
responses, but my projects tend to be simple, so I don't
bother with that. With the frame built, we can push it out
to the XBee through the serial connection:
Essentially, we're checking for or waiting for the API frame
header byte ($7E). Once that is received, we get the rest
of the current packet. The first byte after the header (MSB
of payload bytes) will always be zero. The LSB of the
payload bytes is important because it tells us how many
more bytes to pull from the serial buffer for this packet.

pub tx_frame(p_frame, len)
repeat len
serial.tx(byte[p_frame++])

When a valid packet is available, its length is returned to
the caller.

Again, this method uses buffer pointer and length
parameters so that we can send internal (to the object) or
external packets (in the application) to the radio.

After sending the AT command, the next step is to
extract the value from the response:
Let me share a real world test of this method. In the
laser tag system, a victim tagger can report “You hit me”
or “You defeated me” to the shooter. As a test, I put the
sensors from two victim taggers (which had identical
settings) next to each other, ensuring that the shooter
would hit them both at the same time.

Taggers play audio announcements, including
contiguous victories. When enough hits caused both
victim taggers to be defeated — which happened
simultaneously — the shooter tagger skipped right to the
“Two victories” message, bypassing the message for a
single contiguous victory.

return -1

This method gives the XBee 25 milliseconds to
respond, validates the frame by verifying the checksum,
and ensures that it is an AT response frame ($88) with no
errors ($00). If all of this checks out, the returned value
can be extracted from the frame. I use -1 as the error
value because it is unlikely to be returned from any AT
command.

There's a couple things to note here: The victim
taggers both try to send XBee messages at the same time,
and the under-the-hood layer takes care of ensuring that
both got through to the shooter. On the shooter side, we
would have two messages in the serial buffer; the way
get_rx_frame() is set up, we don't have to worry about
losing anything. The next step is validating the frame by
comparing the transmitted checksum with what we
calculate from the received payload:
To get to the returned value, we have to pull the
frame from the serial RX buffer: