You are on page 1of 40

AN657

Decoding Infrared Remote Controls Using a PIC16C5X Microcontroller

Author: William G. Grimm


Consultant

INTRODUCTION
For many years the consumer electronics industry has
been employing infrared remote controls for the control
of televisions, VCRs, and cable boxes. This same technology has recently started to appear in industrial applications to eliminate keypads.
Decoding most of the infrared signals can be easily
handled by PIC16C5X microcontrollers. This application note describes how this decoding may be done.
The only mandatory hardware for decoding IR signals
is an infrared receiver. The use of two types is
described here. Both are modular types used often by
the consumer electronics industry. The first type
responds to infrared signals modulated at about
40 kHz. The second responds to non-modulated infrared pulses and has a restricted range. The hardware
costs of each approach will be less than two dollars.
Three PIC16C5X application programs are described,
and instructions on how they can be used to create an
algorithm that can decode just about any remote control signal. Each PIC16C5X application program represents a step in mapping out a pre-existing infrared
format. The final application is a fully implemented
example of decoding and interpreting the infrared signals of a type of Teknika TV remote.

THE THREE LAYERS OF AN


INFRARED SIGNAL
The typical infrared signal used by remote controls has
three layers. The names used for these layers has not
been standardized. In this application note they are
called the infrared, the modulation, and the serial data.
The infrared layer is the means of transmission. Infrared is light whose wavelength is too long to see.
Although you cannot see the infrared beam, it behaves
the same as light, so if you cannot see the target
device, you cannot control it with an infrared signal. To
control around corners or through opaque materials,
RF, usually UHF signals are used. Although this application note does not further mention RF, much of what
is presented here can be used with an RF transmission
medium.

1997 Microchip Technology Inc.

The modulation layer refers to the fact that each burst


of infrared signal is often modulated at a frequency
between 32.75 kHz and 56.8 kHz. This is done to
diminish the effects of ambient light. This layer, however, is optional. Some infrared formats do not modulate their outputs, sending pulses of unmodulated
infrared light instead. This is done to extend the remote
controls battery life and to reduce the cost of the
remote control device.
The serial data layer has the information containing a
command. This is typically coded in the lengths of infrared bursts or in the lengths of gaps between infrared
bursts. A long gap or burst is interpreted as a '1', a short
gap or burst is interpreted as a '0'.

HARDWARE DESCRIPTION
The schematic in Figure 1 shows a tool that can be
made to aid development of infrared receiver code. The
schematic consists of a PIC16C57 connected to one of
two available infrared receivers. One receiver is for
non-modulated signals, the other for modulated signals. Modulated receivers are available from Sharp and
LiteOn, part numbers GP1U521Y and LT-1060 respectively. The non-modulated type is available from Quality
Technologies part number QSE157QT.
The choice of the PIC16C57 is not indicative of the processing power required for decoding. Typical IR
receiver code can fit into less than half the ROM space
available in a PIC16C54, and uses four RAM locations.
The choice of a PIC16C57 in this case was driven by
the need to store a lot of signal lengths for later reading.
A ceramic resonator clocks the PIC16C57. It will give
adequate frequency accuracy to determine pulse and
gap lengths. A RC network does not usually have adequate accuracy.
A button is available for resetting the PIC16C57, and
four jumpers are provided to control the application
start-up. The two digit display is multiplexed and driven
through Q1 and Q2.
Three octal switches are used as inputs to control the
OPTION register and which file is displayed.
The whole circuit derives its power from a 9V, 200 mA
wall mounted supply. U1 regulates the 9V down to 5V
for the PIC16C57 and associated circuitry.

DS00657A-page 1

SW2
+5 +5 +5

+5

U1

C
07

SW1

C
07

RN5
1k

RN4
1k

78M05
2

SW3

+5

C
07

+5

RN4
1k

RN5
1k
d

+5
10 11 12

Power Jack
1
2
C3
0.01 F

C2
47 F
10V

13 14 15

PORTB

x1

+5
A

+5

7
17

18 19 20 21 22 23 24 25

MCLR

6
16

40 pulse

28
+5

+5
0.033 F

B
C

10k x4

RN3
B
10k

RN3
A
10k

11

1 12 10

16

5 18 15 17

A d C e

1997 Microchip Technology Inc.

GP1U5 -21Y or
LT-1060
QSE157QT
LN54YA

B G dp
A

f
e

G
C

d left

U3

U5
U3 - Sharp
LiteOn
U4 - Quality Technologies
U5 - Panasonic

+5

RN2
100k x4

PORTB

PORTC
0

+5

PORTA

PIC16C57

26

PORTA

27
1
2
4 MHz
Ceramic
3
Resonator

C
d right

+5

Q1
+5

Q2

1
S

U4

AN657

FIGURE 1: IR RECEIVER SCHEMATIC

DS00657A-page 2

C1 120 F
35V

AN657
DESCRIPTION OF SOFTWARE TO
AID DEVELOPMENT
This application uses four different firmware files.
IRMAIN.ASM controls the selection of the three application files. The first file is MEASURE.ASM which stores
the infrared burst and gap lengths into memory and
allows playback of that information. IR6121.ASM
decodes NEC6121 infrared format and displays the
received codes on the LED display. The final file, TECNICKA.ASM, shows the final firmware for decoding the
infrared format for a Teknika Television.
IRMAIN.ASM
The firmware listed includes three applications that will
aid in designing an infrared control system.
IRMAIN.ASM reads jumpers 1 and 2 and directs program flow after reset to one of the three applications.
Having no jumper in 2 will direct program flow to
MEASURE.ASM. A jumper in 2 only will direct program
flow to IR6121.ASM. Jumpers in both 1 and 2 will
direct program flow to TEKNIKA.ASM. Jumpers 3 and 4
are not used.

FIGURE 2: IRMAIN FLOWCHART

Start

Is
No
1 Closed?

MEASURE.ASM
This is the most basic and most useful of the three
applications. This program stores the infrared burst and
gap lengths into memory, allowing playback of the measurements through the two digit display. It allows external control of the OPTION register also, through SW1.
The setting of SW1 is read directly into the OPTION
register prescaler value for TMR0. If SW1 is changed
during program operation, the PIC16C57 resets.
Upon start-up a hyphen will be displayed in the left
digit space until the infrared input settles to the dark
logic indicating that the unit is ready to receive an infrared signal.
As an infrared signal comes in, the lengths of bursts of
infrared, and the lengths of gaps between burst are
stored in consecutive file locations until all four pages
of the PIC16C57s memory files are filled. If a jumper
had been in 1, the program throws away the first 32
pulse and gap lengths and starts storing pulse and gap
lengths with the thirty third pulse length. This allows the
decoding of very long formats.
When all four pages of file memory are filled with pulse
and gap lengths, a number and decimal point are displayed. The decimal point indicates that the unit is done
reading. The number is a gap or pulse length. SW2 and
SW3 control the time sequence of the pulse or gap
length displayed. These are in octal with SW3 being the
more significant digit.

Goto MEASURE

Yes

Is
No
0 Closed?

Goto IR6121

Yes

Goto TEKNIKA

1997 Microchip Technology Inc.

DS00657A-page 3

AN657
FIGURE 3: MEASURE.ASM FLOWCHART

1/8
second
elapsed?

MEASURE

Is 1
Closed?

No

Yes

No

Read Option
switch

SW1

Yes
Load TR_Count
with delay

Yes

Option
switch
changed?
No

SW1

Read Option SW
Program Option
Register

SW2
Read SW 2 & 3
SW3
Calculate
file to be
displayed

Read Receiver

IR

Convert value
in file to digits
for display

No

Dark 8 ms?
Yes

Is
reading
complete?

No
Read Receiver

IR

Yes
Display digit
not now being
displayed

Receiver
changed?
No

Yes

Calculate time
duration using
subtraction
Store in File

File
registers
full?

Yes

No
Set All Done
Flag

Read TMR0

No

TMR0
Overflow?
Yes
Reload TMR0
Increment Timer

DS00657A-page 4

1997 Microchip Technology Inc.

AN657
IR6121.ASM
This is an example of the next stage in development. It
uses the IR receiver, PIC16C57 clock frequency,
OPTION prescaler value and characteristic time length
constants that were found after using MEASURE.ASM
with an infrared remote control based on the NEC6121
infrared controller[1]. The resulting algorithm is able to
decode the infrared bit stream and display it as four
bytes on the two digit display. The bytes are switched
using SW1 (changing it will not cause this application to
reset). From it, or such a program customized to your
particular remote control, a list can be made of how
each button on a remote control resolves to a set of
bytes in memory. This allows the creation of a button
lookup table.

FIGURE 4: 1/4 SECOND CHORES


1/4 Sec Chores

Hold
Set?

No

Goto NewLoop

Yes

HOLD_
RCVD
Set?

No

Goto RESET_IR

Yes

Goto NewLoop

1997 Microchip Technology Inc.

DS00657A-page 5

AN657
FIGURE 5: IR6121.ASM FLOWCHART
IR6121

NewLoop

Does
No
gap length equal
hold?

Setup ports, TMR0


and fixed Option
register

Yes

Update Display
Read IR Receiver

Set HOLD
and HOLD_RCVD

IR

Receiver
Yes
state changed
lo to hi?

Record TMR0
in Read_LH

No

RESET_IR

Receiver
state changed
lo to hi?

IR_STATE = 0

Calculate gap
duration using
subtraction

Yes

No

No

No

IR_STATE= 0

TMR0
overflow?

Is gap
duration > 38h
& < 48h?

Yes

Yes

Is
IR_STATE
= 0?
No

Yes
IR_STATE = 1

Reload TMR0

other
No

1/8 sec
timeout?

IR_STATE =
IR_STATE + 1

Setup display for


byte 1, 2, 3, or 4

Yes

Yes
Read switch

Rotate 1
into byte 1

Is gap
duration mean
0,1 or other?

No

Rotate 0
into byte 1
SW1

other
Rotate 1
into byte 2

Is gap
duration 0,1
or other?

Yes

0
No

1/4 sec
time-out?
Yes

Is
IR_STATE
<= 8?

Is
IR_STATE
<= 16?
No

Rotate 0
into byte 2

Goto RESET_IR

other
Rotate 1
into byte 3

Is gap
duration 0,1
or other?

Yes

1/4 sec Chores


0

Is
IR_STATE
<= 24?
No

Rotate 0
into byte 3
other
Rotate 1
into byte 4

Is gap
duration 0,1
or other?

Yes

Is
IR_STATE
<= 32?

No

0
Rotate 0
into byte 4

DS00657A-page 6

1997 Microchip Technology Inc.

AN657
TEKNIKA.ASM
This is an example of a finished product. This program
fully decodes the infrared format of a Teknika Television. When a number is pressed on the remote control
it is displayed on the display. When channel up or channel down is pressed, the displayed number increases or
decreases.
It incorporates the final step in implementing a remote
control decoder, that of cross referencing codes to button numbers. The algorithm will only respond if the first

two bytes are 14h and EBh, the characteristic of this


type of Teknika television. Byte 3 and byte 4 are
checked to see if they are complements. If so, byte 3 is
sent through a lookup table to determine which button
the received byte corresponds to, then the appropriate
action is taken. The lookup table was made by using
IR6121 and recording byte 3 with the button pressed.
Similar tables can be made using other remote controls.

FIGURE 6: TEKNIKA.ASM FLOWCHART


Teknika

Setup ports,
Option register,
and TMR0

Read IR
receiver

Service Hold

Is
Yes
HOLD_RCVD
clear?
No

Clear HOLD

Clear
HOLD_RCVD

Is
HOLD
set?

Receiver
changed lo to
hi?
No

Yes

Record TMR0
in READ_LH

Receiver
changed hi to
lo?
No

Yes

Call
TekRdRcvr

No
TMR0 rollover?

Yes
Is
ACTIVE_UP
set?

IR

Yes

No

Yes
BUTTON =
BUTTON + 1

Reload TMR0

No
Is
Yes
ACTIVE_DOWN
set?
No

BUTTON =
BUTTON - 1

Display value
in button

Is
1/8 second
due?

No

Yes
Is
HOLD
set?

No

Yes
Goto Service
Hold

1997 Microchip Technology Inc.

DS00657A-page 7

AN657
FIGURE 7: TEKRDRCVR, TEKIRRESET, TEKRDADDR FLOWCHART
TekRdRcvr

TekRdAddr

Calculate gap
duration using
subtraction

Is
IR_BYTE13
= 14h?

No

Goto
TekIRReset

No

Goto
TekIRReset

Yes
Is
gap length
> 1Ah?

No

Return

Yes

Yes

Yes

No

Return

Is
gap length
< 27h?

No

Return

Is
IR_BYTE24
= 0EBh?

Hold
flag?

Yes

Set
HOLD_RCVD

Return

Goto
TekIRReset

Set Carry

Is
gap length
> 1Fh?

No

No

Is
gap length
> 38h?

No

Yes

Yes

Is
gap length
< 0Eh?

Is
gap length
< 48h?

Yes

Yes

Clear Carry

TekIRReset

No

IR_STATE = 0
Clear:
Hold, New_Key
HOLD_RCVD
ACTIVE_UP
ACTIVE_DOWN

IR_STATE = 1

Return
Return
Is
IR_STATE
bit3 set?

Yes

rrf IRBYTE24

