Item Description Supplier/Part No.
C1-C4 0.01 µF Mouser 80-C315C103M5U
C5 220 ohms Mouser 140-L10V220-RC
JP1-JP4 0.1 M-STRT Mouser 517-6111TG *
LED1 G/R bi-color Mouser 604-WP937EGW
Q1 2N3904 Mouser 610-2N3904
R1-R4 100 ohms Mouser 291-100-RC
R5-R6 470 ohms Mouser 291-470-RC
R7-R8 2.2K Mouser 291-2.2K-RC
R9 10K Mouser 291-10K-RC
RN1 10K Mouser 81-RGLD8X103J
RX1-RX210K dual Gadget Gangster RKJXK122000D
SW1 DIP-6x Mouser 611-BD06
SW2 6 mm NO Mouser 653-B3F-1022
S-U1 14-pin DIP Mouser 571-1-390261-3
U1 MCP3204 Mouser 579-MCP3204-CI/P
X1-X10 0.1 M-STRT Mouser 517-6111TG *
PCB ExpressPCB
Parts Kit Gadget Gangster
* The 517-6111TG is a 40-pin component; only three are
required for the project (split as needed).
◗ BILL OF MATERIALS
the signal. If the PPM signal is lost, the input will remain
high and code is redirected back to the top of the
program where we’ll wait for reconnection and a valid
sync pulse.
When things are working as they should, the PPM
input will drop after about 390 microseconds — this is
where we start the channel position measurement. This
code looks — and is — very easy; it’s actually just a call to
a subroutine and a check on an error flag (stored in C)
that can be set by that routine:
getch1 call #getch
if_c jmp #vexin
mov ch1us, pwidth
As you can see, this section calls a subroutine called
■ FIGURE 8. Test Menu.
18
September 2010
getch which performs the actual channel measurement
and will set the C flag if a measurement error is detected.
After returning from the measurement routine, we check
the C flag and if it’s set, jump right back to the very top of
the program where the PPM stream detection flag is set to
NO (false). This flag can be used by our application to
determine the presence or absence of the PPM stream
and take some action based on that status. Assuming a
good measurement, though, we save the channel timing in
a holding register and then do the same operation for the
rest of the channels.
The hard work is performed by the getch subroutine:
getch mov pwidth, #0
:looplo waitcnt timer, US_001
add pwidth, #1
cmp pwidth, LO_MAX wc, wz
if_a jmp #badch
test pmask, ina wz
if_z jmp #:looplo
:loophi waitcnt timer, US_001
add pwidth, #1
cmp pwidth, CH_MAX wc, wz
if_a jmp #badch
test pmask, ina wz
if_nz jmp #:loophi
goodch cmp pwidth, CH_MIN wc, wz
jmp #getch_ret
badch test $, #1 wc
getch_ret ret
Yeah, this does look a little bit hairy, but as you
examine it closely, you’ll find it’s divided into two sections:
the first to measure the low portion of the period; the
second to measure the idle period which completes the
channel timing.
Again, we start by clearing the timing measurement
variable (pwidth) and then doing a one microsecond
delay. The pulse timing is incremented and then compared
to a constant that defines the longest valid low period. We
do this so that a short on the PPM input can be detected.
If this happens, the C flag gets set and we abort back to
the calling code.
This usually won’t happen, though, and we continue
timing until the PPM line goes back high for the idle
period. Now, we time this while waiting for the line to go
back low (the start of the next channel); again, testing
against an established limit. The test during the high
period will detect a disconnection of the VEX device from
the circuit. When we return to the calling section, the
variable called pwidth will contain the channel value and
when all is well the C flag will be cleared.
After all of the channels have been measured, we can
write the values to the hub for access by the application:
report mov pntr, pospntr
wrword ch1us, pntr
add pntr, #2
wrword ch2us, pntr
add pntr, #2
wrword ch3us, pntr
add pntr, #2
wrword ch4us, pntr
add pntr, #2
wrword ch5us, pntr