mov frqa, #1
mov ctrb, FREE_RUN
mov frqb, #1
waitok rdlong tmp1, okpntr wz
if_nz jmp #waitok
waitstart waitpeq irmask, irmask
mov phsa, #0
waitpne irmask, irmask
mov phsb, #0
waitpeq irmask, irmask
cmp START_BIT, phsa wc
if_nc jmp #waitstart
As you can see, we’re going to use both counters.
Counter A is going to be set up in negative detect mode
to measure the width of incoming bits. Counter B will be
used in free-run mode to keep track of frame timing.
At the label waitok, the program reads a flag from
the hub. This allows the user to enable the SIRCS
decoder when desired. A non-zero value in this flag
allows the program to drop through to waitstart where —
as you’ve no doubt guessed — we will wait for the 2. 4 ms
At the beginning of this section, we can use watipeq
and the IR input pin mask to wait for that input to be high.
We need to start this process while the line is high to
make sure that we can measure the whole bit — we don’t
want to come in late and get an inaccurate measurement.
When the line is high, we clear PSHA and then wait for
the line to drop with waitpne.
When the line goes low, we clear the PHSB register.
Why? Well, we’re assuming at this point that we’ve found
the leading edge of the start bit and we need to clear the
PHSB register which will be keeping track of the frame
duration. Once the line goes back high, we use cmp to
test the width of the bit. If it’s a valid start bit, then we
drop through. Otherwise, we jump back to waitstart and
test the next bit.
With the start bit detected, the next step is to collect
the bits that comprise the device/key code.
mov irwork, #0
mov bits, #0
checkframe cmp MS_044, phsb wc
if_c jmp #irdone
waitbit test irmask, ina wz
if_nz jmp #checkframe
measurebit mov phsa, #0
waitpeq irmask, irmask
cmp ONE_BIT, phsa wc
rcr irwork, #1
add bits, #1
cmp bits, #20 wc
if_b jmp #checkframe
irdone mov tmp1, #32
sub tmp1, bits
shr irwork, tmp1
report wrlong irwork, codepntr
wrlong bits, bitspntr
wrlong DONE, okpntr
Our decoder has no way of knowing what’s being
pointed at it, so it keeps track of the code received
(irwork), as well as the number of bits received (bits) —
both values will be provided to the calling program.
It may seem like odd placement, but the top of the bit
receive loop (at checkframe) actually tests the frame timer
(in PHSB) to see if the frame is complete. I’m using 44
milliseconds as the test value for what is supposed to be a
45 ms frame. It’s okay to be a little short because even if
all the bits of a 20-bit code were “1,” it would still only be
If the frame is still active, we test the line for a new
bit (line is low). While the line remains high, we have
to loop back through checkframe so that the end is
handled correctly. Once the line does drop for a new bit,
we clear PHSA and then wait for the line to go back high.
The width of the newly-captured bit is compared to the
timing for a 1 bit, with the result written into the Carry
flag. This bit is then moved into irwork with rcr (rotate
carry right). With the bit saved, we increment the bit
count and if it’s less (if_b) than 20 bits, it jumps back to
Once we’ve received 20 bits or the frame timer
reaches 44 milliseconds, the program moves to irdone
where we clean up the result. Since the bits come in
LSB first, we had to shift them in from the left (toward the
right) — this means that our result is MSB-aligned in irwork.
By subtracting the number of bits received from 32 (bits
in a long), we can correct and LSB-align the result. One of
my favorite aspects of PASM is that we can shift a value
any number of bits with a single instruction.
Finally, the result in irwork, the number of bits
◗ BILL OF MATERIALS
January 2010 15