No
rrf IRBYTE13

IR_STATE =
IR_STATE +1

Is
IR_STATE
= 16?
Yes
Goto
TekRdAddr

DS00657A-page 8

No

Is
IR_STATE
= 32?

No
Return

Yes
Goto
TekRdCommand

1997 Microchip Technology Inc.

AN657
FIGURE 8: TEKCOMMAND FLOWCHART

TekRdCommand

Set
ACTIVE_UP

Yes

Is
IR_BYTE13
= 13h?

Yes

Is
IR_BYTE13
= IR_BYTE24?

No

Goto
TekIRReset

No

Set
ACTIVE_DOWN

Yes

Is
IR_BYTE13
= 12h?
No

TekLogCommand

Goto
TekLogCommand
Set:
KEY_READY
HOLD
HOLD_RCVD

Set
IR_BYTE24
= 10

Return
IR_BYTE24 =
IR_BYTE24 - 1
Use IR_BYTE24
as an index
to read table

Is
table value =
IR_BYTE13?

Yes

Move
IR_BYTE24
into button
to be displayed

No

Is
IR_BYTE24
= 0?

1997 Microchip Technology Inc.

Yes

Goto
TekLogCommand

DS00657A-page 9

AN657
INSTRUCTIONS ON WRITING AN
ALGORITHM TO DECODE IR
REMOTES
1.

2.

3.

4.

5.

6.

7.

To design a system that uses an infrared remote


control, the first step is to choose a remote control. Self designed or off the shelf, modulated or
unmodulated are the primary technical decisions.
Once a remote control has been chosen or
designed, its modulation frequency, if it has one,
must be determined. This controls the kind of
hardware used to receive the infrared signal.
The next step is to determine the time-base of
the data, that is, if the pulses and gaps are short
or long in reference to the PIC16C57 clock. The
OPTION switch, SW1, is used to get optimum
length pulse and gap counts from TMR0. This
defines the value of the OPTION prescaler.
Fourth, definition is made as to what, in the format, defines a '1', and what, in the format,
defines a '0'. This could be gap counts, pulse
counts, or a combination of both.
Fifth, determination is made of the full length of
commands. This enables the determination as
to whether a button is being held down or if a
new command of the same type as previous is
being issued.
The sixth step requires the writing of code. The
code will resolve the gap and pulse lengths and
command lengths into bits and bytes. Each button on the remote will decode to a unique series
of bits.
The seventh and final step takes these codes
that are received and converts them to button
numbers or commands, using a lookup table.

Step 1: Choosing a remote control


Depending on your application, you may choose to
have an off the shelf remote control or design one yourself. Typically they have small 4-bit microcontrollers in
them, preprogrammed for a serial format. Some companies such as General Instrument sell them as complete units, others such as NEC sell the main
component which can be customized by external
diodes to not interfere with other applications. It is also
possible to program a PIC16C57 to generate a signal
that can be sent to an infrared LED for transmission. Yet
another approach is to use a programmable remote
control to generate any number of infrared formats and
use them right off the shelf to control the target device.

Step 2: Determining a modulation frequency


For this and the next step the MEASURE.ASM program
will be used. To start out, use the non-modulated
receiver and a PIC16C57 running the MEASURE.ASM
application. Select 1 on the option selector. Press a but-

DS00657A-page 10

ton until the decimal point comes on. Using the jumpers
switch through the memorized pulse durations that the
PIC16C57 will have stored in its memory.
If all of the reading except the first are below 40h, the
infrared format is a modulating one. If half or more of
the values show up as 0FFh, then the remote is
non-modulating.

Step 3: Determine time-base


If the remote control is modulated, switch to a demodulating IR receiver. With the option selector still at 1,
press a button on the remote control again until the
decimal point comes on. The series of memorized
pulse durations will now probably include a lot of FFh
values. If so, move the Option selector up until the values are in the 7h to 1Fh range. The Option selector has
the optimum value for the option divisor to be used in
the TMR0 register.
To optimize range and reliability, several demodulating
receivers may be tried. These are available from Sharp
or LiteOn. The modulating frequencies that are presently used are 32.75 kHz, 35.0 kHz, 36.0 kHz, 36.7
kHz, 38 kHz, 39 kHz, 40 kHz, 41.7 kHz, 48 kHz, and
56.8 kHz[2]. The most common are round 40 kHz. The
best match for your remote control will give the longest
range and most consistent results.

Step 4: Decoding ones and zeros


The next step is to map out the characteristic pulse and
gap lengths that represent ones and zeros. By pressing
the same button on the remote, write down the series
of numbers read by the PIC16C57 running the
MEASURE.ASM program. Each odd numbered entry is
the duration of a burst of IR from the remote control.
Each even numbered entry is the duration of a gap
between bursts of infrared. The lengths of these gaps
and bursts define ones and zeros. Their order will
depend on which button is pressed. Once the characteristic lengths have been discovered for a one and a
zero, an algorithm can then be created with a counter
to translate the lengths into ones and zeros.

Step 5: Finding the Command Length


Press the same button again. The command duration
can also be found. This is necessary to determine if a
button is being held down or a new command of the
same type is being issued. Most remote controls repeat
the command as long as the button is held down, the
repetitions separated by a long dark time, usually 0FFh
on an even numbered transition. If no long even numbered counts can be found, consider that some commands can be longer than 64 transitions. The option to
delay counting is available for this reason. Insert jumper
1 and MEASURE.ASM will only start storing transition
times after the 32nd transition.

Step 6: Translating lengths to bits


Once the characteristic lengths of ones and zeros have
been found and the length of the typical command has
been found, a program can then be written to decode

1997 Microchip Technology Inc.

AN657
these lengths to ones and zeros and display them on
the two digit display. Also a HOLD flag can be created
which will be true as long as the button is being held
down. Usually 1/8 second between commands indicates a new command. Use this value to time out
HOLD times and times between commands.
IR6121.ASM is an example of a program that translates
the gap lengths of the NEC6121 format to the four bytes
that make up the information in each command.

REFERENCES
[1] Infrared Remote Controls ICs; NEC Electronics.
August 1991. Literature available 1-800-632-3531.
[2] Sharp Optoelectronics Data Book, 1991/1992, page
961.

Step 7: Create a button to code cross


reference table
TEKNIKA.ASM implements a lookup table to translate
the codes received to the actual button pressed. A
counter is loaded with the highest number button that
can be pressed, and the code is then looked up and
compared with the code that was received. If no match,
the counter is decremented until a match is found.
When found, the counter then has the button number
that was pressed.
Note too, that more checking may be done at this level
on some formats, such as having an address, a complement of the code following the code itself for checking.
The result from all of the steps in decoding is that if a
button is pressed on a remote control, that button number appears in a PIC16C57 file location. A command
such as channel up or channel down will appear as two
set flags, one to indicate the command, the other to
indicate that it is active, HOLD. From this point the
application can access these flags and files to respond
appropriately.

1997 Microchip Technology Inc.

DS00657A-page 11

AN657
Please check the Microchip BBS for the latest version of the source code. Microchips Worldwide Web Address:
www.microchip.com; Bulletin Board Support: MCHIPBBS using CompuServe (CompuServe membership not
required).

APPENDIX A: IRMAIN.ASM
MPASM 01.40 Released

LOC OBJECT CODE


VALUE

00000083

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00001
00002
00224
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051

DS00657A-page 12

IRMAIN.ASM

10-2-1996

10:24:32

PAGE

LINE SOURCE TEXT

TITLE
"IR Receiver Ap-Note Program Selector V0.02"
;
;************************************************************************
; File Name :
IRMAIN.ASM
;************************************************************************
;
Author:
William G. Grimm
;
Company:
Microchip Technology
;
Revision: V0.02
;
Date:
March 28, 1996
;
Assembler: MPASM version 1.21
;
;************************************************************************
;
Revision History:
;
;
;
V0.01
Original March 28, 1996
;
;
V0.02
Added the Technika routine March 28, 1996
;
;
;************************************************************************
; Assembly options
LIST
P=16C57,r=hex,N=75,C=120,T=ON
;
;************************************************************************
;
Required modules:
;
;
picreg.equ
;
irundef.asm
; undefines constants for include files
;
measure.asm
; decodes all remotes
;
ir6121.asm
; decodes all 6121 format remotes
include
"p16c5x.inc"
LIST
; P16C5X.INC Standard Header File, Version 3.30 Microchip Tech, Inc.
LIST
;
;************************************************************************
;
;
;
;************************************************************************
; Ceramic resonator or Crystal, 4.000Mhz. If a Prescaler of
; 64 (5 in the option register) is used, TMR0 will increment every
; 64.00 microseconds.
; If TMR0 is initially loaded with 131, TMR0 will overflow to 0
; in 8.000 milliseconds.
MSEC8
EQU
D'131'
;************************************************************************
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "File and Flag definitions."
;************************************************************************
; file memory location definitions

1997 Microchip Technology Inc.

AN657

0000000E
0000000F

0000000F
0000003F

0000001E
00000000

000000BF

00000003

00000006
00000007

00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117

;************************************************************************
;
; full byte file memory locations
;
LEFT_DIGIT
EQU
0E
; code to be displayed on left digit
RIGHT_DIGIT
EQU
0F
; code to be displayed on right digit
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Constant definitions."
; ***********************************************************************
; Definition of program constants
SUBTITL "Constant definitions."
; ***********************************************************************
; Definitions of constants used to configure the ports
A_CONFIG EQU 0f
; IR input and option dial all inputs
;
B_CONFIG EQU 03f
; PORTB has outputs on bits 6 and 7 for
; the display, bits 0 to 5 are inputs for
; the dials
;
C_CONFIG1 EQU 01e
; lines 1,2,3, and 4 are input during selection
C_CONFIG2 EQU 0
; all lines are outputs normally
;
;************************************************************************
; Definition of program constants
;
HIPHEN
EQU B'10111111'
; - for display
;
;
;DEFINE PORT_A REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y| --> OPTION dial bit 0
;
| | | | | |Y| | --> OPTION dial bit 1
;
| | | | |Y| | | --> OPTION dial bit 2
;
| | | |Y| | | | --> IR input
;
| | |O| | | | | --> Unavailable
;
| |O| | | | | | --> Unavailable
;
|O| | | | | | | --> Unavailable
;
O| | | | | | | | --> Unavailable
;
IR
EQU 3
; IR receiver
;
;DEFINE PORT_B REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y| --> Right dial bit 0
;
| | | | | |Y| | --> Right dial bit 1
;
| | | | |Y| | | --> Right dial bit 2
;
| | | |Y| | | | --> Left dial bit 0
;
| | |Y| | | | | --> Left dial bit 1
;
| |Y| | | | | | --> Left dial bit 2
;
|Y| | | | | | | --> controls right digit, LOW is on
;
Y| | | | | | | | --> controls left digit, LOW is on
; Y = DEFINED AS SHOWN (0/1)
;
RIGHT_OFF
EQU 6
LEFT_OFF
EQU 7
;
;DEFINE PORT_C REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
0 turns element on
;
| | | | | | |Y| --> A
;
| | | | | |Y| | --> D SW1
;
| | | | |Y| | | --> C SW2

1997 Microchip Technology Inc.

DS00657A-page 13

AN657

00000001
00000002
00000007

0000
0000 0E0F
0001 01E2

0002
0003
0004
0005
0006
0007
0008
0009
000A
000B
000C
000D
000E
000F
0010
0011

08C0
08DB
0894
0898
088B
08A8
08A0
08DA
0880
0888
0882
08A1
08B5
0891
08A4
08A6

0012
0012 07C6
0013 0A19
0014 091E
0015
0016
0017
0018
0019
0019

020F
0027
04C6
0800

001A
001B
001C
001D

020E
0027
04E6
0800

091E

00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183

DS00657A-page 14

;
| | | |Y| | | | --> E
;
| | |Y| | | | | --> F
;
| |Y| | | | | | --> B
;
|Y| | | | | | | --> G
;
Y| | | | | | | | --> dp
; Y = DEFINED AS SHOWN (0/1)
;
SW1
EQU 1
SW2
EQU 2
DP
EQU 7
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Display."
; ***********************************************************************
; Display handling routines
;
;-----------------------------------------------------------------------; LookUpDigit
; Inputs a number, outputs the bit pattern to display that number
;-----------------------------------------------------------------------LookUpDigit
andlw 0F
; mask off any higher order bits
addwf PCL,F
; add to create a jump to a return
;
76543210
; PORTC line
;
GBFECDA
; element assignment
retlw B'11000000'
; Zero
retlw B'11011011'
; 1
retlw B'10010100'
; 2
retlw B'10011000'
; 3
retlw B'10001011'
; 4
retlw B'10101000'
; 5
retlw B'10100000'
; 6
retlw B'11011010'
; 7
retlw B'10000000'
; 8
retlw B'10001000'
; 9
retlw B'10000010'
; A
retlw B'10100001'
; b
retlw B'10110101'
; c
retlw B'10010001'
; d
retlw B'10100100'
; E
retlw B'10100110'
; F
;
;-----------------------------------------------------------------------; UpdateDisplay
; Rotates power to each of the three display digits.
;-----------------------------------------------------------------------UpdateDisplay
btfss PORTB,RIGHT_OFF
; Check the right digit
goto
RightOn
; right digit is on now
;
call
DisplayOff
; turn off all displays, and read PORTC
; inputs if active
movf
RIGHT_DIGIT,W
; Left digit is on, turn on right digit
movwf PORTC
; send right digit out to the port
bcf
PORTB,RIGHT_OFF
; turn on the right digit
retlw 0
RightOn
call
DisplayOff
; turn off all displays, and read PORTC
; inputs if active
movf
LEFT_DIGIT,W
; Right digit is on, turn on left digit
movwf PORTC
; send left digit out to the port
bcf
PORTB,LEFT_OFF
; turn on the left digit
retlw 0
;
;-----------------------------------------------------------------------; DisplayOff

