As we will see in just a moment, the command bytes
and transmission count are sent in a packed long. This is
read from the hub (the address of usercmd is in par) and
the count is extracted. If the count is zero, there is no
command, and we can receive the next packet and move
it to the hub. Let's do that.
As you now know, we synchronize with the LANC
stream by looking for the idle period between packets.
That is handled with this code:
mov phsa, #0
mov lancframes, #0
clear_cmd mov r1, #0
wrlong r1, par
mov cmdb2, cmd
shr cmdb2, #16
and cmdb2, #$FF
wait_idle neg r1, cnt
:loop test siomask, ina wc
if_nc jmp #wait_idle
mov r2, r1
adds r2, cnt
cmps r2, idletix wc, wz
if_b jmp #:loop
wait_idle_ret ret
We use andn to write a 0 into the output and
direction bits of the LANC pin; this causes the pin to be
in input state and preps the output bit for use later.
Next, we set up ctra to free run; this will be used to
detect the loss of LANC data. Lou's project, for example,
uses a wireless connection between a base station and
several remote cameras; by detecting the loss of the
LANC stream, his system can tell if a camera has gone
off-line or was disconnected.
Finally, we clear the frames received counter and the
value presently sitting in the command variable (usercmd,
which is holding the hub address of cogparms[0]) — this
lets the foreground know that we're ready.
The main control loop is fairly trim: We check to see
if there is a command from the application and if so,
extract the command bytes and count. If there is no
command, we'll simply wait on the next LANC packet
and move it into the hub:
As I've stated many times, one of my favorite aspects
of the Propeller is the ability to do precise timing by
using the cnt register, and that's what we're doing here.
At the top of the loop, we move the negative value of
the cnt register into r1; this is the starting point of our
timing. Then, we drop into a loop that looks at the LANC
serial line, moving the state of the line into the Carry bit.
If the line was low (nc), we start all over because we've
sampled in the middle of a zero bit; this means we're not
in the idle period.
lanc_loop rdlong cmd, par
mov cmdcount, cmd
and cmdcount, #$FF
tjz cmdcount, #rx_lanc8
cmp cmdcount, #$FF wc, wz
if_e jmp #wake
If the LANC serial line is high, we copy the starting
value into r2 and add this to the current content of the
cnt register. At this point, r2 holds the time (in system
ticks) between when we (re)started and now. This is
compared with the value in idletix. Once the value in r2
exceeds the value in idletix, we know that we've found
the idle period, and can exit and receive the packet:
mov cmdb1, cmd
shr cmdb1, #8
and cmdb1, #$FF
receive mov rxwork, #0
mov rxbits, #8
:loop mov rxtimer, cnt
test siomask, ina wc
if_nc jmp #rx_byte
cmp lostix, phsa wc, wz
if_a jmp #:loop
mov losflag, #1
BILL OF MATERIALS
R
ESO
URC
ES
Jon "JonnyMac" McPhalen
jon@jonmcphalen.com
www.boehmel.de/lanc.htm
Excellent LANC reference
R1 3.3K Mouser 71-CRCW0603-3.3K-E3
R2 4.7K Mouser 71-CRCW0603-4.7K-E3
X1,X2 0.1x3 M Mouser 2340-6111TG
Parallax, Inc.
www.parallax.com
Propeller chips and programming tools
PCB BayArea Circuits
16 July 2014