key to barrel shift all bits right:
IF cmdCode = VolUp THEN
ASM
MOVB C, Control.0
RR Control
ENDASM
DELAY_MS KeyDelay
GOTO Main
ENDIF
With a barrel shift, we don't lose the end bit to the
"bit bucket" — it gets wrapped around to the opposite end.
To do this, we forego the use of the SX/B shift operators
for a block of Assembly. The SX/B shift operators — like its
PBASIC counterparts — do allow end bits to be lost and
pad with zeros. What we do here is copy the end bit to
the Carry and then to an Assembly shift with RR to move
everything; the Carry bit is copied into the opposite end
and we have a barrel shift. This is a useful trick.
MIX IT UP
We've seen how easy it is to decode SIRCS signals
when there is no interrupt, but what happens when we
want to fold SIRCS decoding into a project that requires
buffered serial communications? In my opinion, the best
approach is to put the SIRCS decoding into the interrupt
with the UARTs. Here's how I do it:
Test_SIRCS_Tix:
ASM
BANK sircs
INC irTix
CJB irTix, #3, SIRCS_Exit
CLR irTix
JB irReady, SIRCS_Exit
JB irCmd, Check_Bit
JB IR, SIRCS_Exit
Start_Packet:
SETB irCmd
SETB irBit
CLR irBitWidth
CLR irBitCount
CLR irCode_LSB
CLR irCode_MSB
JMP SIRCS_Exit
Check_Bit:
JNB IR, Update_BitWidth
JNB irBit, SIRCS_Exit
CLRB irBit
TEST irBitCount
JNZ Test_DBit
Test_SBit:
CJA irBitWidth, #216, Next_Bit
CLRB irCmd
JMP SIRCS_Exit
Test_DBit:
CLC
RR irCode_MSB
RR irCode_LSB
CJB irBitWidth, #108, Next_Bit
SETB irCode_MSB.3
22
January 2009
Next_Bit:
CLR irBitWidth
INC irBitCount
CJB irBitCount, #13, SIRCS_Exit
SETB irReady
MOVB C, irCode_LSB.7
RL irCode_MSB
CLRB irCode_LSB.7
CLRB irCmd
JMP SIRCS_Exit
Update_BitWidth:
INC irBitWidth
SETB irBit
SIRCS_Exit:
BANK __DEFAULT
ENDASM
Okay, I know this is Assembly and can look a little
scary at first, but it's really not; in fact, as you work
through it you'll see that it very closely matches the high-level SX/B version we did earlier. The code starts by dividing the ISR by three to get the desired sample timing. The
interrupt runs every 3.255 microseconds so dividing by
three gets us to 9. 76 microseconds — this is close enough
to the 10 microsecond sample rate used by PULSIN that
we can use the same sample values for bit measurements.
After dividing the ISR, we'll drop through to the actual
code. This routine can only buffer one SIRCS command and
if one has already been detected and not cleared by the
foreground, we just exit. If we're not already receiving a
stream, then we'll have a look at the input; if it has gone low
(indicating a bit), then we can initiate the decoding process.
Everything gets set up at Start_Packet and on subsequent passes, will jump to Check_Bit. The variable called
irBitCount is used to determine whether we're looking for
the start bit (count is zero) or analyzing data bits. Once a
valid start bit is detected, irBitCount is non-zero and
subsequence passes will be routed to Test_DBit which
handles the bit-by-bit analysis of the incoming stream.
After 13 bits (start plus 12 data bits), the irReady flag is
set to alert the foreground and the word that holds the
packed device and command codes is separated into
clean bytes. Yeah, okay … it's a little hairy at first but
please trust me, after you've worked your way though it a
couple times you'll see that it's not so bad. The good news
for you is that I've already written and tested it — you just
have to pop it into your own applications!
DUAL CONTROL
With the ability to decode the SIRCS stream in the
interrupt, we enable two modes of control for the output
port on our board. The receive UART and the SIRCS
decoder both set flags when they have valid data, so all
we have to do is monitor these flags and deal with them:
Main:
IF irReady THEN Process_IR
IF rxReady THEN Process_Serial
GOTO Main