1997 Microchip Technology Inc.

AN657
001E
001E 05E6
001F 05C6
0020 0800

0200
0200

00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054

; Turns off the display at the three transistors


;-----------------------------------------------------------------------DisplayOff
bsf
PORTB,LEFT_OFF
; turn off the left digit
bsf
PORTB,RIGHT_OFF
; turn off the right digit
retlw 0
;
;************************************************************************
; include files
org
200
BeginMeasure
include
"measure.asm"
TITLE
"IR Receiver output measurement routine V0.07"
;
;************************************************************************
; File Name :
MEASURE.ASM
;************************************************************************
;
Author:
William G. Grimm
;
Company:
Microchip Technology
;
Revision: V0.07
;
Date:
March 31, 1996
;
Assembler: MPASM version 1.21
;
;************************************************************************
;
Revision History:
;
;
;
V0.01
Original January 9, 1995
;
;
V0.02
Added overflow indication January 12, 1996
;
;
V0.03
Modified to conform to Microchip specifications
;
February 17, 1996
;
;
V0.04
Modified for new hardware March 19, 1996
;
;
V0.05
Changable option register and delay added
;
March 20, 1996
;
;
V0.06
Added code that creates 1/8 second time out
;
for all options 1 to 7, 0 gets a 1/16 second time out.
;
March 26, 1996
;
;
V0.07
Improved roll over detection for long gaps and pulses
;
March 27, 1996
;
;
V0.08
Changed to header file March 31, 1996
;
;
V0.09
Fixed bug that kept jumper 1 from being read
;
;
;************************************************************************
; Assembly options
LIST
P=16C57,r=hex,N=75,C=120,T=ON
;
;************************************************************************
;
;
;
;************************************************************************
;************************************************************************
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "RAM and Flag definitions."
;************************************************************************
; file memory location definitions

1997 Microchip Technology Inc.

DS00657A-page 15

AN657

00000008
00000009
0000000B
0000000C
0000000D

00000001
00000002
00000003
00000004
00000005
00000006

00000020
00000000

0200
0200
0201
0202
0203
0204
0205
0206
0207

0C83
01C1
0021
0004
076C
058C
046C
02AB

00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120

DS00657A-page 16

;************************************************************************
;
; full byte file memory locations
;
START_COUNT
EQU
08
; TMR0 value at previous IR rcvr transition
TR_COUNT
EQU
09
; transition being read
TIMERM
EQU
FLAG
EQU
SCALE_RECORD EQU
;
LEFT_DIGIT
;
RIGHT_DIGIT

0b
0c
0d
EQU
EQU

0E
0F

;
;
;
;

Bit5 = 1/4 sec, Bit1 = 16 millisecs.


program flags
prescaler value is stored here
defined in main routine

; Files 10h-1fh,30h-3fh,50h-5fh,70h-7fh
; are used to store IR pulse and gap lengths.
;
;
;
;
;DEFINE FLAG REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y| -->
;
| | | | | |Y| | --> Eighth second flag.
;
| | | | |Y| | | --> used for math, TMR0 overdue for reload
;
| | | |Y| | | | --> the Value START_COUNT is new
;
| | |Y| | | | | --> measurement has overflowed
;
| |Y| | | | | | --> Value of last IR bit received.
;
|Y| | | | | | | --> if set memory is full, stop reading
;
Y| | | | | | | | -->
;
_8TH_SEC
EQU 1
OVERDUE
EQU 2
NEW_START_COUNT
EQU 3
OVERFLOW
EQU 4
LAST_IR
EQU 5
ALL_DONE
EQU 6
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Constant definitions."
; ***********************************************************************
; Definition of program constants
;
SKIP_NUM EQU d'32'
; readings to skip before filing them
OPTION_MASK
EQU
B'00000000' ; SET UP PRESCALER, WDT on 18msec.
; lowest three bits must be zero to not
; overwrite the prescaler dialed in
; externally
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Timer routines."
; ***********************************************************************
; Timer servicing routine
;
Called every 1.6 to 8 milliseconds this clears the
;
watch dog, reloads TMR0
;
and keeps track of relative time.
;
ServiceTimerM
movlw
MSEC8
;TMR0 = 8 milliseconds.
addwf
TMR0,W
; Add overflow amount.
movwf
TMR0
;
/
clrwdt
btfss
FLAG,NEW_START_COUNT ; find if measured length is too long
bsf
FLAG,OVERFLOW
; length is too long to measure
bcf
FLAG,NEW_START_COUNT ; set the flag indicating the reload
incf
TIMERM,F
; increment the timer

1997 Microchip Technology Inc.

AN657
0208
0209
020A
020B
020C
020D
020E
020F
020F
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219

090F
018B
0743
0800
006B
052C
0800

020D
0E07
01E2
0800
0800
0880
0840
0820
0810
0808
0804

021A
021A 05AC
021B 02A9
021C 0509
021D
021E
021F
0220

0C3F
0189
0643
05CC

0221 0A25
0222
0222 04AC
0223 02A9
0224 0409

0225
0225 0208
0226 0081
0227 0028
0228
0229
022A
022B

0C83
0088
0603
0028

00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186

call
xorwf
btfss
retlw
clrf
bsf
retlw

TimerLookup
TIMERM,W
STATUS,Z
0
TIMERM
FLAG,_8TH_SEC
0

;
;
;
;
;
;
;

get the maximum count


see if maximum count is here
Is maximum count there?
not there return
reset the timer
Set the 1/8 sec flag.
reset and ready for 1/8 sec chores

;
TimerLookup
movf
SCALE_RECORD,W
; bring in the record of the option
andlw
7
; ensure lookup table is not overjumped
addwf
PCL,F
; look up the proper timer overflow
retlw
0
; this will only get 1/16 sec time out
retlw
0
; option = 1
retlw
b'10000000'
; option = 2
retlw
b'01000000'
; option = 3
retlw
b'00100000'
; option = 4
retlw
b'00010000'
; option = 5
retlw
b'00001000'
; option = 6
retlw
b'00000100'
; option = 7
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "IR counter."
;
;
; ***********************************************************************
; IR Receiver routines
;
;-----------------------------------------------------------------------; ReadReceiver
; Second part of the IR receiver. It takes the present count of the
; TMR0 and subtracts the count recorded when the receiver output
; went high (START_COUNT) to find the dark pulse duration. In that duration
; will be encoded the 1, 0, HOLD, or attention.
;-----------------------------------------------------------------------ReadReceiverHi
bsf
FLAG,LAST_IR
; record the IR receiver state
incf
TR_COUNT,F
bsf
TR_COUNT,0
; Times when IR rcvr is Lo are recorded
; in odd numbered locations
movlw
3fh
; bring in highest valid address in
xorwf
TR_COUNT,W
; TR_count see if highest count is in
btfsc
STATUS,Z
; skip if not highest address
bsf
FLAG,ALL_DONE
; set all done flag to stop reading
goto
TimeIRReceiver
;
ReadReceiverLo
bcf
FLAG,LAST_IR
; record the IR value
incf
TR_COUNT,F
bcf
TR_COUNT,0
; Times when IR rcvr is Hi are recorded
; in even numbered locations
;
; Calc the length of the dark pulse,
; length of time receiver was high.
; (placed in START_COUNT)
TimeIRReceiver
movf
START_COUNT,W
; bring in the start measurement
subwf
TMR0,W
; subtract the final from the start
movwf
START_COUNT
; gap or pulse length is now in
; START_COUNT, must be checked
movlw
MSEC8
; Base number of TMR0 count.
subwf
START_COUNT,W
; Subtract the base count of TMR0
btfsc
STATUS,C
; skip the store and toss value if neg.
movwf
START_COUNT
; value was positive, store

1997 Microchip Technology Inc.

DS00657A-page 17

AN657
022C
022C 06E9
022D 0A3A

022E
022F
0230
0231
0232
0233
0234
0235

0209
0E0F
0024
0584
0689
05A4
06A9
05C4

0236
0237
0238
0239

0CFF
078C
0208
0020

023A
023A 0201
023B 0028
023C 056C

023D 048C
023E 0800

023F
023F 042C
0240 0246
0241 0024

0242
0243
0244
0245
0246
0247
0248

04C4
06A4
05C4
04A4
0684
05A4
0584

0249 04A3
024A 04C3
024B 0380
024C 0900
024D 002E
024E 0200
024F 0900
0250 002F

0251 05A3

00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252

DS00657A-page 18

;
MathDone
btfsc
goto
;

TR_COUNT,7
DoNotStore

; check to see if in delay


; do not store the value if in delay

movf
andlw
movwf
bsf
btfsc
bsf
btfsc
bsf

TR_COUNT,W
0f
FSR
FSR,4
TR_COUNT,4
FSR,5
TR_COUNT,5
FSR,6

;
;
;
;
;
;
;
;
;

format for FSR


Setup place the count will be stored
reduce to file location
place file address in FSR
set to place in upper file group
set bank bit 0
/
set bank bit 1
/

movlw
btfss
movf
movwf

0ffh
FLAG,OVERFLOW
START_COUNT,W
INDF

;
;
;
;
;

bring in the overflow indication


skip loading of result if overflowed
bring in the measurement
store it for display using
indirect addressing

DoNotStore
movf
movwf
bsf

bcf

TMR0,W
;
START_COUNT
;
FLAG,NEW_START_COUNT
;
;
;
FLAG,OVERFLOW
;

bring in the count now


store it for next time
set ind flag that START_COUNT is new.
this flag is used to determine if the
pulse has gone on too long to measure
clear any overflow indication

;
retlw
0
;
;
;************************************************************************
; The following code segments are called by the executive
; every 1/8 second and every two seconds
;
EighthSecondChores
; all that needs doing every 1/8 sec
; can be placed in this subroutine
bcf
FLAG,_8TH_SEC
; clear the time out flag
;
comf
PORTB,W
; read the dial settings
; the requested memory location is in W
movwf
FSR
; Following formats the FSR to point to
; the selected file w/ the IR pulse
bcf
FSR,6
; or gap length
btfsc
FSR,5
; move bit 5 to 6
bsf
FSR,6
; if 5 was 1, set 6
bcf
FSR,5
btfsc
FSR,4
; move bit 4 to 5
bsf
FSR,5
; if 4 was high, set bit 5 of fsr
bsf
FSR,4
; Format for FSR, upper bank of bytes
;
bcf
STATUS,PA0
; get ready to call from page 1
bcf
STATUS,PA1
; /
;
swapf
INDF,W
; bring in IR measurement to be dispd
call
LookUpDigit
movwf
LEFT_DIGIT
; display more significant digit
;
movf
INDF,W
; bring in IR measurement to be dispd
call
LookUpDigit
movwf
RIGHT_DIGIT
; display less significant digit
;
if BeginMeasure==200
; return the bits to this page
bsf
STATUS,PA0
; page 1

1997 Microchip Technology Inc.

AN657
0252 04C3

0253 0245
0254 0E07
0255 018D
0256 0743
0257 0A61
0258 0AAD

0259
0259 0024
025A 003F
025B
025B 02A4
025C
025D
025E
025F
0260

0060
021F
0743
0A5B
0800

0261
0261 006C
0262 006B
0263 0069
0264 0C0F
0265 0959
0266 0C2F
0267 0959
0268 0C4F
0269 0959
026A 0C6F
026B 0959
026C 0C0F
026D 0005
026E 0C3F
026F 0006

0270 05E6
0271 05C6
0272 0C1E

00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318

bcf
STATUS,PA1
endif
if BeginMeasure==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginMeasure==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif

; /

; page 2
; /

; page 3
; /

;
comf
andlw
xorwf
btfss
goto
goto

PORTA,W

; bring in the reqd prescale value


; from the dial, reverse sense
7
; AND w/ highest possible prescale value
SCALE_RECORD,W
; compare the prescale dial setting
; with the original one
STATUS,Z
; skip if the same
StartMeasure
; restart the application if different
DoneEighthSecondChores

;
;
ClearRam
movwf
FSR
movwf
1fh
MemoryInitLoop
incf
FSR,F
clrf
movf
btfss
goto
retlw

INDF
1fh,w
STATUS,Z
MemoryInitLoop
0

; clears memory at reset


; place in fsr for indirect addressing.
; when zero, memory init is done.
;
;
;
;
;
;

increment to the next memory location


to be initialized.
clear memory location.
Has top memory location zeroed yet?
/
/

;
;
;************************************************************************
;
Start HERE.
;************************************************************************
StartMeasure
clrf
FLAG
; Clear out flag bank 1.
;
clrf
TIMERM
; restart the TIMERM at 0
;
clrf
TR_COUNT
; initialize memory counter
;
movlw
0f
; start zeroing at memory location 10h
call
ClearRam
; clear the first bank of memory
;
movlw
2f
; start zeroing at memory location 10h.
call
ClearRam
; clear the second bank of memory
;
movlw
4f
; start zeroing at memory location 10h
call
ClearRam
; clear the third bank of memory
;
movlw
6f
; start zeroing at memory location 10h
call
ClearRam
; clear the fourth bank of memory
;
movlw
A_CONFIG
; setup for PORTA, in loop so
; micocontroller will never forget
tris
PORTA
; inputs on bit 0.
movlw
B_CONFIG
tris
PORTB
; PORTB has outputs on bits 0,6,7;
; inputs on bits 1, 2, 3, 4, and 5.
;
bsf
PORTB,LEFT_OFF
; turn off both digits to read jumpers
bsf
PORTB,RIGHT_OFF
; /
movlw
C_CONFIG1
; configuration to read from PORTC

1997 Microchip Technology Inc.

DS00657A-page 19

AN657
0273
0274
0275
0276

0007
0CE0
0727
0029

0277 0C00
0278 0007
0279 0245
027A
027B
027C
027D

027E
027F
0280
0281

0E07
002D
0D00
0002

0CBF
0027
05E6
04C6

0282 0C83
0283 0021
0284
0284
0285
0286
0287
0288
0289
028A
028B
028C
028D
028E

0C83
0081
0603
0A84
0900
0765
006B
072C
0A84
006C
05AC

028F
0290
0291
0292

0CBF
0027
04E6
05C6

0293 093A

0294

0294
0294
0295
0296
0297
0298

07CC
0A9E
04A3
04C3
0912

0299 05A3
029A 04C3

00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384

DS00657A-page 20

tris
movlw
btfss
movwf

PORTC
-(SKIP_NUM)
PORTC,SW1
TR_COUNT

;
;
;
;

configure PORTC to read the bits


let inputs settle, bring in skip numb
skip if jumper 1 is not installed
move the skip number to file pointer

movlw
tris

C_CONFIG2
PORTC

; bring in config to use PORTC for disp


; PORTC is normally all outputs

comf

PORTA,W

andlw
movwf
iorlw
option

7
SCALE_RECORD
OPTION_MASK

;
;
;
;
;
;

bring in the requested prescale


value from the dial, reverse sense
AND w/ highest possible prescale value
record the value of the prescaler
Setup prescaler for TMR0, WDT on 18ms.
/

movlw
movwf
bsf
bcf

HIPHEN
PORTC
PORTB,LEFT_OFF
PORTB,RIGHT_OFF

;
;
;
;

Disp that unit waiting for dark conds


put the Hiphen on right digit
turn off left digit
turn ON right digit

movlw
movwf

MSEC8
TMR0

;TMR0 = 8 mSEC
;
/

;
;

;
SettlingLoop
movlw
MSEC8
; Check for overflow.
subwf
TMR0,W
; SEE IF TMR0 < MSEC8,
btfsc
STATUS,C
; If TMR0 < MSEC8, Overflow.
goto
SettlingLoop
; No overflow, no carry, loop.
call
ServiceTimerM
; Keep time and reload time keeper.
btfss
PORTA,IR
; IR receiver quiet?
clrf
TIMERM
; not quiet, reset timer
btfss
FLAG,_8TH_SEC
; Allow out of loop if quiet for 1/8sec
goto
SettlingLoop
; not quiet long enough yet
clrf
FLAG
; re-clear all of the flags
bsf
FLAG,LAST_IR
; set the flag, receiver is now hi
;
;
movlw
HIPHEN
; Display that unit is ready to receive
movwf
PORTC
; put the Hiphen on right digit
bcf
PORTB,LEFT_OFF
; turn on left digit
bsf
PORTB,RIGHT_OFF
; turn OFF right digit
;
call
DoNotStore
; setup timer last read for first read
;
;************ Main loop Starts here. *************
Main
;
;
InnerLoop
btfss
FLAG,ALL_DONE
; update display only if memory is full
goto
CheckIr
; not full, keep reading the IR rcvr
bcf
STATUS,PA0
; get ready to call from page 1
bcf
STATUS,PA1
; /
call
UpdateDisplay
; rotate power to the next display digit
;
if BeginMeasure==200
; return the bits to this page
bsf
STATUS,PA0
; page 1
bcf
STATUS,PA1
; /
endif
if BeginMeasure==400
bcf
STATUS,PA0
; page 2
bsf
STATUS,PA1
; /
endif
if BeginMeasure==600
bsf
STATUS,PA0
; page 3

1997 Microchip Technology Inc.

AN657
029B 07C6
029C 04E7
029D 0AA6
029E
029E
029F
02A0
02A1

0665
06AC
02A2
091A

02A2
02A3
02A4
02A5

0765
07AC
02A2
0922

02A6
02A6
02A7
02A8
02A9
02AA

0C83
0081
0603
0A94
0900

02AB 062C
02AC 0A3F

02AD
02AD 0A94

0400
0400

00000005

00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00196
00197
00198
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027

bsf
endif
btfss
bcf
goto
;
CheckIr
btfsc
btfsc
incf
call

STATUS,PA1

; /

PORTB,RIGHT_OFF
PORTC,DP
ReadDone

; skip if the right digit is off


; lite the decimal to show read taken
; memory is full, done reading receiver

PORTA,IR
FLAG,LAST_IR
PCL,F
ReadReceiverHi

;
;
;
;
;

?IR receiver not recvg an IR burst?


was it receiving a burst last time?
Not either, skip next instruction
Record TMR0 value when the lo to hi
transition came from the receiver

PORTA,IR
FLAG,LAST_IR
PCL,F
ReadReceiverLo

;
;
;
;

?IR receiver receiving an IR burst?


was it not receiving burst last time?
Not either skip next instruction
read the new information

MSEC8
TMR0,W
STATUS,C
InnerLoop
ServiceTimerM

;
;
;
;
;

Check for overflow.


SEE IF TMR0 < MSEC8,
If TMR0 < MSEC8, Overflow.
No overflow, no carry, loop.
Keep time and reload time keeper.

FLAG,_8TH_SEC
EighthSecondChores

; check for 1/8 second time out

;
btfss
btfss
incf
call
;
ReadDone
;
movlw
subwf
btfsc
goto
call
;
btfsc
goto

; anything that needs doing every 1/8sec


; can go in this subroutine
DoneEighthSecondChores
;
goto
Main
;
;
org
400
BeginIr6121
include
"ir6121.asm"
TITLE
"IR-NEC6121 format Remote Control Detector V0.02"
SUBTITL
"Comments documentation and history"
;
;************************************************************************
; File Name :
IR6121.ASM
;************************************************************************
;
Author:
William G. Grimm
;
Company:
Microchip Technology
;
Revision: V0.02
;
Date:
February 27, 1996
;
Assembler: MPASM version 1.21
;
;************************************************************************
;
Revision History:
;
;
;
V0.01
Original February 27, 1996
;
;
V0.02
Converted to Ap-note format and made into a header
;
file March 28, 1996
;************************************************************************
OPTION_CODE
EQU
B'00000101'
;SET UP PRESCALER, WDT on 18msec.
;************************************************************************
;
;************************************************************************
; file memory location definitions
;************************************************************************

1997 Microchip Technology Inc.

DS00657A-page 21

AN657

0000000B
0000000C

00000011
00000012
00000013
00000014
00000018
00000019
0000001A
0000001B
0000001C
0000001D
0000001E
0000001F

00000006
00000005
00000004
00000003
00000002
00000001
00000000

00000000
00000001
00000002

00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093

DS00657A-page 22

;
; full byte file memory locations
;
TIMER
EQU
0b
; Bit 5 = 1/4 second, Bit 1 = 16 millisecs.
TEMP
EQU
0c
; temporary file storage
;
;
LEFT_DIGIT
EQU
0e
; defined in irmain
;
RIGHT_DIGIT
EQU
0f
; defined in irmain
READ_LH
EQU
11
; Low to high reading is stored here.
IR_STATE
EQU
12
; Which bit is coming in.
IR_BYTE13
EQU
13
; First byte for collecting inputs.
IR_BYTE24
EQU
14
; Second byte for collecting inputs.
;
FLAG2
EQU
18
; flag bank 2
FLAG3
EQU
19
; flag bank 3
C_BYTE_1
EQU
1A
; Memory location defs for storing inputs
C_BYTE_2
EQU
1B
BYTE_1
EQU
1C
BYTE_2
EQU
1D
BYTE_3
EQU
1E
BYTE_4
EQU
1F
;
;DEFINE FLAG2 REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y| --> Command Ready.
;
| | | | | |Y| | --> Command in process.
;
| | | | |Y| | | --> Most Significant bit of time stamp.
;
| | | |Y| | | | --> HOLD is active
;
| | |Y| | | | | --> Four bytes have been recvd ok
;
| |Y| | | | | | --> Value of last IR bit received.
;
|Y| | | | | | | --> A Valid hold received < 1/4 sec ago.
;
Y| | | | | | | | -->
; Y = DEFINED AS SHOWN (0/1)
;
HOLD_RCVD
EQU 6
LAST_IR_STATE
EQU 5
KEY_READY
EQU 4
HOLD
EQU 3
STAMP_MSB
EQU 2
CMD_PEND
EQU 1 ; A channel command is pending.
CMD_RDY
EQU 0 ; A channel command is ready.
;
;DEFINE FLAG3 REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y| --> Quarter second flag.
;
| | | | | |Y| | --> Eighth second flag.
;
| | | | |Y| | | --> Two second flag.
;
| | | |Y| | | | -->
;
| | |Y| | | | | -->
;
| |Y| | | | | | -->
;
|Y| | | | | | | -->
;
Y| | | | | | | | -->
; Y = DEFINED AS SHOWN (0/1)
;
;
_4TH_SEC
EQU 0
EIGTH_SEC
EQU 1
TWO_SEC
EQU 2
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Constant definitions."
;************************************************************************
; Gap length IR decoding time constants. Values were derived from
; successive readings made with MEASURE.ASM

1997 Microchip Technology Inc.

AN657
0000001A
00000027
00000038
00000048
0000001F
0000000E

0400
0400
0401
0402
0403
0404

0C83
01C1
0021
0004
03EB

0405 0A08
0406 0559
0407 0800
0408
0408
0409
040A
040B
040C
040D
040E
040F
0410
0411
0412

020B
0E0F
0F02
0643
0539
020B
0E1F
0F19
0643
0519
0800

0413
0413 0213
0414 003A

00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159

;
HOLD_MIN
EQU 1a
; Changed from 1e to minimize intermittency.
HOLD_MAX
EQU 27
; Changed from 23 to minimize intermittency.
HEAD_MIN
EQU 38
HEAD_MAX
EQU 48
ONE_MAX
EQU 1f
ZERO_MAX
EQU 0e
;
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Timer Routines."
;************************************************************************
; Timer servicing routine
;
Called every 8 milliseconds this clears the
;
watch dog, reloads the real time clock counter
;
and keeps track of relative time.
;
SvcTimer
movlw
MSEC8
;TMR0 = 8 milliseconds.
addwf
TMR0,W
; Add overflow amount.
movwf
TMR0
;
/
clrwdt
incfsz
TIMER,F
; Increment the timer, Skip to two sec
; set up if it rolls over.
goto
CheckMatch
; Go to other possible set ups.
bsf
FLAG3,TWO_SEC
; Set the 2 second flag.
;
retlw
0
; sync serviced.
CheckMatch
; 1/8 and 1/4 sec flags are staggered
; for more eff use of processor time.
movf
TIMER,W
; Bring in the timer.
andlw
b'00001111'
; Check lower bits.
xorlw
d'2'
; 1/8sec chores called when lo nibble=2.
btfsc
STATUS,Z
; Was the low nibble not 2?
bsf
FLAG3,EIGTH_SEC
; No! it was 2, Set the 1/8 sec flag.
movf
TIMER,W
; Bring in the timer.
andlw
b'00011111'
; Check five lower bits.
xorlw
0x19
; 1/4 second chores called every 0x19.
btfsc
STATUS,Z
; Was the low five bits not 0x19?
bsf
FLAG3,_4TH_SEC
; No! it was 0x19, Set the 1/4sec flag.
retlw
0
; matches checked, return.
;
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "6121 type IR remote control reader."
; ***********************************************************************
; The following reads the IR transmitter.
; When the IR transmitter is being read,
; This routine takes control of the clocks
; and suspends all other functions.
;
; ***********************************************************************
; IR Receiver routine
;
;
;-----------------------------------------------------------------------; ReadAddr
;
This routine places the first two bytes received in temporary
;
locations. Normally this routine would be configured to detect
;
weather or not the received command was ment for this equipment
;-----------------------------------------------------------------------ReadAddr
movf
IR_BYTE13,W
; bring in the first complete byte read
movwf
C_BYTE_1
; store it in the contingent first byte

1997 Microchip Technology Inc.

DS00657A-page 23

AN657
0415 0214
0416 003B
0417 0800

0418
0418
0419
041A
041B
041C
041D
041E
041F
0420
0421

021A
003C
021B
003D
0213
003E
0214
003F
0598
0A48

0422
0422 04B8

0423 0211
0424 0081
0425 0031
0426
0427
0428
0429

0C83
0091
0603
0031

042A
042A 0678
042B 0A40
042C 094B
042D 01E2
042E 0800
042F
0430
0431
0432

0C1F
0091
0603
0A5E

0433 0C0E
0434 0091

00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225

DS00657A-page 24

movf
movwf
retlw

IR_BYTE24,W
C_BYTE_2
0

; bring in the second complete byte read


; store it in the contingent second byte
; command.

;
;-----------------------------------------------------------------------; ReadCommand
;
This routine places the third and fourth bytes in memory locations
;
so they can be displayed. The first two bytes are transferred from
;
their trmporary locations to locations where they too can be
;
displayed. Normally this routine would be configured to decode
;
the appropriate action from the received number. the third and fourth
;
bytes are always complements of each other in this format. Typically
;
a complementary check of these two bytes is done at this point in the IR
;
reception
;-----------------------------------------------------------------------ReadCommand
movf
C_BYTE_1,W
; bring in the first complete byte read
movwf
BYTE_1
; store it to be dispd as actual first byte
movf
C_BYTE_2,W
; bring in the first complete byte read
movwf
BYTE_2
; store it to be dispd as actual 2nd byte
movf
IR_BYTE13,W
; bring in the third complete byte read
movwf
BYTE_3
; store it to be displayed as the 3rd byte
movf
IR_BYTE24,W
; bring in the fourth complete byte read
movwf
BYTE_4
; store it to be displayed as the 4th byte
bsf
FLAG2,KEY_READY ; Good set received
goto
LogHold
; Activate the hold for the first pass.
;
;
;-----------------------------------------------------------------------; ReadReceiver
; Second part of the IR receier. It takes the present count of the
; RTCC and subtracts the count recorded when the receiver output
; went high (READ_LH) to find the dark pulse duration. In that duration
; will be encoded the 1, 0, HOLD, or attention.
;-----------------------------------------------------------------------ReadReceiver
bcf
FLAG2,LAST_IR_STATE ; Record that the IR receiver output
; is now high
; Calc the length of the dark pulse,
; length of time receiver was high.
; (placed in READ_LH)
movf
READ_LH,W
; bring in the start measurement
subwf
TMR0,W
; subtract the final from the start
movwf
READ_LH
; gap or pulse length is now in
; READ_LH, must be checked
movlw
MSEC8
; Base number of TMR0 count.
subwf
READ_LH,W
; Subtract the base count of TMR0
btfsc
STATUS,C
; skip the store and toss value if neg
movwf
READ_LH
; value was positive, store
;
Ir6121MathDone
;
btfsc
FLAG2,HOLD
; is it now looking for holds?
goto
LookForHold
; look for HOLD
;
call
LookForAttentionGap ; look for an attention dark pulse
addwf
PCL,F
; skip if a 1 was retd, no atten pulse
retlw
0
; a 0 retd, ATTEN pulse found, return
;
movlw
ONE_MAX
; Test for the max length of one.
subwf
READ_LH,W
; If no carry gend, A valid 1 is found
btfsc
STATUS,C
; No carry means the reading is below max
goto
ResetIR
; IR no good, Above maximum is invalid.
;
movlw
ZERO_MAX
; Test for the max length of Zero.
subwf
READ_LH,W
; If no carry gend, A valid 0 is found.

1997 Microchip Technology Inc.

AN657

0435
0436
0437
0438

0772
0333
0672
0334

0439
043A
043B
043C
043D

0C01
01F2
0723
0800
07B2

043E 0A13
043F 0A18

0440
0440
0441
0442
0443
0444
0445
0446
0447
0448
0448
0449
044A

044B
044B
044C
044D
044E
044F
0450
0451
0452
0453
0454
0455
0455
0456
0457
0458
0459

0C1A
0091
0703
0800
0C27
0091
0603
0800
0578
05D8
0800

0C38
0091
0703
0A55
0C48
0091
0603
0A55
0072
0800
0CE0
0152
0743
0800
0801

00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291

; the carry now has the newly received bit


; shift the bit into the proper location
;
btfss
rrf
btfsc
rrf

IR_STATE,3
IR_BYTE13,F
IR_STATE,3
IR_BYTE24,F

; Every 8 states result in dest changes


; this bit is a part of IR byte 1 or 3
;
/
; this bit is a part of ir byte 2 or 4

movlw
addwf
btfss
retlw
btfss

1
IR_STATE,F
STATUS,DC
0
IR_STATE,5

goto
goto

ReadAddr
ReadCommand

;
;
;
;
;
;
;
;

;
Get ready to add one to the IR STATE
inc the state setting half carry bits
skip if digit carry generated
all done reading for now
check to determine if the 1st and 2nd
bytes or 3rd and 4th bytes are now ready
First and second byte ready.
Third and fourth byte ready.

;
;-----------------------------------------------------------------------; LookForHold
; Reads the length of the received dark pulse and determines if
; a valid HOLD pulse has been received
;-----------------------------------------------------------------------LookForHold
movlw
HOLD_MIN
; Find if between hold and one.
subwf
READ_LH,W
; IF no carry is gend, The read is between
btfss
STATUS,C
; HOLD and one and as such, invalid.
retlw
0
; Return to main routine from invalid read
movlw
HOLD_MAX
; Test for the max length of HOLD.
subwf
READ_LH,W
; If no carry is gend, get a valid hold
btfsc
STATUS,C
;
retlw
0
LogHold
bsf
FLAG2,HOLD
; valid HOLD received
bsf
FLAG2,HOLD_RCVD ; clear bit for the next hold condition
retlw
0
;
;-----------------------------------------------------------------------; LookForAttentionGap
; Reads the length of the received dark pulse and determines if
; a valid attention pulse has been received
;-----------------------------------------------------------------------LookForAttentionGap
; look for attention dark pulse
movlw
HEAD_MIN
; Find if between head and one.
subwf
READ_LH,W
; IF no carry is gend, reading is between
btfss
STATUS,C
; HOLD and HEAD and as such, invalid.
goto
CheckIRState
; continue, no attention gap.
movlw
HEAD_MAX
; Test for the max length of HEAD.
subwf
READ_LH,W
; If no carry is gend, get a valid head.
btfsc
STATUS,C
; A carry = a too long gap and is invalid.
goto
CheckIRState
; continue, no attention gap
clrf
IR_STATE
; Valid Attention dark pulse. This command
; starts the state machine looking for bits
retlw
0
; return to main routine, ATTEN found
CheckIRState
movlw
0e0
; load A mask to mask all counting states
andwf
IR_STATE,W
; compare with present state
btfss
STATUS,Z
retlw
0
; not a count state, return to main routine
retlw
01
; counting state, look for 1's and 0's
;
;-----------------------------------------------------------------------; RecordRTCCatLowToHiTransition
; First part of the IR receier. It records the time when the
; output of the IR receiver went from low to high. this creates the
; starting time for timing an IR pulse.
;------------------------------------------------------------------------

1997 Microchip Technology Inc.

DS00657A-page 25

AN657
045A
045A
045B
045C
045D

05B8
0201
0031
0800

045E
045E
045F
0460
0461
0462

0478
04D8
0072
0272
0800

0463
0463 0439
0464 0245
0465
0466
0467
0468
0469
046A
046B
046C
046D
046E

0E07
0643
0A7A
002C
00EC
064C
0A7A
0C1C
01CC
0024

046F 04A3
0470 04C3
0471 0380
0472 0900
0473 002E
0474 0200
0475 0900
0476 002F

0477 04A3
0478 05C3

0479 0800
047A
047A 0CBF
047B 002E

00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357

DS00657A-page 26

RecordRTCC_atLowToHiTransition
bsf
FLAG2,LAST_IR_STATE ; record that IR was last in dark pulse
movf
TMR0,W
; bring in the clock time
movwf
READ_LH
; record for when it goes back low
retlw
0
;-----------------------------------------------------------------------; ResetIR
; Resets the IR state machine to ready it for receiving IR messages.
;-----------------------------------------------------------------------ResetIR
bcf
FLAG2,HOLD
; not seen clear the hold
bcf
FLAG2,HOLD_RCVD
; clear the bit for next hold condition
clrf
IR_STATE
; preset IR_STATE to -1
comf
IR_STATE,F
; /
retlw
0
;
;************************************************************************
; The following subroutines are called by the executive
; every 1/8 second, every 1/4 second, and every two seconds
;
EigthSecChores
; all that needs doing every 1/8 sec
; can be placed in this subroutine
bcf
FLAG3,EIGTH_SEC
; clear the time out flag
;
comf
PORTA,W
; bring in the requested prescale value
; from the dial, reverse sense
andlw
7
; AND w/ highest possible prescale value
btfsc
STATUS,Z
; if zero, display hiphens
goto
DisplayHiphens
; was zero, display hiphens
movwf
TEMP
; place in temporary storage
decf
TEMP,F
; dec, dial settings 1 to 4 are valid
btfsc
TEMP,2
; if bit2 is set dial is 5 or higher
goto
DisplayHiphens
; dial is above 5, display hiphens
movlw
BYTE_1
addwf
TEMP,W
; add in dial setting (between 0 and 3)
movwf
FSR
; place in pointer register.
; NOTE! FSR bits5,6 = clear, File page1
;
bcf
STATUS,PA0
; get ready to call from page 1
bcf
STATUS,PA1
; /
;
swapf
INDF,W
; bring in IR measurement to be dispd
call
LookUpDigit
movwf
LEFT_DIGIT
; display more significant digit
;
movf
INDF,W
; bring in IR measurement to be dispd
call
LookUpDigit
movwf
RIGHT_DIGIT
; display less significant digit
;
if BeginIr6121==200
; return the bits to this page
bsf
STATUS,PA0
; page 1
bcf
STATUS,PA1
; /
endif
if BeginIr6121==400
bcf
STATUS,PA0
; page 2
bsf
STATUS,PA1
; /
endif
if BeginIr6121==600
bsf
STATUS,PA0
; page 3
bsf
STATUS,PA1
; /
endif
;
retlw
0
DisplayHiphens
movlw
HIPHEN
; dial not in range, display hiphens
movwf
LEFT_DIGIT
; / Hiphen in left digit

1997 Microchip Technology Inc.

AN657
047C 002F
047D 0800
047E
047E 0678
047F 06D8
0480 02A2
0481 095E
0482 04D8

0483 0419
0484 0800
0485
0485 0C0F
0486
0487
0488
0489
048A
048B

0005
0C3F
0006
0C00
0007
0498

048C 0459
048D 0800

048E
048E 0985
048F 0C05
0490 0002
0491 0078
0492 0079
0493
0494
0495
0496
0497

0CFF
003C
003D
003E
003F

0498 0C83
0499 0021
049A 095E
049B 05B8
049C 04A4
049D 04C4

049E

049E
049E 0665
049F 06B8

00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423

movwf
retlw

RIGHT_DIGIT
0

;
QuarterSecChores
btfsc
btfsc

FLAG2,HOLD
FLAG2,HOLD_RCVD

incf
call

PCL,F
ResetIR

bcf

FLAG2,HOLD_RCVD

bcf
retlw

FLAG3,_4TH_SEC
0

; / Hiphen in right digit

;
;
;
;
;

all that needs doing every 1/4 second


can be placed in this subroutine
Check for HOLD condition still valid
Check to see if a hold pulse has been
seen in the last 1/4 second

;
;
;
;

reset
ready
Clear
to be

the
for
the
set

IR state machine and get


next
hold received flag, it is
by IR controller

;
TwoSecChores
movlw
A_CONFIG
tris
movlw
tris
movlw
tris
bcf

PORTA
B_CONFIG
PORTB
C_CONFIG2
PORTC
FLAG2,KEY_READY

bcf
retlw

FLAG3,TWO_SEC
0

; clear the 1/4 second time out

;
;
;
;
;
;

things done every two seconds


setup for PORTA, in loop so
microcontroller will never forget
inputs are on bits 0,1, and 2.
PORTB inputs are not used,
PORTB outputs control digit drives

;
;
;
;
;

PORTC is all outputs


Routine that would interpret the key
will clear the flag that says it is
ready
clear the two second time out

;
;
;************************************************************************
;
Start HERE.
;************************************************************************
StartIr6121
call
TwoSecChores
; re-setup ports A, B, and C
;
movlw
OPTION_CODE
;SET UP PRESCALER, WDT on 18msec.
option
;Clock TMR0 every 64 instruc cycles.
;
clrf
FLAG2
; Clear out flag bank 2.
clrf
FLAG3
; Clear out flag bank 3.
;
movlw
0ff
; Display FF at start up
movwf
BYTE_1
; first byte = FF
movwf
BYTE_2
; second = FF
movwf
BYTE_3
; third = FF
movwf
BYTE_4
; fourth byte = FF
;
movlw
MSEC8
;TMR0 = 8 mSEC
movwf
TMR0
;
/
;
call
ResetIR
; get the IR ready to receive
bsf
FLAG2,LAST_IR_STATE ; preset the IR flag for a
; RecordRTCCatLowToHiTransition
bcf
FSR,5
; File page 1
bcf
FSR,6
; /
;
;************ Main loop Starts here. *************
IRMain
;
;
IRInnerLoop
btfsc
PORTA,IR
; ?IR rcvr not receiving an IR burst?
btfsc
FLAG2,LAST_IR_STATE ; was it receiving a burst last time?

1997 Microchip Technology Inc.

DS00657A-page 27

AN657
04A0 02A2
04A1 095A

04A2
04A3
04A4
04A5

0765
07B8
02A2
0922

04A6
04A7
04A8
04A9
04AA

0C83
0081
0603
0A9E
0900

04AB 04A3
04AC 04C3
04AD 0912

04AE 04A3
04AF 05C3

04B0
04B1
04B2
04B3
04B4

07C6
0778
0AB4
04E7

04B4 0639
04B5 0963

04B6 0619
04B7 097E

04B8 0659
04B9 0985

04BA 0A9E
0600
0600

00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00199
00200
00201
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010

DS00657A-page 28

incf
call

PCL,F
; Not either
RecordRTCC_atLowToHiTransition
; Record the TMR0 value when the lo to
; hi transition came from the receiver

btfss
btfss
incf
call

PORTA,IR
FLAG2,LAST_IR_STATE
PCL,f
ReadReceiver

;
;
;
;

?IR receiver receiving an IR burst?


was it not rcvg a burst last time?
Not either
read the new information

movlw
subwf
btfsc
goto
call

MSEC8
TMR0,W
STATUS,C
IRInnerLoop
SvcTimer

;
;
;
;
;

Check for overflow.


SEE IF TMR0 < MSEC8,
If TMR0 < MSEC8, Overflow.
No overflow, no carry, loop.
Keep time and reload time keeper.

bcf
bcf
call

STATUS,PA0
STATUS,PA1
UpdateDisplay

; get ready to call from page 1


; /
; rotate power to next display digit

;
if BeginIr6121==200
bsf
STATUS,PA0
bcf
STATUS,PA1
endif
if BeginIr6121==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginIr6121==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif

; return the bits to this page


; page 1
; /

; page 2
; /

; page 3
; /

;
btfss
btfss
goto
bcf
NotHold
;
btfsc
call

PORTB,RIGHT_OFF
FLAG2,HOLD
NotHold
PORTC,DP

;
;
;
;

Is display ready to display HOLD?


IS the hold active?
do not turn on lite for HOLD indicate
TURN on LED flag, show HOLD is active

FLAG3,EIGTH_SEC
EigthSecChores

; check for 1/8 second time out


; all that needs doing every 1/8 second
; can go in this subroutine

btfsc
call

FLAG3,_4TH_SEC
QuarterSecChores

; check for 1/4 second time out


; all that needs doing every 1/4sec
; can go in this subroutine

btfsc
call

FLAG3,TWO_SEC
TwoSecChores

; check for two second time out


; all that needs doing every two secs
; can go in this subroutine

goto

IRMain

;
org
600
BeginTeknika
include
"teknika.asm"
TITLE
"IR-Technica TV format Remote Control Detector V0.01"
SUBTITL
"Comments documentation and history"
;
;************************************************************************
; File Name :
TEKNIKA.ASM
;************************************************************************
;
Author:
William G. Grimm
;
Company:
Microchip Technology
;
Revision: V0.01
;
Date:
March 31, 1996

1997 Microchip Technology Inc.

AN657

0000000C

00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076

;
Assembler: MPASM version 1.21
;
;************************************************************************
;
Revision History:
;
;
;
V0.01
Original March 28, 1996
;
;
V0.02
repaired bug that kept HOLD from operating
;
March 31, 1996
;
;
V0.03
modified gpa and pulse length subtraction
;
March 31, 1996
;
;************************************************************************
;
OPTION_CODE
EQU
B'00000101'
;SET UP PRESCALER, WDT on 18msec.
;
Same as IR6121
;************************************************************************
;
;************************************************************************
; file memory location definitions
;************************************************************************
;
; full byte file memory locations
;
(those commented out are defined in IR6121 or IRMAIN)
;
;
TIMER
EQU
0b
; Bit5 = 1/4 second, Bit1 = 16 millisecs.
BUTTON
EQU
0c
; holds last value of last button pressed
;
;
RIGHT_DIGIT
EQU
0f
;
READ_LH
EQU
11
;
IR_STATE
EQU
12
;
IR_BYTE13
EQU
13
;
IR_BYTE24
EQU
14
;
;
FLAG2
EQU
18
;
FLAG3
EQU
19
;
;DEFINE FLAG2 REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y|
;
| | | | | |Y| |
;
| | | | |Y| | |
;
| | | |Y| | | |
;
| | |Y| | | | |
;
| |Y| | | | | |
;
|Y| | | | | | |
;
Y| | | | | | | |
; Y = DEFINED AS SHOWN (0/1)
;
(commented definitions are
;HOLD_RCVD
EQU 6
;LAST_IR_STATE EQU 5
;KEY_READY
EQU 4
;HOLD
EQU 3
;STAMP_MSB
EQU 2
;CMD_PEND
EQU 1
;CMD_RDY
EQU 0
;
;DEFINE FLAG3 REG FUNCTION:
;
BIT # 7|6|5|4|3|2|1|0|
;--------------|-|-|-|-|-|-|-|
;
| | | | | | |Y|
;
| | | | | |Y| |
;
| | | | |Y| | |

1997 Microchip Technology Inc.

;
;
;
;
;

defined in irmain
Low to high reading is stored here.
Which bit is coming in.
First byte for collecting inputs.
Second byte for collecting inputs.

; flag bank 2
; flag bank 3

-->
-->
-->
-->
-->
-->
-->
-->

Command Ready.
Command in process.
Most Significant bit of time stamp.
HOLD is active
4 bytes have been rcvd successfully
Value of last IR bit received.
A Valid hold received < 1/4 sec ago.

defined elsewhere)

; A channel command is pending.


; A channel command is ready.

--> Quarter second flag.


--> Eighth second flag.
--> Two second flag.

DS00657A-page 29

AN657

00000003
00000004

00000014
000000EB
00000000
00000001
00000002
00000003
00000008
00000009
0000000A
0000000B
00000010
00000011
0000001B
0000001A
00000013
00000012

0600
0600
0601
0602
0603
0604

0C83
01C1
0021
0004
03EB

0605 0A08
0606 0559

00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142

DS00657A-page 30

;
| | | |Y| | | | --> A channel up has been received
;
| | |Y| | | | | --> A Channel Down has been received
;
| |Y| | | | | | -->
;
|Y| | | | | | | -->
;
Y| | | | | | | | -->
; Y = DEFINED AS SHOWN (0/1)
;
(commented definitions are defined elsewhere)
;
;_4TH_SEC
EQU 0
;EIGTH_SEC
EQU 1
;TWO_SEC
EQU 2
ACTIVE_UP
EQU 3
ACTIVE_DOWN
EQU 4
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Constant definitions."
;************************************************************************
; Gap length IR decoding time constants. Values were derived from
; successive readings made with MEASURE.ASM
; (commented defines are characterisitic of all 6121 remotes
;
and are defined in IR6121)
;HOLD_MIN
EQU 1a
; Changed from 1e to minimize intermittency.
;HOLD_MAX
EQU 27
; Changed from 23 to minimize intermittency.
;HEAD_MIN
EQU 38
;HEAD_MAX
EQU 48
;ONE_MAX
EQU 1f
;ZERO_MAX
EQU 0e
;
;
; Definitions characteristic of Teknika TV remote controls
ID_BYTE_1
EQU 14
; Teknika signature byte 1
ID_BYTE_2
EQU 0eb
; Teknika signature byte 2
;
TEK_ZERO
EQU 000
; #0
TEK_ONE
EQU 001
; #1
TEK_TWO
EQU 002
; #2
TEK_THREE
EQU 003
; #3
TEK_FOUR
EQU 008
; #4
TEK_FIVE
EQU 009
; #5
TEK_SIX
EQU 00a
; #6
TEK_SEVEN
EQU 00b
; #7
TEK_EIGHT
EQU 010
; #8
TEK_NINE
EQU 011
; #9
TEK_ON_OFF
EQU 01b
; ON/OFF
TEK_MUTE
EQU 01a
; Mute button
TEK_CHUP
EQU 013
; CHUP Clockwise
TEK_CHDN
EQU 012
; CHDN Counter Clockwise
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Timer Routines."
;************************************************************************
; Timer servicing routine
;
Called every 8 milliseconds, this clears the
;
watch dog, reloads TMR0
;
and keeps track of relative time.
;
TekServiceTimer
movlw
MSEC8
;TMR0 = 8 milliseconds.
addwf
TMR0,W
; Add overflow amount.
movwf
TMR0
;
/
clrwdt
incfsz
TIMER,F
; Increment the timer, Skip to two second
; set up if it rolls over.
goto
TekCheckMatch
; Go to other possible setups.
bsf
FLAG3,TWO_SEC
; Set the two second flag.
;

1997 Microchip Technology Inc.

AN657
0607 0800
0608
0608
0609
060A
060B
060C
060D
060E
060F
0610
0611
0612

020B
0E0F
0F02
0643
0539
020B
0E1F
0F19
0643
0519
0800

0613
0613
0614
0615
0616
0617
0618
0619
061A
061B

0C14
0193
0743
0A82
0CEB
0194
0743
0A82
0800

061C
061C
061D
061E
061F

0253
0194
0743
0A82

0620
0621
0622
0623
0624
0625

0C13
0193
0643
0579
0643
0A39

0626 0C12
0627 0193
0628 0643

00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208

retlw
0
TekCheckMatch
movf
andlw
xorlw
btfsc
bsf
movf
andlw
xorlw
btfsc
bsf
retlw

TIMER,W
b'00001111'
d'2'
STATUS,Z
FLAG3,EIGTH_SEC
TIMER,W
b'00011111'
0x19
STATUS,Z
FLAG3,_4TH_SEC
0

;
;
;
;
;
;
;
;
;
;
;
;
;
;

sync serviced.
1/8 and 1/4 second flags are staggered
make more efficient use of processor time
Bring in the timer.
Check lower bits.
1/8sec chores called when low nibble=2.
Was the low nibble not 2?
No! it was 2, Set the 1/8 sec flag.
Bring in the timer.
Check five lower bits.
1/4 second chores called every 0x19.
Was the low five bits not 0x19?
No! it was 0x19, Set the 1/4 sec flag.
matches checked, return.

;
;
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "6121 type IR remote control reader."
; *******************************************
; The following reads the IR transmitter.
; When the IR transmitter is being read,
; this routine takes control of the clocks
; and suspends all other functions.
;
; ********************************************
; IR Receiver routine
;
;
;-----------------------------------------------------------------------; TekRdAddr
;
This routine determines whether a Teknika remote control is
;
sending the command.
;-----------------------------------------------------------------------TekRdAddr
movlw
ID_BYTE_1
; bring in what would be the first byte
xorwf
IR_BYTE13,W
; compare with the byte that came in first
btfss
STATUS,Z
; if the same, the zero bit is set
goto
TekIRReset
; wrong ID, reset the IR state
movlw
ID_BYTE_2
; bring in what would be the second byte
xorwf
IR_BYTE24,W
; compare with the byte that came in 2nd
btfss
STATUS,Z
; if the same, the zero bit is set
goto
TekIRReset
; wrong ID, reset the IR state
retlw
0
; Success! A Teknika remote sent the command
;
;-----------------------------------------------------------------------; RD_COMMAND
;
This routine determines what kind of command was sent, and places
;
the result in BUTTON or one of the channel up or down flags.
;-----------------------------------------------------------------------TekRdCommand
comf
IR_BYTE13,W
; Byte3 must be the complement of Byte4
xorwf
IR_BYTE24,W
; For a valid command.
btfss
STATUS,Z
; If the same, skip to continue.
goto
TekIRReset
; not complements, not valid.
;
movlw
TEK_CHUP
; check for a channel up command
xorwf
IR_BYTE13,W
; compare with byte 3
btfsc
STATUS,Z
; skip if no match
bsf
FLAG3,ACTIVE_UP
; active channel up
btfsc
STATUS,Z
; skip again if no active channel up
goto
TekLogCommand
;
movlw
TEK_CHDN
; check for a channel down command
xorwf
IR_BYTE13,W
; compare with byte 3
btfsc
STATUS,Z
; skip if no match

1997 Microchip Technology Inc.

DS00657A-page 31

AN657
0629 0599
062A 0643
062B 0A39
062C 0C0A
062D 0034
062E
062E
062F
0630
0631
0632

00F4
0254
0643
0A39
0214

0633 093B
0634
0634 0193
0635
0636
0637
0637
0638
0639
0639
063A
063B
063B
063C
063D
063E
063F
0640
0641
0642
0643
0644
0645

0743
0A2E
0214
002C
0598
0A6C

01E2
0800
0801
0802
0803
0808
0809
080A
080B
0810
0811

0646
0646 04B8

0647 0211
0648 0081
0649 0031
064A
064B
064C
064D

0C83
0091
0603
0031

064E
064E 0678

00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274

DS00657A-page 32

bsf
btfsc
goto

FLAG3,ACTIVE_DOWN
STATUS,Z
TekLogCommand

; active channel down


; skip again if no active channel down

movlw
movwf

d'10'
IR_BYTE24

; Look for ten possible buttons.


; IR_BYTE24 is converted for use as
; a counter.

IR_BYTE24,F
IR_BYTE24,W
STATUS,Z
TekLogCommand
IR_BYTE24,W

;
;
;
;
;
;
;
;
;
;
;
;

GuessLoop
decf
comf
btfsc
goto
movf
call
CheckGuess
xorwf

TekTable
IR_BYTE13,W

decrement to next button to look for


See if it rolled over to FF
If rollover, this not a valid command.
not a listed button return.
Bring in the counter, which is a
guess as to what the button is.
NO! Get the code for guessed value
for dog biscuit
look for a match with the guess and
actual value which is in IR_BYTE13.
If it matchs skip and stop looping.
No match. Guess again.

btfss
STATUS,Z
goto
GuessLoop
TekLogButton
movf
IR_BYTE24,W
; bring in the count
movwf
BUTTON
; it has the new button number
TekLogCommand
bsf
FLAG2,KEY_READY
; Good set received
goto
TekLogHold
; Activate the hold for the first pass.
;
TekTable
addwf
PCL,F
; Computed jump for look-up table.
retlw
TEK_ZERO
; #0
retlw
TEK_ONE
; #1
retlw
TEK_TWO
; #2
retlw
TEK_THREE
; #3
retlw
TEK_FOUR
; #4
retlw
TEK_FIVE
; #5
retlw
TEK_SIX
; #6
retlw
TEK_SEVEN
; #7
retlw
TEK_EIGHT
; #8
retlw
TEK_NINE
; #9
;
;
;-----------------------------------------------------------------------; TekRdRcvr
; Second part of the IR receiver. It takes the present count of
; TMR0 and subtracts the count recorded when the receiver output
; went high (READ_LH) to find the dark pulse duration. In that duration
; will be encoded the 1, 0, HOLD, or attention.
;-----------------------------------------------------------------------TekRdRcvr
bcf
FLAG2,LAST_IR_STATE ; Record that the IR rcvr output
; is now high
; Calculate length of the dark pulse,
; length of time receiver was high.
; (placed in READ_LH)
movf
READ_LH,W
; bring in the start measurement
subwf
TMR0,W
; subtract the final from the start
movwf
READ_LH
; gap or pulse length is now in
; READ_LH, must be checked
movlw
MSEC8
; Base number of TMR0 count.
subwf
READ_LH,W
; Subtract the base count of TMR0
btfsc
STATUS,C
; skip the store and toss value if neg
movwf
READ_LH
; value was positive, store
;
TekMathDone
;
btfsc
FLAG2,HOLD
; is it now looking for holds?

1997 Microchip Technology Inc.

AN657
064F 0A64
0650 096F
0651 01E2
0652 0800
0653
0654
0655
0656

0C1F
0091
0603
0A82

0657 0C0E
0658 0091

0659
065A
065B
065C

0772
0333
0672
0334

065D
065E
065F
0660
0661

0C01
01F2
0723
0800
07B2

0662 0A13
0663 0A1C

0664
0664
0665
0666
0667
0668
0669
066A
066B
066C
066C
066D
066E

066F
066F
0670
0671
0672
0673
0674
0675
0676
0677

0C1A
0091
0703
0800
0C27
0091
0603
0800
0578
05D8
0800

0C38
0091
0703
0A79
0C48
0091
0603
0A79
0072

0678 0800

00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340

goto

TekLookHold

; look for HOLD

call
addwf
retlw

TekLookAtten
PCL,F
0

; look for an attention dark pulse


; skip if 1 was retd, no atten pulse
; a 0 retd, ATTEN pulse found, return

movlw
subwf
btfsc
goto

ONE_MAX
READ_LH,W
STATUS,C
TekIRReset

;
;
;
;

Test for the max length of one.


If no carry is gend, get a valid one
No carry means the read is below max
IR no good, Above maximum is invalid.

movlw
subwf

ZERO_MAX
READ_LH,W

;
;
;
;

Test for the max length of Zero.


If no carry is gend, get a valid 0.
the carry now has the newly rcvd bit
shift the bit into the proper location

btfss
rrf
btfsc
rrf

IR_STATE,3
IR_BYTE13,F
IR_STATE,3
IR_BYTE24,F

; Every 8 states gives dest changes


; this bit is a part of IR byte 1 or 3
;
/
; this bit is a part of ir byte 2 or 4

movlw
addwf
btfss
retlw
btfss

1
IR_STATE,F
STATUS,DC
0
IR_STATE,5

goto
goto

TekRdAddr
TekRdCommand

;
;
;
;
;
;
;
;

;
Get ready to add one to the IR STATE
inc the state setting half carry bits
skip if digit carry generated
all done reading for now
check to determine if the 1st and 2nd
bytes or 3rd and 4th bytes now ready
First and second byte ready.
Third and fourth byte ready.

;
;-----------------------------------------------------------------------; LOOK_HOLD
; Reads the length of the received dark pulse and determines if
; a valid HOLD pulse has been received
;-----------------------------------------------------------------------TekLookHold
movlw
HOLD_MIN
; Find if between hold and one.
subwf
READ_LH,W
; IF no carry is gend, The read is between
btfss
STATUS,C
; HOLD and one and as such, invalid.
retlw
0
; Ret to main routine from invalid read.
movlw
HOLD_MAX
; Test for the max length of HOLD.
subwf
READ_LH,W
; If no carry is gend, get a valid hold.
btfsc
STATUS,C
;
retlw
0
TekLogHold
bsf
FLAG2,HOLD
; valid HOLD received
bsf
FLAG2,HOLD_RCVD ; clear bit for the next hold condition
retlw
0
;
;-----------------------------------------------------------------------; LOOK_ATTEN
; Reads the length of the received dark pulse and determines if
; a valid attention pulse has been received
;-----------------------------------------------------------------------TekLookAtten
; look for attention dark pulse
movlw
HEAD_MIN
; Find if between head and one.
subwf
READ_LH,W
; IF no carry is gend, Reading between
btfss
STATUS,C
; HOLD and HEAD and as such, invalid.
goto
TekCheckState
; continue, no attention gap.
movlw
HEAD_MAX
; Test for the max length of HEAD.
subwf
READ_LH,W
; If no carry is gend, get a valid head
btfsc
STATUS,C
; A carry = a too long gap = invalid.
goto
TekCheckState
; continue, no attention gap
clrf
IR_STATE
; Valid Atten dark pulse. Command starts
; the state machine looking for bits.
retlw
0
; return to main routine, ATTEN found

1997 Microchip Technology Inc.

DS00657A-page 33

AN657
0679
0679
067A
067B
067C
067D

0CE0
0152
0743
0800
0801

067E
067E
067F
0680
0681

05B8
0201
0031
0800

0682
0682
0683
0684
0685
0686
0687
0688

0478
04D8
0479
0499
0072
0272
0800

0689
0689
068A
068B
068C
068D
068E
068E
068F
0690
0691
0692
0693
0694
0694
0695
0696
0697
0698
0699
069A

0679
0A8E
0699
0A94
0800
02AC
0C0A
008C
0603
006C
0800
00EC
024C
0743
0800
0C09
002C
0800

069B
069B 0439
069C 0800

00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406

DS00657A-page 34

TekCheckState
movlw
0e0
; load A mask to mask all count states
andwf
IR_STATE,W
; compare with present state
btfss
STATUS,Z
retlw
0
; not a count state, ret to main routine
retlw
01
; counting state, look for 1's and 0's
;
;-----------------------------------------------------------------------; RECORD_LH
; First part of the IR receiver. It records the time when the
; output of the IR receiver went from low to high. this creates the
; starting time for timing an IR pulse.
;-----------------------------------------------------------------------TekRecordLH
bsf
FLAG2,LAST_IR_STATE ; record that IR was last in dark pulse
movf
TMR0,W
; bring in the clock time
movwf
READ_LH
; record for when it goes back low
retlw
0
;-----------------------------------------------------------------------; TekIRReset
; Resets the IR state machine to ready it for receiving IR messages.
;-----------------------------------------------------------------------TekIRReset
bcf
FLAG2,HOLD
; not seen clear the hold
bcf
FLAG2,HOLD_RCVD
; clear bit for the next hold condition
bcf
FLAG3,ACTIVE_UP
; clear channel up if present
bcf
FLAG3,ACTIVE_DOWN
; clear channel down if present
clrf
IR_STATE
; preset IR_STATE to -1
comf
IR_STATE,F
; /
retlw
0
;
;-----------------------------------------------------------------------; TekSvcHold
; Uses the HOLD to increment or decrement the BUTTON number.
;-----------------------------------------------------------------------TekSvcHold
btfsc
FLAG3,ACTIVE_UP
; is Channel up now present?
goto
IncButton
; Yes, increment button
btfsc
FLAG3,ACTIVE_DOWN
; is Channel Down now present?
goto
DecButton
; Yes, Decrement button
retlw
0
; neither now active
IncButton
incf
BUTTON,F
; increment button
movlw
d'10'
;
subwf
BUTTON,W
; Compare with 10
btfsc
STATUS,C
; is BUTTON < 10?
clrf
BUTTON
; No recycle
retlw
0
DecButton
decf
BUTTON,F
; Decrement button
comf
BUTTON,W
; Roll to FF?
btfss
STATUS,Z
; ship if roll over
retlw
0
movlw
d'9'
; recycle on zero
movwf
BUTTON
; /
retlw
0
;
;************************************************************************
; The following subroutines are called by the executive
; every 1/8 second, every 1/4 second, and every two seconds
;
TekEigthSec
; all that needs doing every 1/8 sec
; can be placed in this subroutine
bcf
FLAG3,EIGTH_SEC
; clear the time out flag
;
retlw
0

1997 Microchip Technology Inc.

AN657
069D
069D 0678
069E 06D8
069F 02A2
06A0 0982
06A1 04D8
06A2 0678
06A3 0989
06A4 0419
06A5 0800
06A6
06A6 0C0F
06A7
06A8
06A9
06AA
06AB
06AC

0005
0C3F
0006
0C00
0007
0498

06AD 0459
06AE 0800

06AF
06AF 09A6
06B0 0C05
06B1 0002
06B2 0078
06B3 0079
06B4 006C

06B5 0C83
06B6 0021
06B7 0982
06B8 05B8
06B9 04A4
06BA 04C4

06BB

06BB
06BB
06BC
06BD
06BE

0665
06B8
02A2
097E

00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472

;
TekQuarterSec
btfsc
btfsc

FLAG2,HOLD
FLAG2,HOLD_RCVD

incf
call

PCL,F
TekIRReset

bcf

FLAG2,HOLD_RCVD

btfsc
call

FLAG2,HOLD
TekSvcHold

bcf
retlw

FLAG3,_4TH_SEC
0

;
;
;
;
;

all that needs doing every 1/4 second


can be placed in this subroutine
Check for HOLD condition still valid
Check to see if a hold pulse has been
seen in the last 1/4 second

;
;
;
;
;
;

reset the IR state machine and get


ready for next
Clear the hold received flag, it is
to be set by IR controller
check for active hold
service the hold function

;
TekTwoSec
movlw

A_CONFIG

tris
movlw
tris
movlw
tris
bcf

PORTA
B_CONFIG
PORTB
C_CONFIG2
PORTC
FLAG2,KEY_READY

bcf
retlw

FLAG3,TWO_SEC
0

; clear the 1/4 second time-out

;
;
;
;
;
;

things done every two seconds


setup for PORTA in loop, so
microcontroller will never forget
inputs are on bits 0,1, and 2.
PORTB inputs are not used,
PORTB outputs control digit drives

;
;
;
;
;

PORTC is all outputs


Routine that would interpret the key
will clear the flag that says it is
ready
clear the two second time-out

;
;
;************************************************************************
;
Start HERE.
;************************************************************************
StartTek
call
TekTwoSec
; re-setup ports A and B
;
movlw
OPTION_CODE
;SET UP PRESCALER, WDT on 18msec.
option
;Clock TMR0 every 64 inst cycles.
;
clrf
FLAG2
; Clear out flag bank 2.
clrf
FLAG3
; Clear out flag bank 3.
clrf
BUTTON
; Displays Zero on reset
;
;
movlw
MSEC8
;TMR0 = 8 mSEC
movwf
TMR0
;
/
;
call
TekIRReset
; get the IR ready to receive
bsf
FLAG2,LAST_IR_STATE ; preset the IR flag for a RECORD_LH
;
bcf
FSR,5
; File page 1
bcf
FSR,6
; /
;
;************ Main loop Starts here. *************
TekMain
;
;
TekInnerLoop
btfsc
PORTA,IR
; ?IR receiver not rcvg an IR burst?
btfsc
FLAG2,LAST_IR_STATE ; was it receiving a burst last time?
incf
PCL,F
; Not either
call
TekRecordLH
; Record the TMR0 value when the lo to
; hi transition came from the receiver
;

1997 Microchip Technology Inc.

DS00657A-page 35

AN657
06BF
06C0
06C1
06C2

0765
07B8
02A2
0946

06C3
06C4
06C5
06C6
06C7

0C83
0081
0603
0ABB
0900

06C8 04A3
06C9 04C3
06CA 020C
06CB 0900
06CC 0027

06CD 05A3
06CE 05C3

06CF 0678
06D0 04E7
06D1 05E6
06D2 04C6
06D3 0639
06D4 099B

06D5 0619
06D6 099D

06D7 0659
06D8 09A6

06D9 0ABB
0100

0100
0100
0101
0102
0103
0104

0C1E
0007
0000
0747
0B08

00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216

DS00657A-page 36

btfss
btfss
incf
call

PORTA,IR
FLAG2,LAST_IR_STATE
PCL,F
TekRdRcvr

;
;
;
;

?IR receiver receiving an IR burst?


was it not rcvg a burst last time?
Not either
read the new information

movlw
subwf
btfsc
goto
call

MSEC8
TMR0,W
STATUS,C
TekInnerLoop
TekServiceTimer

;
;
;
;
;

Check for overflow.


SEE IF TMR0 < MSEC8,
If TMR0 < MSEC8, Overflow.
No overflow, no carry, loop.
Keep time and reload time keeper.

bcf
bcf

STATUS,PA0
STATUS,PA1

; get ready to call from page 1


; /

movf
call
movwf

BUTTON,W
LookUpDigit
PORTC

; get the IR measurement to be dispd

; display on Right digit

;
if BeginTeknika==200
bsf
STATUS,PA0
bcf
STATUS,PA1
endif
if BeginTeknika==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginTeknika==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif

; return the bits to this page


; page 1
; /

; page 2
; /

; page 3
; /

;
btfsc
bcf

FLAG2,HOLD
PORTC,DP

; IS the hold active?


; TURN on LED flag to show HOLD active

bsf
bcf

PORTB,LEFT_OFF
PORTB,RIGHT_OFF

; turn off the left digit


; turn on the right digit

btfsc
call

FLAG3,EIGTH_SEC
TekEigthSec

; check for 1/8 second time-out


; all that needs doing every 1/8 sec
; can go in this subroutine

btfsc
call

FLAG3,_4TH_SEC
TekQuarterSec

; check for 1/4 second time-out


; all that needs doing every 1/4 sec
; can go in this subroutine

btfsc
call

FLAG3,TWO_SEC
TekTwoSec

; check for two second time-out


; all that needs doing every two sec
; can go in this subroutine

goto

TekMain

;
org
100
;
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SUBTITL "Start"
;
;************************************************************************
;
Start HERE.
;************************************************************************
StartAll
movlw
C_CONFIG1
; configuration to read from PORTC
tris
PORTC
; configure PORTC to read the bits
nop
; allow time for the inputs to settle
btfss
PORTC,SW2
; check to see if jumper is in #2
goto
TekOr6121
; Indicates IR6121 or TEK is requested
if BeginMeasure==200

1997 Microchip Technology Inc.

AN657
0105 05A3
0106 04C3

0107 0A61
0108
0108 0727
0109 0B0D

010A 04A3
010B 05C3

010C 0A8E
010D

010D 05A3
010E 05C3
010F 0AAF

07FF
07FF 0B00

00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264

bsf
STATUS,PA0
bcf
STATUS,PA1
endif
if BeginMeasure==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginMeasure==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif
goto
StartMeasure
TekOr6121
btfss
PORTC,SW1
goto
Teknika
if BeginIr6121==200
bsf
STATUS,PA0
bcf
STATUS,PA1
endif
if BeginIr6121==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginIr6121==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif
goto
StartIr6121
Teknika
if BeginTeknika==200
bsf
STATUS,PA0
bcf
STATUS,PA1
endif
if BeginTeknika==400
bcf
STATUS,PA0
bsf
STATUS,PA1
endif
if BeginTeknika==600
bsf
STATUS,PA0
bsf
STATUS,PA1
endif
goto
StartTek
;
; START Vector
org
0x07ff
goto
StartAll
;
END

1997 Microchip Technology Inc.

; page 1
; /

; page 2
; /

; page 3
; /
; Start the IR measurement routine
; check SW1 to determine if Tek or 6121
; jumper in, Teknika
; page 1
; /

; page 2
; /

; page 3
; /
; Start the 6121 IR format decoder

; page 1
; /

; page 2
; /

; page 3
; /
; Start the Technika Remote decoder

; start vector

DS00657A-page 37

AN657
MEMORY USAGE MAP ('X' = Used,

'-' = Unused)

0000 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX X--------------0100 : XXXXXXXXXXXXXXXX ---------------- ---------------0200 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0240 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0280 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXX-0400 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0440 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0480 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0600 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0640 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
0680 : XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
06C0 : XXXXXXXXXXXXXXXX XXXXXXXXXX------ ---------------07C0 : ---------------- ---------------- ---------------All other memory blocks unused.
Program Memory Words Used:
629
Program Memory Words Free: 1419
Errors
:
0
Warnings :
0 reported,
0 suppressed
Messages :
0 reported,
0 suppressed

DS00657A-page 38

------------------------------XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
---------------XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXX----XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
------------------------------X

1997 Microchip Technology Inc.

Note the following details of the code protection feature on PICmicro MCUs.

The PICmicro family meets the specifications contained in the Microchip Data Sheet.
Microchip believes that its family of PICmicro microcontrollers is one of the most secure products of its kind on the market today,
when used in the intended manner and under normal conditions.
There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our knowledge, require using the PICmicro microcontroller in a manner outside the operating specifications contained in the data sheet.
The person doing so may be engaged in theft of intellectual property.
Microchip is willing to work with the customer who is concerned about the integrity of their code.
Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as unbreakable.
Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of
our product.

If you have any further questions about this matter, please contact the local sales office nearest to you.

Information contained in this publication regarding device


applications and the like is intended through suggestion only
and may be superseded by updates. It is your responsibility to
ensure that your application meets with your specifications.
No representation or warranty is given and no liability is
assumed by Microchip Technology Incorporated with respect
to the accuracy or use of such information, or infringement of
patents or other intellectual property rights arising from such
use or otherwise. Use of Microchips products as critical components in life support systems is not authorized except with
express written approval by Microchip. No licenses are conveyed, implicitly or otherwise, under any intellectual property
rights.

Trademarks
The Microchip name and logo, the Microchip logo, FilterLab,
KEELOQ, microID, MPLAB, PIC, PICmicro, PICMASTER,
PICSTART, PRO MATE, SEEVAL and The Embedded Control
Solutions Company are registered trademarks of Microchip Technology Incorporated in the U.S.A. and other countries.
dsPIC, ECONOMONITOR, FanSense, FlexROM, fuzzyLAB,
In-Circuit Serial Programming, ICSP, ICEPIC, microPort,
Migratable Memory, MPASM, MPLIB, MPLINK, MPSIM,
MXDEV, PICC, PICDEM, PICDEM.net, rfPIC, Select Mode
and Total Endurance are trademarks of Microchip Technology
Incorporated in the U.S.A.
Serialized Quick Turn Programming (SQTP) is a service mark
of Microchip Technology Incorporated in the U.S.A.
All other trademarks mentioned herein are property of their
respective companies.
2002, Microchip Technology Incorporated, Printed in the
U.S.A., All Rights Reserved.
Printed on recycled paper.

Microchip received QS-9000 quality system


certification for its worldwide headquarters,
design and wafer fabrication facilities in
Chandler and Tempe, Arizona in July 1999. The
Companys quality system processes and
procedures are QS-9000 compliant for its
PICmicro 8-bit MCUs, KEELOQ code hopping
devices, Serial EEPROMs and microperipheral
products. In addition, Microchips quality
system for the design and manufacture of
development systems is ISO 9001 certified.

2002 Microchip Technology Inc.

M
WORLDWIDE SALES AND SERVICE
AMERICAS

ASIA/PACIFIC

Japan

Corporate Office

Australia

2355 West Chandler Blvd.


Chandler, AZ 85224-6199
Tel: 480-792-7200 Fax: 480-792-7277
Technical Support: 480-792-7627
Web Address: http://www.microchip.com

Microchip Technology Australia Pty Ltd


Suite 22, 41 Rawson Street
Epping 2121, NSW
Australia
Tel: 61-2-9868-6733 Fax: 61-2-9868-6755

Microchip Technology Japan K.K.


Benex S-1 6F
3-18-20, Shinyokohama
Kohoku-Ku, Yokohama-shi
Kanagawa, 222-0033, Japan
Tel: 81-45-471- 6166 Fax: 81-45-471-6122

Rocky Mountain

China - Beijing

2355 West Chandler Blvd.


Chandler, AZ 85224-6199
Tel: 480-792-7966 Fax: 480-792-7456

Microchip Technology Consulting (Shanghai)


Co., Ltd., Beijing Liaison Office
Unit 915
Bei Hai Wan Tai Bldg.
No. 6 Chaoyangmen Beidajie
Beijing, 100027, No. China
Tel: 86-10-85282100 Fax: 86-10-85282104

Atlanta
500 Sugar Mill Road, Suite 200B
Atlanta, GA 30350
Tel: 770-640-0034 Fax: 770-640-0307

Boston
2 Lan Drive, Suite 120
Westford, MA 01886
Tel: 978-692-3848 Fax: 978-692-3821

Chicago
333 Pierce Road, Suite 180
Itasca, IL 60143
Tel: 630-285-0071 Fax: 630-285-0075

Dallas
4570 Westgrove Drive, Suite 160
Addison, TX 75001
Tel: 972-818-7423 Fax: 972-818-2924

Detroit
Tri-Atria Office Building
32255 Northwestern Highway, Suite 190
Farmington Hills, MI 48334
Tel: 248-538-2250 Fax: 248-538-2260

Kokomo
2767 S. Albright Road
Kokomo, Indiana 46902
Tel: 765-864-8360 Fax: 765-864-8387

Los Angeles
18201 Von Karman, Suite 1090
Irvine, CA 92612
Tel: 949-263-1888 Fax: 949-263-1338

China - Chengdu
Microchip Technology Consulting (Shanghai)
Co., Ltd., Chengdu Liaison Office
Rm. 2401, 24th Floor,
Ming Xing Financial Tower
No. 88 TIDU Street
Chengdu 610016, China
Tel: 86-28-6766200 Fax: 86-28-6766599

China - Fuzhou
Microchip Technology Consulting (Shanghai)
Co., Ltd., Fuzhou Liaison Office
Unit 28F, World Trade Plaza
No. 71 Wusi Road
Fuzhou 350001, China
Tel: 86-591-7503506 Fax: 86-591-7503521

China - Shanghai
Microchip Technology Consulting (Shanghai)
Co., Ltd.
Room 701, Bldg. B
Far East International Plaza
No. 317 Xian Xia Road
Shanghai, 200051
Tel: 86-21-6275-5700 Fax: 86-21-6275-5060

China - Shenzhen

150 Motor Parkway, Suite 202


Hauppauge, NY 11788
Tel: 631-273-5305 Fax: 631-273-5335

Microchip Technology Consulting (Shanghai)


Co., Ltd., Shenzhen Liaison Office
Rm. 1315, 13/F, Shenzhen Kerry Centre,
Renminnan Lu
Shenzhen 518001, China
Tel: 86-755-2350361 Fax: 86-755-2366086

San Jose

Hong Kong

Microchip Technology Inc.


2107 North First Street, Suite 590
San Jose, CA 95131
Tel: 408-436-7950 Fax: 408-436-7955

Microchip Technology Hongkong Ltd.


Unit 901-6, Tower 2, Metroplaza
223 Hing Fong Road
Kwai Fong, N.T., Hong Kong
Tel: 852-2401-1200 Fax: 852-2401-3431

New York

Toronto
6285 Northam Drive, Suite 108
Mississauga, Ontario L4V 1X5, Canada
Tel: 905-673-0699 Fax: 905-673-6509

India
Microchip Technology Inc.
India Liaison Office
Divyasree Chambers
1 Floor, Wing A (A3/A4)
No. 11, OShaugnessey Road
Bangalore, 560 025, India
Tel: 91-80-2290061 Fax: 91-80-2290062

Korea
Microchip Technology Korea
168-1, Youngbo Bldg. 3 Floor
Samsung-Dong, Kangnam-Ku
Seoul, Korea 135-882
Tel: 82-2-554-7200 Fax: 82-2-558-5934

Singapore
Microchip Technology Singapore Pte Ltd.
200 Middle Road
#07-02 Prime Centre
Singapore, 188980
Tel: 65-334-8870 Fax: 65-334-8850

Taiwan
Microchip Technology Taiwan
11F-3, No. 207
Tung Hua North Road
Taipei, 105, Taiwan
Tel: 886-2-2717-7175 Fax: 886-2-2545-0139

EUROPE
Denmark
Microchip Technology Nordic ApS
Regus Business Centre
Lautrup hoj 1-3
Ballerup DK-2750 Denmark
Tel: 45 4420 9895 Fax: 45 4420 9910

France
Microchip Technology SARL
Parc dActivite du Moulin de Massy
43 Rue du Saule Trapu
Batiment A - ler Etage
91300 Massy, France
Tel: 33-1-69-53-63-20 Fax: 33-1-69-30-90-79

Germany
Microchip Technology GmbH
Gustav-Heinemann Ring 125
D-81739 Munich, Germany
Tel: 49-89-627-144 0 Fax: 49-89-627-144-44

Italy
Microchip Technology SRL
Centro Direzionale Colleoni
Palazzo Taurus 1 V. Le Colleoni 1
20041 Agrate Brianza
Milan, Italy
Tel: 39-039-65791-1 Fax: 39-039-6899883

United Kingdom
Arizona Microchip Technology Ltd.
505 Eskdale Road
Winnersh Triangle
Wokingham
Berkshire, England RG41 5TU
Tel: 44 118 921 5869 Fax: 44-118 921-5820
01/18/02

2002 Microchip Technology Inc.

You might also like