Beruflich Dokumente
Kultur Dokumente
AN643
Author:
Rodger Richey
Microchip Technology Inc.
INTRODUCTION
In the past, adding speech recording and playback
capability to a product meant using a digital signal
processor or a specialized audio chip. Now, using a
simplified Adaptive Differential Pulse Code Modulation
(ADPCM) algorithm, these audio capabilities can be
added to any PICmicro device. This application note will
cover the ADPCM compression and decompression
algorithms, performance comparison of all PICmicro
devices, and an application using a PIC16C72 microcontroller.
DEFINITION OF TERMS
step size - value of the step used for quantization of analog signals and inverse quantization of a number of steps.
quantization - the digital form of an analog input signal
is represented by a finite number of steps.
adaptive quantization - the step size of a quantizer is
dramatically changed with time in order to adapt to a
changing input signal.
inverse quantizer - a finite number of steps is
converted into a digital representation of an analog
signal.
THEORY OF OPERATION
The ADPCM algorithm takes advantage of the high
correlation between consecutive speech samples,
which enables future sample values to be predicted.
Instead of encoding the speech sample, ADPCM
encodes the difference between a predicted sample
and the speech sample. This method provides more
efficient compression with a reduction in the number of
bits per sample, yet preserves the overall quality of the
speech signal. The implementation of the ADPCM
algorithm provided in this application note is based on
the Interactive Multimedia Associations (IMA)
Recommended Practices for Enhancing Digital Audio
Compatibility in Multimedia Systems revision 3.00. The
ITU (formerly CCITT) G.721 ADPCM algorithm is well
known and has been implemented on many digital
signal processors such as the TMS320 family from
Texas Instruments and the ADSP-2100 family from
Analog Devices. ITU G.721 uses floating point
COMPRESSION
The input, si, to the encoder routine must be 16-bit twos
complement speech data. The range of allowable values for si is 32767 to -32768. Figure 1 shows a block
diagram for ADPCM compression and Appendix A has
a listing of the function ADPCMEncoder(). The
predicted sample, sp, and the quantizer step size index
are saved in a structure for the next iteration of the
encoder. Initially, the quantizer step size index and the
predicted sample (sp) are set to zero. The encoder
function takes a 16-bit twos complement speech
sample and returns an 8-bit number containing the
4-bit sign-magnitude ADPCM code.
si
d
Quantizer
Inverse
Quantizer
dq
sr
sp
Stepsize
Adapter
Adaptive
Predictor
DS00643B-page 1
AN643
The adaptive predictor of ITU G.721 adjusts according to
the value of each input sample using a weighted average
of the last six dequantized difference values and the last
two predicted values. So at this point, the dequantized difference, dq, is added to the predicted sample, sp, to produce a new predicted sample, sr. Finally the new
predicted sample, sr, is saved into sp.
2.
predsample = state.prevsample;
index = state.previndex;
3.
step = StepSizeTable[index];
4.
5.
if(diff >= 0)
code = 0;
else
{
code = 8;
diff = - diff;
}
6.
tempstep = step;
7.
8.
DS00643B-page 2
AN643
TABLE 1: ADPCMEncoder() STEP-BY-STEP FUNCTIONS (CONTINUED)
9.
if(code & 8)
predsample -= diffq;
else
predsample += diffq;
index += IndexTable[code];
if(index <
index
if(index >
index
state.prevsample = predsample;
state.previndex = index;
DECOMPRESSION
The input into the decoder, t, must be an 8-bit number
containing the 4-bit ADPCM data in sign-magnitude
format. The range of allowable values for t is 0 to 15,
where 7 = 0x07 and -7 = 0x0F. Figure 2 shows a block diagram for ADPCM decompression and Appendix B has a
listing of the function ADPCMDecoder(). The predicted
sample, sp, and the quantizer step size index are saved in
a structure for the next iteration of the decoder. Initially,
the quantizer step size index and the predicted sample
0)
= 0;
88)
= 88;
(sp) are set to zero. This function takes a 4-bit sign-magnitude ADPCM code and returns the 16-bit twos complement speech sample.
This decoder is the same as the one used in the encoder
routine. It uses the ADPCM value to update the inverse
quantizer, which produces a difference, dq. The difference, dq, is added to the predicted sample, sp, to produce
the output sample, sr. The output sample, sr, is then saved
into the predicted sample, sp, for the next iteration of the
decoder.
Inverse
Quantizer
Stepsize
Adapter
dq
sr
sp
Adaptive
Predictor
DS00643B-page 3
AN643
The following (Table 2) is a step-by-step description of
the ADPCMDecoder() function from Appendix B.
2.
predsample = state.prevsample;
index = state.previndex;
3.
step = StepSizeTable[index];
4.
5.
if(code & 8)
predsample -= diffq;
else
predsample += diffq;
6.
7.
index += IndexTable[code];
8.
if(index <
index
if(index >
index
9.
state.prevsample = predsample;
state.previndex = index;
0)
= 0;
88)
= 88;
return ( predsample );
DS00643B-page 4
AN643
IMA ADPCM REFERENCE ALGORITHM
The IMA, specifically the Digital Audio Technical Working
Group, is a trade association with representatives from
companies such as Compaq, Apple Computer, Crystal
Semiconductor, DEC, Hewlett-Packard, Intel,
Microsoft, Sony, and Texas Instruments to name a
few. This group is working towards a standard that defines
the exchange of high quality audio data between computing platforms. The algorithm from Intel/DVI (Digital Video
Interactive) has been selected as the standard due to its
audio dynamic range and low data rate. The
recommended digital audio exchange formats are given
in Table 3.
Mono/Stereo
8.0 kHz
11.025 kHz
22.05 kHz
44.10 kHz
Data Format
Notes
mono
mono
mono
4-bit ADPCM
DVI Algorithm
mono/stereo
mono/stereo
4-bit ADPCM
DVI Algorithm
mono/stereo
mono/stereo
4-bit ADPCM
DVI Algorithm
mono/stereo
CD-DA Standard
mono/stereo
4-bit ADPCM
DVI Algorithm
PERFORMANCE
Table 4 shows the performance comparison of the ADPCM compression and decompression routines for the PIC16C5X,
PIC16CXXX, and PIC17CXXX family of devices assuming 80 additional instruction cycles for overhead. Any device without a PWM module will have to increase the operating frequency to generate a software PWM. Table 4 also provides the
minimum external operating frequency required to run the routines. The C code from Appendix C was used. The
input/output data rate of the speech samples is 8.0 kHz. The minimum operating frequency is calculated as follows:
8000 x # of Total Instruction Cycles x 4.
For example, the ADPCM encoding using the PIC16CXXX family would require an 8000 x ( 225 + 80 ) x 4 = 9.760 MHz
external crystal.
Encode/Decode
# of Instruction Cycles
Encode
273
11.296 MHz
Decode
208
9.216 MHz
Encode
225
9.760 MHz
Decode
168
7.936 MHz
Encode
199
8.928 MHz
Decode
161
7.712 MHz
DS00643B-page 5
AN643
Table 5 illustrates the amount of program and data memory that the ADPCM algorithms consume for the various
PICmicro devices. The program memory numbers may
change slightly depending on the specific device being
used. The table memory column shows how much program memory is used to store the two lookup tables used
by the ADPCM algorithm.
Device
PIC16C5X
PIC16CXXX
PIC17CXXX
Encode
Decode
Encode
Decode
Encode
Decode
273
205
220
162
203
164
13
10
13
10
13
10
196
196
97
APPLICATION
The hardware for this application note implements only
the decompression algorithm, but the compression algorithm is also included in the firmware. A block diagram is
shown in Figure 3 and the schematic is provided in
Appendix E. The complete source code listing, including
a block diagram, is given in Appendix F.
The board uses a PIC16C72, rated for 20 MHz operation,
to control the speech decoding and output. The A/D (Analog-to-Digital) converter of the PIC16C72 is not used in
this design. Two 27C512A EPROMs from Microchip Technology are used to store up to 32.768 seconds of ADPCM
data. Each EPROM holds 65536 bytes. Each byte in the
EPROM contains two ADPCM values. One second of
speech requires 8000 ADPCM codes (8 kHz sample
rate). Therefore, each EPROM holds (65536 x 2) / 8000 =
16.384 seconds of speech. A 16-bit up counter is used to
clock data out of the EPROMs. This method uses only two
I/O lines to control the counter and eleven I/O lines to read
the EPROM data.
Speech regeneration is accomplished by using the Capture/Compare/PWM (CCP) module of the PIC16C72. The
PWM module is configured for a period of 32 kHz. This
allows each sample of the speech signal to be output for
four PWM periods. The period is calculated by using the
2x (1 / 20 MHz) 1
31.25 s = 2x 50 ns 1
625 =
2x
log(625) = log(2x)
log(625) = x log(2)
9.3 = x
A PWM duty cycle with up to 9-bits of resolution may be
used with a period of 32 kHz. The upper 9-bits of each
speech sample are used to set the PWM duty cycle
(CCPR1L
=
sample<15:9>,
CCP1CON<5:4>
= sample<8:7>). This PWM speech signal is passed
through a 4th-order Butterworth low pass filter with a corner frequency of 4 kHz. The low pass filter converts the
PWM into an analog voltage level. Finally, the analog voltage level is amplified by a National Semiconductor
LM386N-3 before entering the speaker.
Every 125 s (8 kHz) one ADPCM code must be
converted into a speech sample for output to the PWM.
This frame of 125 s relates to 625 instruction cycles for
an external crystal frequency of 20 MHz. The ADPCM
decode routine, EPROM reads and writes to the PWM
must be accomplished within 625 instruction cycles.
16-bit
Counter
16
27C512A
3
27C512A
Butterworth
LPF
DS00643B-page 6
Amplifier
Speaker
Power
Supply
AN643
To implement audio recording, the following changes to
the application hardware would have to be made:
Replace the EPROMs with RAM and
Add a microphone with input filtering and
Use the on-board A/D converter of the PIC16C7X
devices for 8-bit recording or
Use an external 12- to 16-bit A/D converter for
better quality recording
The following is the sequence of events to record and
store speech data. A timer would be used to set the
sample rate. When the timer overflowed an A/D
conversion would be started.
1. Start an A/D conversion when the timer
overflows.
2. Read the sample and call the routine
ADPCMEncoder().
3. Store the result in the upper 4-bits of a
temporary variable.
4. Start an A/D conversion when the timer
overflows.
5. Read the sample and call the routine
ADPCMEncoder().
6. Store the result in the lower 4-bits of the
temporary variable.
7. Write the temporary variable to the SRAM.
8. GOTO 1.
Typical conversion times for the PIC16C7XX devices
are 40 s. Assuming that the external crystal frequency
is 20 MHz and the sample rate is 8 kHz, the encoder
routine takes approximately 45 s (225 instruction
cycles x 200 ns) to complete. This leaves approximately
40 s or 200 instruction cycles to read the A/D converter, write to the SRAM and complete any other
tasks. An external A/D converter that is faster could be
used to increase the amount of time for processing
other tasks.
CONCLUSION
The final results of the application hardware using the
PIC16C72 are:
Compression and Decompression
- 906 words of Program Memory used
- 44% of total Program Memory
- 24 bytes of Data Memory used
- 19% of total Data Memory
Decompression only
- 686 words of Program Memory used
- 33% of total Program Memory
- 22 bytes of Data Memory used
- 17% of total Data Memory
~250 Instruction cycles to decode one ADPCM
code
- 40% of frame (250/625)
Hardware used
- CCP1 configured for PWM (9-bit duty cycle,
32 kHz period speech output)
- Timer2 to set the 8.0 kHz output sample rate
- 13 I/O lines to read data from the EPROMs
References:
1.
2.
3.
4.
COMPUTER PROGRAM
The IMA Reference ADPCM algorithm was written for a
PC using Borland C++ version 3.1. This program uses
the same routines that are used in Appendix C. A raw
sound file is recorded on the PC using a 16-bit sound
card. Speech is recorded at 8.0 kHz in 16-bit mono
mode. This raw speech file is processed by the encoder
part of the program which creates a file with the
ADPCM values. This file can now be burned into
EPROMs for use with the application hardware. The
decoder part of the program can take this file and
create a new 16-bit raw speech file. The 16-bit sound
card on the PC can play this file to ensure that the
ADPCM compression/decompression routines are
working properly. The PC program is given in
Appendix F. It is composed of three files:
pcspeech.c, pcadpcm.c, and pcadpcm.h.
5.
DS00643B-page 7
AN643
APPENDIX A:
ADPCMEncoder() FUNCTION
/*
/*
/*
/*
/*
/*****************************************************************************
*
ADPCMEncoder - ADPCM encoder routine
*
******************************************************************************
*
Input Variables:
*
*
signed long sample - 16-bit signed speech sample
*
*
Return Variable:
*
*
char - 8-bit number containing the 4-bit ADPCM code
*
*****************************************************************************/
char ADPCMEncoder( signed long sample )
{
int code;
/* ADPCM output value */
int tempstep;
/* Temporary step size */
/* Restore previous values of predicted sample and quantizer step
size index
*/
predsample = state.prevsample;
index = state.previndex;
step = StepSizeTable[index];
/* Compute the difference between the actual sample (sample) and the
the predicted sample (predsample)
*/
diff = sample - predsample;
if(diff >= 0)
code = 0;
else
{
code = 8;
diff = -diff;
}
/* Quantize the difference into the 4-bit ADPCM code using the
the quantizer step size
*/
tempstep = step;
if( diff >= tempstep )
{
code |= 4;
DS00643B-page 8
AN643
diff
}
tempstep
if( diff
{
code
diff
}
tempstep
if( diff
code
-= tempstep;
>>= 1;
>= tempstep )
|= 2;
-= tempstep;
>>= 1;
>= tempstep )
|= 1;
DS00643B-page 9
AN643
APPENDIX B:
ADPCMDecoder() FUNCTION
/*
/*
/*
/*
/*****************************************************************************
*
ADPCMDecoder - ADPCM decoder routine
*
******************************************************************************
*
Input Variables:
*
*
char code - 8-bit number containing the 4-bit ADPCM code
*
*
Return Variable:
*
*
signed long - 16-bit signed speech sample
*
*****************************************************************************/
signed long ADPCMDecoder(char code )
{
/* Restore previous values of predicted sample and quantizer step
size index
*/
predsample = state.prevsample;
index = state.previndex;
/* Find quantizer step size from lookup table using index
*/
step = StepSizeTable[index];
/* Inverse quantize the ADPCM code into a difference using the
quantizer step size
*/
diffq = step >> 3;
if( code & 4 )
diffq += step;
if( code & 2 )
diffq += step >> 1;
if( code & 1 )
diffq += step >> 2;
/* Add the difference to the predicted sample
*/
if( code & 8 )
predsample -= diffq;
else
predsample += diffq;
/* Check for overflow of the new predicted sample
DS00643B-page 10
AN643
*/
if( predsample > 32767 )
predsample = 32767;
else if( predsample < -32768 )
predsample = -32768;
/* Find new quantizer step size by adding the old index and a
table lookup using the ADPCM code
*/
index += IndexTable[code];
/* Check for overflow of the new quantizer step size index
*/
if( index < 0 )
index = 0;
if( index > 88 )
index = 88;
/* Save predicted sample and quantizer step size index for next
iteration
*/
state.prevsample = predsample;
state.previndex = index;
/* Return the new speech sample */
return( predsample );
}
DS00643B-page 11
AN643
APPENDIX C:
/*****************************************************************************
*
Filename:
ADPCM.C
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-9-96
*
*
Compiled using Bytecraft Ltd. MPC version BC.193
*
******************************************************************************
*
This file contains the ADPCM encode and decode routines. This
*
*
routines were obtained from the Interactive Multimedia Association's
*
*
Reference ADPCM algorithm. This algorithm was first implemented by
*
*
Intel/DVI.
*
*****************************************************************************/
/* Table of index changes */
const int IndexTable[16] = {0xff,0xff,0xff,0xff,2,4,6,8,
0xff, 0xff, 0xff, 0xff, 2, 4, 6, 8
0005 0782
ADDWF PCL
};
0006 34FF
RETLW FFh
0007 34FF
RETLW FFh
0008 34FF
RETLW FFh
0009 34FF
RETLW FFh
000A 3402
RETLW 02h
000B 3404
RETLW 04h
000C 3406
RETLW 06h
000D 3408
RETLW 08h
000E 34FF
RETLW FFh
000F 34FF
RETLW FFh
0010 34FF
RETLW FFh
0011 34FF
RETLW FFh
0012 3402
RETLW 02h
0013 3404
RETLW 04h
0014 3406
RETLW 06h
0015 3408
RETLW 08h
/* Quantizer step size lookup table */
const long StepSizeTable[89] = {
7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,
41,45,50,55,60,66,73,80,88,97,107,118,130,143,157,
173,190,209,230,253,279,307,337,371,408,449,494,544,
598,658,724,796,876,963,1060,1166,1282,1411,1552,
1707,1878,2066,2272,2499,2749,3024,3327,3660,4026,
4428,4871,5358,5894,6484,7132,7845,8630,9493,10442,
11487,12635,13899,15289,16818,18500,20350,22385,
24623, 27086, 29794, 32767
0016 0782
ADDWF PCL
};
0017 3407
RETLW 07h
0018 3400
RETLW 00h
0019 3408
RETLW 08h
001A 3400
RETLW 00h
001B 3409
RETLW 09h
001C 3400
RETLW 00h
001D 340A
RETLW 0Ah
001E 3400
RETLW 00h
001F 340B
RETLW 0Bh
0020 3400
RETLW 00h
0021 340C
RETLW 0Ch
0022 3400
RETLW 00h
0023 340D
RETLW 0Dh
0024 3400
RETLW 00h
0025 340E
RETLW 0Eh
0026 3400
RETLW 00h
0027 3410
RETLW 10h
0028 3400
RETLW 00h
0029 3411
RETLW 11h
002A 3400
RETLW 00h
DS00643B-page 12
AN643
002B
002C
002D
002E
002F
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
003A
003B
003C
003D
003E
003F
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
004A
004B
004C
004D
004E
004F
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
005A
005B
005C
005D
005E
005F
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
006A
006B
006C
006D
006E
006F
3413
3400
3415
3400
3417
3400
3419
3400
341C
3400
341F
3400
3422
3400
3425
3400
3429
3400
342D
3400
3432
3400
3437
3400
343C
3400
3442
3400
3449
3400
3450
3400
3458
3400
3461
3400
346B
3400
3476
3400
3482
3400
348F
3400
349D
3400
34AD
3400
34BE
3400
34D1
3400
34E6
3400
34FD
3400
3417
3401
3433
3401
3451
3401
3473
3401
3498
3401
34C1
3401
34EE
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
13h
00h
15h
00h
17h
00h
19h
00h
1Ch
00h
1Fh
00h
22h
00h
25h
00h
29h
00h
2Dh
00h
32h
00h
37h
00h
3Ch
00h
42h
00h
49h
00h
50h
00h
58h
00h
61h
00h
6Bh
00h
76h
00h
82h
00h
8Fh
00h
9Dh
00h
ADh
00h
BEh
00h
D1h
00h
E6h
00h
FDh
00h
17h
01h
33h
01h
51h
01h
73h
01h
98h
01h
C1h
01h
EEh
DS00643B-page 13
AN643
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
007A
007B
007C
007D
007E
007F
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
008A
008B
008C
008D
008E
008F
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
009A
009B
009C
009D
009E
009F
00A0
00A1
00A2
00A3
00A4
00A5
00A6
00A7
00A8
00A9
00AA
00AB
00AC
00AD
00AE
00AF
00B0
00B1
00B2
00B3
00B4
3401
3420
3402
3456
3402
3492
3402
34D4
3402
341C
3403
346C
3403
34C3
3403
3424
3404
348E
3404
3402
3405
3483
3405
3410
3406
34AB
3406
3456
3407
3412
3408
34E0
3408
34C3
3409
34BD
340A
34D0
340B
34FF
340C
344C
340E
34BA
340F
344C
3411
3407
3413
34EE
3414
3406
3417
3454
3419
34DC
341B
34A5
341E
34B6
3421
3415
3425
34CA
3428
34DF
342C
345B
3431
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
DS00643B-page 14
01h
20h
02h
56h
02h
92h
02h
D4h
02h
1Ch
03h
6Ch
03h
C3h
03h
24h
04h
8Eh
04h
02h
05h
83h
05h
10h
06h
ABh
06h
56h
07h
12h
08h
E0h
08h
C3h
09h
BDh
0Ah
D0h
0Bh
FFh
0Ch
4Ch
0Eh
BAh
0Fh
4Ch
11h
07h
13h
EEh
14h
06h
17h
54h
19h
DCh
1Bh
A5h
1Eh
B6h
21h
15h
25h
CAh
28h
DFh
2Ch
5Bh
31h
AN643
00B5
00B6
00B7
00B8
00B9
00BA
00BB
00BC
00BD
00BE
00BF
00C0
00C1
00C2
00C3
00C4
00C5
00C6
00C7
00C8
344B
3436
34B9
343B
34B2
3441
3444
3448
347E
344F
3471
3457
342F
3460
34CE
3469
3462
3474
34FF
347F
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
RETLW
4Bh
36h
B9h
3Bh
B2h
41h
44h
48h
7Eh
4Fh
71h
57h
2Fh
60h
CEh
69h
62h
74h
FFh
7Fh
002E
0030
0032
0034
0036
*/
*/
*/
*/
/*****************************************************************************
*
ADPCMEncoder - ADPCM encoder routine
*
******************************************************************************
*
Input Variables:
*
*
signed long sample - 16-bit signed speech sample
*
*
Return Variable:
*
*
char - 8-bit number containing the 4-bit ADPCM code
*
*****************************************************************************/
char ADPCMEncoder( signed long sample )
0037
{
00C9 1283
BCF
STATUS,RP0
00CA 00B7
MOVWF 37
00CB 0804
MOVF
FSR,W
00CC 00B8
MOVWF 38
0039
int code;
/* ADPCM output value */
00CD
00CE
00CF
00D0
00D1
00D2
00D3
00D4
00D5
00D6
00D7
00D8
00D9
00DA
00DB
00DC
00DD
00DE
00DF
00E0
00E1
00E2
00E3
082B
00B2
082C
00B3
082D
00B6
0836
0084
1003
0D84
3000
008A
0804
2016
1283
00B0
0A84
3000
008A
0804
2016
1283
00B1
MOVF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
BCF
RLF
MOVLW
MOVWF
MOVF
CALL
BCF
MOVWF
INCF
MOVLW
MOVWF
MOVF
CALL
BCF
MOVWF
2B,W
32
2C,W
33
2D,W
36
36,W
FSR
STATUS,C
FSR
00h
PCLATH
FSR,W
0016h
STATUS,RP0
30
FSR
00h
PCLATH
FSR,W
0016h
STATUS,RP0
31
index = state.previndex;
step = StepSizeTable[index];
DS00643B-page 15
AN643
00E4
00E5
00E6
00E7
00E8
00E9
00EA
00EB
00EC
00ED
00EE
00EF
0832
0237
00AE
0833
1C03
3E01
0238
00AF
1BAF
28F0
01B9
28F9
MOVF
SUBWF
MOVWF
MOVF
BTFSS
ADDLW
SUBWF
MOVWF
BTFSC
GOTO
CLRF
GOTO
32,W
37,W
2E
33,W
STATUS,C
01h
38,W
2F
2F,7
00F0h
39
00F9h
00F0
00F1
00F2
00F3
00F4
00F5
00F6
00F7
00F8
3008
00B9
09AF
09AE
0AAE
1D03
28F9
1283
0AAF
MOVLW
MOVWF
COMF
COMF
INCF
BTFSS
GOTO
BCF
INCF
08h
39
2F
2E
2E
STATUS,Z
00F9h
STATUS,RP0
2F
00F9
00FA
00FB
00FC
00FD
00FE
00FF
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
010A
010B
010C
010D
010E
010F
0110
0111
0112
0113
0113
0114
0115
0116
0117
0118
0119
011A
011B
011C
011D
011E
011F
1283
0830
00B4
0831
00B5
0D35
0CB5
0CB4
0D35
0CB5
0CB4
0D35
0CB5
0CB4
0830
022E
3080
062F
00A9
3080
0631
1C03
3E01
0229
1C03
2921
BCF
MOVF
MOVWF
MOVF
MOVWF
RLF
RRF
RRF
RLF
RRF
RRF
RLF
RRF
RRF
MOVF
SUBWF
MOVLW
XORWF
MOVWF
MOVLW
XORWF
BTFSS
ADDLW
SUBWF
BTFSS
GOTO
STATUS,RP0
30,W
34
31,W
35
35,W
35
34
35,W
35
34
35,W
35
34
30,W
2E,W
80h
2F,W
29
80h
31,W
STATUS,C
01h
29,W
STATUS,C
0121h
1283
1539
0830
02AE
0831
1C03
3E01
02AF
0830
07B4
0831
1803
3E01
BCF
BSF
MOVF
SUBWF
MOVF
BTFSS
ADDLW
SUBWF
MOVF
ADDWF
MOVF
BTFSC
ADDLW
STATUS,RP0
39,2
30,W
2E
31,W
STATUS,C
01h
2F
30,W
34
31,W
STATUS,C
01h
if(diff >= 0)
code = 0;
else
{
code = 8;
diff = -diff;
}
/* Quantize the difference into the 4-bit ADPCM code
using the quantizer step size. Inverse quantize
the ADPCM code into a predicted difference using
the quantizer step size */
diffq = step >> 3;
DS00643B-page 16
code |= 4;
diff -= step;
diffq += step;
AN643
0120 07B5
ADDWF
35
0121
0122
0123
0124
0125
0126
0127
0128
0129
012A
012B
012C
012D
012E
012F
0130
0131
0131
0132
0133
0134
0135
0136
0137
0138
0139
013A
013B
013C
013D
013E
1283
0D31
0CB1
0CB0
0830
022E
3080
062F
00A9
3080
0631
1C03
3E01
0229
1C03
293F
BCF
RLF
RRF
RRF
MOVF
SUBWF
MOVLW
XORWF
MOVWF
MOVLW
XORWF
BTFSS
ADDLW
SUBWF
BTFSS
GOTO
STATUS,RP0
31,W
31
30
30,W
2E,W
80h
2F,W
29
80h
31,W
STATUS,C
01h
29,W
STATUS,C
013Fh
1283
14B9
0830
02AE
0831
1C03
3E01
02AF
0830
07B4
0831
1803
3E01
07B5
BCF
BSF
MOVF
SUBWF
MOVF
BTFSS
ADDLW
SUBWF
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
STATUS,RP0
39,1
30,W
2E
31,W
STATUS,C
01h
2F
30,W
34
31,W
STATUS,C
01h
35
013F
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
014A
014B
014C
014D
014E
014F
014F
0150
0151
0152
0153
0154
0155
0156
1283
0D31
0CB1
0CB0
0830
022E
3080
062F
00A9
3080
0631
1C03
3E01
0229
1C03
2957
BCF
RLF
RRF
RRF
MOVF
SUBWF
MOVLW
XORWF
MOVWF
MOVLW
XORWF
BTFSS
ADDLW
SUBWF
BTFSS
GOTO
STATUS,RP0
31,W
31
30
30,W
2E,W
80h
2F,W
29
80h
31,W
STATUS,C
01h
29,W
STATUS,C
0157h
1283
1439
0830
07B4
0831
1803
3E01
07B5
BCF
BSF
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
STATUS,RP0
39,0
30,W
34
31,W
STATUS,C
01h
35
0157
0158
0159
015A
015B
015C
}
step >>= 1;
{
code |= 2;
diff -= step;
diffq += step;
}
step >>= 1;
1283
1DB9
2961
0834
02B2
0835
BCF
BTFSS
GOTO
MOVF
SUBWF
MOVF
STATUS,RP0
39,3
0161h
34,W
32
35,W
code |= 1;
diffq += step;
}
/* Fixed predictor computes new predicted sample by
adding the old predicted sample to predicted
difference */
if( code & 8 )
predsample -= diffq;
DS00643B-page 17
AN643
015D
015E
015F
0160
0161
0162
0163
0164
0165
0166
1C03
3E01
02B3
2967
0834
07B2
0835
1803
3E01
07B3
BTFSS
ADDLW
SUBWF
GOTO
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
STATUS,C
01h
33
0167h
34,W
32
35,W
STATUS,C
01h
33
0167
0168
0169
016A
016B
016C
016D
016E
016F
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
017A
017B
017C
017D
017E
017F
0180
0181
0182
0183
0184
0185
0186
3001
0732
00A8
3080
0633
00A7
3000
1803
3001
0727
0428
1D03
1C03
297B
30FF
1283
00B2
307F
00B3
2987
3080
1283
0633
00A7
3000
0227
1803
2987
1283
01B2
3080
00B3
MOVLW
ADDWF
MOVWF
MOVLW
XORWF
MOVWF
MOVLW
BTFSC
MOVLW
ADDWF
IORWF
BTFSS
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVLW
MOVWF
GOTO
MOVLW
BCF
XORWF
MOVWF
MOVLW
SUBWF
BTFSC
GOTO
BCF
CLRF
MOVLW
MOVWF
01h
32,W
28
80h
33,W
27
00h
STATUS,C
01h
27,W
28,W
STATUS,Z
STATUS,C
017Bh
FFh
STATUS,RP0
32
7Fh
33
0187h
80h
STATUS,RP0
33,W
27
00h
27,W
STATUS,C
0187h
STATUS,RP0
32
80h
33
0187
0188
0189
018A
018B
018C
018D
018E
018F
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
019A
018A
1283
0839
2005
1283
07B6
1BB6
01B6
3080
1283
0636
00A7
30D8
0227
1D03
1C03
299B
3058
1283
00B6
CLRF
BCF
MOVF
CALL
BCF
ADDWF
BTFSC
CLRF
MOVLW
BCF
XORWF
MOVWF
MOVLW
SUBWF
BTFSS
BTFSS
GOTO
MOVLW
BCF
MOVWF
PCLATH
STATUS,RP0
39,W
0005h
STATUS,RP0
36
36,7
36
80h
STATUS,RP0
36,W
27
D8h
27,W
STATUS,Z
STATUS,C
019Bh
58h
STATUS,RP0
36
else
predsample += diffq;
predsample = 32767;
index = 88;
DS00643B-page 18
AN643
019B
019C
019D
019E
019F
01A0
01A1
1283
0832
00AB
0833
00AC
0836
00AD
01A2 300F
01A3 0539
01A4 0008
BCF
MOVF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
STATUS,RP0
32,W
2B
33,W
2C
36,W
2D
state.prevsample = predsample;
state.previndex = index;
/* Return the new ADPCM code */
return ( code & 0x0f );
MOVLW 0Fh
ANDWF 39,W
RETURN
}
/*****************************************************************************
*
ADPCMDecoder - ADPCM decoder routine
*
******************************************************************************
*
Input Variables:
*
*
char code - 8-bit number containing the 4-bit ADPCM code
*
*
Return Variable:
*
*
signed long - 16-bit signed speech sample
*
*****************************************************************************/
signed long ADPCMDecoder(char code )
003A
{
01A5 1283
BCF
STATUS,RP0
01A6 00BA
MOVWF 3A
/* Restore previous values of predicted sample and
quantizer step size index */
01A7 082B
MOVF
2B,W
predsample = state.prevsample;
01A8 00B2
MOVWF 32
01A9 082C
MOVF
2C,W
01AA 00B3
MOVWF 33
01AB 082D
MOVF
2D,W
index = state.previndex;
01AC 00B6
MOVWF 36
/* Find quantizer step size from lookup table using
index */
01AD 0836
MOVF
36,W
step = StepSizeTable[index];
01AE 0084
MOVWF FSR
01AF 1003
BCF
STATUS,C
01B0 0D84
RLF
FSR
01B1 3000
MOVLW 00h
01B2 008A
MOVWF PCLATH
01B3 0804
MOVF
FSR,W
01B4 2016
CALL
0016h
01B5 1283
BCF
STATUS,RP0
01B6 00B0
MOVWF 30
01B7 0A84
INCF
FSR
01B8 3000
MOVLW 00h
01B9 008A
MOVWF PCLATH
01BA 0804
MOVF
FSR,W
01BB 2016
CALL
0016h
01BC 1283
BCF
STATUS,RP0
01BD 00B1
MOVWF 31
/* Inverse quantize the ADPCM code into a difference
using the quantizer step size */
01BE 0830
MOVF
30,W
diffq = step >> 3;
01BF 00B4
MOVWF 34
01C0 0831
MOVF
31,W
01C1 00B5
MOVWF 35
01C2 0D35
RLF
35,W
01C3 0CB5
RRF
35
01C4 0CB4
RRF
34
01C5 0D35
RLF
35,W
01C6 0CB5
RRF
35
01C7 0CB4
RRF
34
01C8 0D35
RLF
35,W
01C9 0CB5
RRF
35
01CA 0CB4
RRF
34
01CB 1D3A
BTFSS 3A,2
if( code & 4 )
01CC 29D3
GOTO
01D3h
DS00643B-page 19
AN643
01CD
01CE
01CF
01D0
01D1
01D2
01D3
01D4
01D5
01D6
01D7
01D8
01D9
01DA
01DB
01DC
01DD
01DE
01DF
01E0
01E1
01E2
01E3
01E4
01E5
01E6
01E7
01E8
01E9
01EA
01EB
01EC
01ED
01EE
01EF
01F0
01F1
01F2
01F3
01F4
01F5
0830
07B4
0831
1803
3E01
07B5
1283
1CBA
29E3
0830
00A8
0831
00A9
0D29
0CA9
0CA8
0828
07B4
0829
1803
3E01
07B5
1283
1C3A
29F6
0830
00A8
0831
00A9
0D29
0CA9
0CA8
0D29
0CA9
0CA8
0828
07B4
0829
1803
3E01
07B5
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
BCF
BTFSS
GOTO
MOVF
MOVWF
MOVF
MOVWF
RLF
RRF
RRF
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
BCF
BTFSS
GOTO
MOVF
MOVWF
MOVF
MOVWF
RLF
RRF
RRF
RLF
RRF
RRF
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
30,W
34
31,W
STATUS,C
01h
35
STATUS,RP0
3A,1
01E3h
30,W
28
31,W
29
29,W
29
28
28,W
34
29,W
STATUS,C
01h
35
STATUS,RP0
3A,0
01F6h
30,W
28
31,W
29
29,W
29
28
29,W
29
28
28,W
34
29,W
STATUS,C
01h
35
01F6
01F7
01F8
01F9
01FA
01FB
01FC
01FD
01FE
01FF
0200
0201
0202
0203
0204
0205
1283
1DBA
2A00
0834
02B2
0835
1C03
3E01
02B3
2A06
0834
07B2
0835
1803
3E01
07B3
BCF
BTFSS
GOTO
MOVF
SUBWF
MOVF
BTFSS
ADDLW
SUBWF
GOTO
MOVF
ADDWF
MOVF
BTFSC
ADDLW
ADDWF
STATUS,RP0
3A,3
0200h
34,W
32
35,W
STATUS,C
01h
33
0206h
34,W
32
35,W
STATUS,C
01h
33
0206
0207
0208
0209
020A
020B
020C
020D
020E
020F
3001
0732
00A8
3080
0633
00A7
3000
1803
3001
0727
MOVLW
ADDWF
MOVWF
MOVLW
XORWF
MOVWF
MOVLW
BTFSC
MOVLW
ADDWF
01h
32,W
28
80h
33,W
27
00h
STATUS,C
01h
27,W
DS00643B-page 20
diffq += step;
predsample -= diffq;
else
predsample += diffq;
AN643
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
021A
021B
021C
021D
021E
021F
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
022A
022B
022C
022D
022E
022F
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0428
1D03
1C03
2A1A
30FF
1283
00B2
307F
00B3
2A26
3080
1283
0633
00A7
3000
0227
1803
2A26
1283
01B2
3080
00B3
018A
1283
083A
2005
1283
07B6
1BB6
01B6
3080
1283
0636
00A7
30D8
0227
1D03
1C03
2A3A
3058
1283
00B6
IORWF
BTFSS
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVLW
MOVWF
GOTO
MOVLW
BCF
XORWF
MOVWF
MOVLW
SUBWF
BTFSC
GOTO
BCF
CLRF
MOVLW
MOVWF
CLRF
BCF
MOVF
CALL
BCF
ADDWF
BTFSC
CLRF
MOVLW
BCF
XORWF
MOVWF
MOVLW
SUBWF
BTFSS
BTFSS
GOTO
MOVLW
BCF
MOVWF
28,W
STATUS,Z
STATUS,C
021Ah
FFh
STATUS,RP0
32
7Fh
33
0226h
80h
STATUS,RP0
33,W
27
00h
27,W
STATUS,C
0226h
STATUS,RP0
32
80h
33
predsample = 32767;
PCLATH
STATUS,RP0
3A,W
0005h
STATUS,RP0
36
36,7
36
80h
STATUS,RP0
36,W
27
D8h
27,W
STATUS,Z
STATUS,C
023Ah
58h
STATUS,RP0
36
023A
023B
023C
023D
023E
023F
0240
0241
0242
1283
0832
00AB
01AC
1BAB
03AC
1283
0836
00AD
BCF
MOVF
MOVWF
CLRF
BTFSC
DECF
BCF
MOVF
MOVWF
0243
0244
0245
0246
0833
0084
0832
0008
MOVF
33,W
MOVWF FSR
MOVF
32,W
RETURN
index = 88;
STATUS,RP0
32,W
2B
2C
2B,7
2C
STATUS,RP0
36,W
2D
state.previndex = index;
DS00643B-page 21
AN643
APPENDIX D:
DS00643B-page 22
R5
C7
560 pF
121k 107k
R3
C8
220 pF
121k
R4
X1
20 MHz
Start
CE
OE1
OE2
2
3
-V
+9V DC
9V
Power Jack
J1
C15
0.1 F
LF442
C6
0.1 F
8 U6A
1
+V
S2
Push SW
140k
R8
165k
C10
68 pF
R7
28
27
26
25
24
23
22
21
20
19
18
17
16
15
6
5
C18
0.1 F
C3
0.1 F
3
7
2
4 8
6 1
C11
0.1 F
9V
U8
5
C20
10 F
1
2
3
4
10k
R10
U10
BST
V+
CAP+
OSC
GND SHDN
CAPVOUT
MAX1044
C25
10 F
8
7
6
5
C21
0.1 F
Speaker
-V
+V
0.33 F
C14
220 F
LS1
C13
Speaker Amplifier
Q1
Q2
Q3
Q4
Q5
Q6
Q7
12
11
9
6
5
4
3
LM386N-3
CD4024
14
VDD
7
VSS
RST
CLK
U3
CD4040
Voltage Inverter
C12
0.1 F
VDD
1
RST 2
0.1 F
LF442
U6B
ECLK
RST
RB7
RB6
RB5
RB4
RB3
RB2
RB1
RB0
165k
C9
1 nF
R6
VDD
0.1 F
C1
RB7
MCLR
RB6
RA0/AN0
RB5
RA1/AN1
RB4
RA2/AN2
RB3
RA3/AN3/VREF
RB2
RA4/T0CKI
RB1
RA5/AN4/SS
RB0/INT
VSS
VDD
OSC1/CLKIN
OSC2/CLKOUT
VSS
RC0/T1OSO/T1CKI
RC7
RC1/T1OSI
RC6
RC2/CCP1
RC5/SDO
RC3/SCK/SCL
RC4/SDI/SDA
PIC16C72
Push SW
S1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
9V
J2
1
Selects the analog
2
+V
voltage, +/-5V or +/-9V
3
Jumper
VDD
10k
R13
C23
15 pF
C22
15 pF
R1
Start
10k
R2
VDD
10
9
8
7
6
5
4
3
25
24
21
23
2
26
27
1
27C512
CE
OE
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
A13
A14
A15
U4
27C512
CE
OE
11
12
13
15
16
17
18
19
Vcc 28
GND 14
O0
O1
O2
O3
O4
O5
O6
O7
RB0
RB1
RB2
RB3
RB4
RB5
RB6
RB7
RB0
RB1
RB2
RB3
RB4
RB5
RB6
RB7
C5
0.1 F
VDD
C4
0.1 F
VDD
CE 20
OE2 22
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
A13
A14
A15
CE 20
OE1 22
APPENDIX E:
10k
VDD
AN643
DS00643B-page 23
AN643
APPENDIX F:
Yes
Clear Address, ADPCM
structure, and enable
Timer2 and PWM
No
Address
overflow?
Yes
Reset Address and
EPROM Address
No
Address
overflow?
Yes
Reset EPROM Address,
disable EPROMs and
PWM
DS00643B-page 24
AN643
Firmware Listing
/*****************************************************************************
*
Filename:
SPEECH.C
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Title:
Senior Applications Engineer
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-9-96
*
*
Compiled using Bytecraft Ltd. MPC version BC.193
*
******************************************************************************
*
Include files:
*
*
16c72.h - Standard include file for the PIC16C72 device
*
*
delay14.h - Standard include file for delay routines
*
*
adpcm.h - Include file with ADPCM related information (Rev0)
*
*
adpcm.c - Source file with ADPCM routines (Rev0)
*
******************************************************************************
*
This file contains the routines to:
*
*
- Initialize the PIC16C72
*
*
- Read data from the EPROMs
*
*
- Call the ADPCM decoder routine
*
*
- Send data to the DAC and PWM
*
*
- Increment the address of the EPROMs
*
******************************************************************************
*
External Clock Frequency: 20MHz
*
*
Configuration Bit Settings
*
*
OSC:
HS
*
*
WDT:
Off
*
*
PWRTE: On
*
*
CP:
Off
*
*
Compression and Decompression (only Decompression is used)
*
*
Program Memory Usage:
906 words
*
*
Data Memory Usage:
24 bytes
*
*
Compression only
*
*
Program Memory Usage:
686 words
*
*
Data Memory Usage:
22 bytes
*
*****************************************************************************/
#pragma option v
#include <16c72.h>
#pragma option +l;
0FFB
#define MAXROM 2043
0005 0FFB
#pragma memory ROM [MAXROM] @ 0x05;
0020 0060
#pragma memory RAM [0x96]
@ 0x20;
00A0 0060
#pragma memory RAM [0x32]
@ 0xA0;
#pragma option +l;
#include "adpcm.h"
/*****************************************************************************
*
Filename:
PCADPCM.H
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Title:
Senior Applications Engineer
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-11-96
*
*
Compiled using Bytecraft Ltd. MPC version BC.193
*
******************************************************************************
*
This is the header file that contains the ADPCM structure definition
*
*
and the function prototypes.
*
*****************************************************************************/
struct ADPCMState {
signed long prevsample;
/ * Predicted sample */
int
previndex; /*Index into step size table*/
};
DS00643B-page 25
AN643
/* Function prototype for the ADPCM Encoder routine */
signed long ADPCMDecoder( char );
/* Function prototype for the ADPCM Decoder routine */
char ADPCMEncoder( signed long );
0000
0001
0002
0000
0002
0006
0007
0025
002A
002B 0003
DS00643B-page 26
AN643
*
None
*
*
Return Variables:
*
*
None
*
*****************************************************************************/
void main(void)
{
003B
char code;
// EPROM byte
003C
signed long sample;
// decoded sample
003E
unsigned long pwmout; // temporary variable for PWM
025D 2247
CALL
0247h
Init72();
025E
025F
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
026A
026B
026C
026D
026E
026F
0270
0271
MOVLW
BCF
MOVWF
BSF
NOP
NOP
BCF
NOP
NOP
BCF
NOP
NOP
BCF
NOP
NOP
BCF
BSF
BSF
BSF
BSF
01h
STATUS,RP0
2A
PORTC,6
Wait = 1;
3001
1283
00AA
1707
0000
0000
1307
0000
0000
1085
0000
0000
1005
0000
0000
108C
1683
148C
170B
178B
PORTC,6
PORTA,1
PORTA,0
PIR1,1
STATUS,RP0
PIR1,1
INTCON,PEIE
INTCON,GIE
PORTC.RST = 1;
NOP();
NOP();
PORTC.RST = 0;
NOP();
NOP();
PORTA.OE1 = 0;
NOP();
NOP();
PORTA.CE = 0;
NOP();
NOP();
PIR1.TMR2IF = 0;
PIE1.TMR2IE = 1;
INTCON.PEIE = 1;
INTCON.GIE = 1;
// Enable EPROM #1
while(1)
{
0272
0273
0274
0275
0275
0276
0277
0278
0279
027A
027B
027C
027D
1283
1807
2A72
BCF
BTFSC
GOTO
STATUS,RP0
PORTC,0
0272h
1283
1C07
2A75
1283
01A5
01A6
01AB
01AC
01AD
BCF
BTFSS
GOTO
BCF
CLRF
CLRF
CLRF
CLRF
CLRF
STATUS,RP0
PORTC,0
0275h
STATUS,RP0
25
26
2B
2C
2D
027E
027F
0280
0281
0282
0283
1683
1107
1283
1512
300F
0097
BSF
BCF
BCF
BSF
MOVLW
MOVWF
STATUS,RP0
PORTC,2
STATUS,RP0
T2CON,2
0Fh
CCP1CON
0284
0285
0286
0287
0288
0289
028A
028B
028C
1283
0806
00BB
083B
00A7
0EA7
300F
0527
390F
BCF
MOVF
MOVWF
MOVF
MOVWF
SWAPF
MOVLW
ANDWF
ANDLW
STATUS,RP0
PORTB,W
3B
3B,W
27
27
0Fh
27,W
0Fh
Address = 0;
T2CON.TMR2ON = 1;
// Enable Timer2
CCP1CON = 0x0f;
// Enable PWM
do
{
DS00643B-page 27
AN643
028D
028E
028F
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
029A
029B
029C
029D
029E
029F
02A0
02A1
02A2
02A3
02A4
02A5
02A6
02A7
02A8
02A9
02AA
02AB
02AC
02AD
02AE
02AF
02B0
02B1
02B2
21A5
1283
00BC
0804
00BD
1283
082A
3800
1D03
2A92
3001
1283
00AA
083C
00BE
083D
00BF
1FBD
2AA4
3080
023F
00BF
2AA6
3080
07BF
083F
00A7
0CA7
307F
0527
0095
30CF
0597
183F
1697
1283
1BBE
1617
CALL
BCF
MOVWF
MOVF
MOVWF
BCF
MOVF
IORLW
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
BTFSS
GOTO
MOVLW
SUBWF
MOVWF
GOTO
MOVLW
ADDWF
MOVF
MOVWF
RRF
MOVLW
ANDWF
MOVWF
MOVLW
ANDWF
BTFSC
BSF
BCF
BTFSC
BSF
01A5h
STATUS,RP0
3C
FSR,W
3D
STATUS,RP0
2A,W
00h
STATUS,Z
0292h
01h
STATUS,RP0
2A
3C,W
3E
3D,W
3F
3D,7
02A4h
80h
3F,W
3F
02A6h
80h
3F
3F,W
27
27
7Fh
27,W
CCPR1L
CFh
CCP1CON
3F,0
CCP1CON,5
STATUS,RP0
3E,7
CCP1CON,4
02B3
02B4
02B5
02B6
02B7
02B8
02B9
02BA
02BB
02BC
02BD
02BE
02BF
02C0
02C1
02C2
02C3
02C4
02C5
02C6
02C7
02C8
02C9
02CA
02CB
02CC
300F
1283
053B
118A
21A5
118A
1283
00BC
0804
00BD
1283
082A
3800
1D03
2ABD
3001
1283
00AA
083C
00BE
083D
00BF
1FBD
2ACF
3080
023F
MOVLW
BCF
ANDWF
BCF
CALL
BCF
BCF
MOVWF
MOVF
MOVWF
BCF
MOVF
IORLW
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
BTFSS
GOTO
MOVLW
SUBWF
0Fh
STATUS,RP0
3B,W
PCLATH,3
01A5h
PCLATH,3
STATUS,RP0
3C
FSR,W
3D
STATUS,RP0
2A,W
00h
STATUS,Z
02BDh
01h
STATUS,RP0
2A
3C,W
3E
3D,W
3F
3D,7
02CFh
80h
3F,W
DS00643B-page 28
while(Wait);
Wait = 1;
if(sample<0)
// Add offset to
else
pwmout += 0x8000;
CCPR1L = (pwmout>>9)&0x007f; // Write 7 bits
// to CCPR1L
if(pwmout&0x0100)
CCP1CON.5 = 1;
if(pwmout&0x0080)
// Write 2 bits
// to CCP1CON
// to get 9-bit
CCP1CON.4 = 1;
// PWM
while(Wait);
Wait = 1;
if(sample<0)
// Add offset to
AN643
02CD
02CE
02CF
02D0
02D1
02D2
02D3
02D4
02D5
02D6
02D7
02D8
02D9
02DA
02DB
02DC
02DD
00BF
2AD1
3080
07BF
083F
00A7
0CA7
307F
0527
0095
30CF
0597
183F
1697
1283
1BBE
1617
MOVWF
GOTO
MOVLW
ADDWF
MOVF
MOVWF
RRF
MOVLW
ANDWF
MOVWF
MOVLW
ANDWF
BTFSC
BSF
BCF
BTFSC
BSF
3F
02D1h
80h
3F
3F,W
27
27
7Fh
27,W
CCPR1L
CFh
CCP1CON
3F,0
CCP1CON,5
STATUS,RP0
3E,7
CCP1CON,4
02DE
02DF
02E0
02E1
02E2
02E3
02E4
02E5
02E6
02E7
02E8
02E9
02EA
02EB
02EC
1283
0AA5
1903
0AA6
1787
0000
0000
1387
0000
0000
0826
0425
118A
1D03
2A84
BCF
INCF
BTFSC
INCF
BSF
NOP
NOP
BCF
NOP
NOP
MOVF
IORWF
BCF
BTFSS
GOTO
STATUS,RP0
25
STATUS,Z
26
PORTC,7
02ED
02EE
02EF
02F0
02F1
02F2
02F3
02F4
02F5
02F6
02F7
02F8
02F9
02FA
02FB
02FC
02FD
02FE
02FF
0300
0301
0302
0303
1283
1405
0000
0000
1485
0000
0000
1705
0000
0000
1305
0000
0000
1105
0000
0000
1005
0000
0000
01A5
01A6
0000
0000
BCF
BSF
NOP
NOP
BSF
NOP
NOP
BSF
NOP
NOP
BCF
NOP
NOP
BCF
NOP
NOP
BCF
NOP
NOP
CLRF
CLRF
NOP
NOP
STATUS,RP0
PORTA,0
else
pwmout += 0x8000;
CCPR1L = (pwmout>>9)&0x007f; // Write 7 bits
// to CCPR1L
if(pwmout&0x0100)
CCP1CON.5 = 1;
if(pwmout&0x0080)
// Write 2 bits
// to CCP1CON
// to get 9-bit
CCP1CON.4 = 1;
// PWM
// Increment Address of EPROMS
PORTC,7
26,W
25,W
PCLATH,3
STATUS,Z
0284h
PORTA,1
PORTA,6
PORTA,6
PORTA,2
PORTA,0
25
26
Address++;
PORTC.ECLK = 1;
NOP();
NOP();
PORTC.ECLK = 0;
NOP();
NOP();
} while(Address);
PORTA.CE = 1;
// Disable EPROM #1
NOP();
NOP();
PORTA.OE1 = 1;
NOP();
NOP();
PORTA.RST = 1;
NOP();
NOP();
PORTA.RST = 0;
NOP();
NOP();
PORTA.OE2 = 0;
NOP();
NOP();
PORTA.CE = 0;
NOP();
NOP();
Address = 0;
1283
0806
00BB
083B
00A7
BCF
MOVF
MOVWF
MOVF
MOVWF
// Enable EPROM #2
NOP();
NOP();
do
{
0304
0305
0306
0307
0308
STATUS,RP0
PORTB,W
3B
3B,W
27
DS00643B-page 29
AN643
0309
030A
030B
030C
030D
030E
030F
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
031A
031B
031C
031D
031E
031F
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
032A
032B
032C
032D
032E
032F
0330
0331
0332
0EA7
300F
0527
390F
21A5
1283
00BC
0804
00BD
1283
082A
3800
1D03
2B12
3001
1283
00AA
083C
00BE
083D
00BF
1FBD
2B24
3080
023F
00BF
2B26
3080
07BF
083F
00A7
0CA7
307F
0527
0095
30CF
0597
183F
1697
1283
1BBE
1617
SWAPF
MOVLW
ANDWF
ANDLW
CALL
BCF
MOVWF
MOVF
MOVWF
BCF
MOVF
IORLW
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
BTFSS
GOTO
MOVLW
SUBWF
MOVWF
GOTO
MOVLW
ADDWF
MOVF
MOVWF
RRF
MOVLW
ANDWF
MOVWF
MOVLW
ANDWF
BTFSC
BSF
BCF
BTFSC
BSF
27
0Fh
27,W
0Fh
01A5h
STATUS,RP0
3C
FSR,W
3D
STATUS,RP0
2A,W
00h
STATUS,Z
0312h
01h
STATUS,RP0
2A
3C,W
3E
3D,W
3F
3D,7
0324h
80h
3F,W
3F
0326h
80h
3F
3F,W
27
27
7Fh
27,W
CCPR1L
CFh
CCP1CON
3F,0
CCP1CON,5
STATUS,RP0
3E,7
CCP1CON,4
0333
0334
0335
0336
0337
0338
0339
033A
033B
033C
033D
033E
033F
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
300F
1283
053B
118A
21A5
118A
1283
00BC
0804
00BD
1283
082A
3800
1D03
2B3D
3001
1283
00AA
083C
00BE
083D
00BF
1FBD
MOVLW
BCF
ANDWF
BCF
CALL
BCF
BCF
MOVWF
MOVF
MOVWF
BCF
MOVF
IORLW
BTFSS
GOTO
MOVLW
BCF
MOVWF
MOVF
MOVWF
MOVF
MOVWF
BTFSS
0Fh
STATUS,RP0
3B,W
PCLATH,3
01A5h
PCLATH,3
STATUS,RP0
3C
FSR,W
3D
STATUS,RP0
2A,W
00h
STATUS,Z
033Dh
01h
STATUS,RP0
2A
3C,W
3E
3D,W
3F
3D,7
DS00643B-page 30
while(Wait);
Wait = 1;
if(sample<0)
// Add offset to
else
pwmout += 0x8000;
CCPR1L = (pwmout>>9)&0x007f; // Write 7 bits
// to CCPR1L
if(pwmout&0x0100)
CCP1CON.5 = 1;
if(pwmout&0x0080)
// Write 2 bits
// to CCP1CON
// to get 9-bit
CCP1CON.4 = 1;
// PWM
// Decode lower 4 bits of code
sample = ADPCMDecoder(code&0x0f);
while(Wait);
Wait = 1;
if(sample<0)
// Add offset to
AN643
034A
034B
034C
034D
034E
034F
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
035A
035B
035C
035D
2B4F
3080
023F
00BF
2B51
3080
07BF
083F
00A7
0CA7
307F
0527
0095
30CF
0597
183F
1697
1283
1BBE
1617
GOTO
MOVLW
SUBWF
MOVWF
GOTO
MOVLW
ADDWF
MOVF
MOVWF
RRF
MOVLW
ANDWF
MOVWF
MOVLW
ANDWF
BTFSC
BSF
BCF
BTFSC
BSF
034Fh
80h
3F,W
3F
0351h
80h
3F
3F,W
27
27
7Fh
27,W
CCPR1L
CFh
CCP1CON
3F,0
CCP1CON,5
STATUS,RP0
3E,7
CCP1CON,4
035E
035F
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
036A
036B
036C
036D
036E
036F
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
037A
037B
037C
037D
037E
037F
0380
0381
0382
0383
0384
1283
0AA5
1903
0AA6
1787
0000
0000
1387
0000
0000
0826
0425
118A
1D03
2B04
1283
1112
0197
1683
1507
1283
1405
0000
0000
1505
0000
0000
1705
0000
0000
1305
0000
0000
1085
0000
0000
1005
2A72
0008
BCF
INCF
BTFSC
INCF
BSF
NOP
NOP
BCF
NOP
NOP
MOVF
IORWF
BCF
BTFSS
GOTO
BCF
BCF
CLRF
BSF
BSF
BCF
BSF
NOP
NOP
BSF
NOP
NOP
BSF
NOP
NOP
BCF
NOP
NOP
BCF
NOP
NOP
BCF
GOTO
RETURN
STATUS,RP0
25
STATUS,Z
26
PORTC,7
else
pwmout += 0x8000;
CCPR1L = (pwmout>>9)&0x007f; // Write 7 bits
// to CCPR1L
if(pwmout&0x0100)
CCP1CON.5 = 1;
if(pwmout&0x0080)
// Write 2 bits
// to CCP1CON
// to get 9-bit
CCP1CON.4 = 1;
// PWM
// Increment Address of EPROMS
Address++;
PORTC,7
26,W
25,W
PCLATH,3
STATUS,Z
0304h
STATUS,RP0
T2CON,2
CCP1CON
STATUS,RP0
PORTC,2
STATUS,RP0
PORTA,0
PORTC.ECLK = 1;
NOP();
NOP();
PORTC.ECLK = 0;
NOP();
NOP();
} while(Address);
T2CON.TMR2ON = 0;
// Disable Timer2
CCP1CON = 0;
TRISC.PWM = 1;
// Disable PWM
// Make PWM input
PORTA.CE = 1;
// Disable EPROM #2
NOP();
NOP();
PORTA.OE2 = 1;
NOP();
NOP();
PORTA.RST = 1;
NOP();
NOP();
PORTA.RST = 0;
NOP();
NOP();
PORTA.OE1 = 0;
NOP();
NOP();
PORTA.CE = 0;
PORTA,2
PORTA,6
PORTA,6
PORTA,1
PORTA,0
0272h
// Enable EPROM #1
}
}
/*****************************************************************************
*
__INT - This is the interrupt service routine. Only Timer 2 overflow
*
*
is implemented.
*
******************************************************************************
DS00643B-page 31
AN643
*
Input Variables:
*
*
None
*
*
Return Variables:
*
*
None
*
*****************************************************************************/
0004 2B85
GOTO
0385h
void __INT(void)
0385
{
0385 1283
BCF
STATUS,RP0
if(PIR1.TMR2IF)
// Timer2 overflow interrupt
0386 1C8C
BTFSS PIR1,1
0387 2B8A
GOTO
038Ah
0388
{
0388 01AA
CLRF
2A
Wait = 0;
0389 108C
BCF
PIR1,1
PIR1.TMR2IF = 0;
// Clear flag
}
038A 0009
RETFIE
return;
}
ROM USAGE MAP
0000 to 0002
0004 to 038A
Total ROM used 038A
Errors
Warnings
DS00643B-page 32
:
:
0
0
AN643
APPENDIX G: PC ADPCM ENCODER/DECODER PROGRAM
PCSPEECH.C
/*****************************************************************************
*
Filename: PCSPEECH.C
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Title:
Senior Applications Engineer
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-11-96
*
*
Compiled using Borland C+ Version 3.1
*
******************************************************************************
*
Include files:
*
*
stdio.h - Standard input/output header file
*
*
stdlib.h - Standard library header file
*
*
string.h - Standard string header file
*
*
pcadpcm.h - ADPCM related information header file (Rev0)
*
******************************************************************************
*
Usage:
*
*
ADPCM Encode - pcspeech e <infile> <outfile>
*
*
<infile> is a 16-bit raw speech file
*
*
<outfile> contains the ADPCM codes
*
*
ADPCM Decode - pcspeech d <infile> <outfile>
*
*
<infile> contains the ADPCM codes
*
*
<outfile> is a 16-bit raw speech file
*
******************************************************************************
*
This file contains the code to:
*
*
- Open the input and output files
*
*
- Read data from the input file
*
*
- Call the encode/decode routines
*
*
- Write data to the output file
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcadpcm.h"
/*****************************************************************************
*
Usage - this routine prints a how to message for the pcspeech prgm
*
******************************************************************************
*
Input variables:
*
*
None
*
*
Output variables:
*
*
None
*
*****************************************************************************/
void Usage(void)
{
printf("ADPCM Encoder/Decoder -- usage:\n");
printf("\tEncoder = pcspeech e infile outfile\n");
printf("\tDecoder = pcspeech d infile outfile\n");
exit(1);
}
/*****************************************************************************
*
main - controls file I/O and ADPCM calls
*
******************************************************************************
*
Input variables:
*
*
int argc - number of arguements in argv
*
*
char **argv - pointer to an array of strings
*
*
Return variables:
*
*
None
*
*****************************************************************************/
void main(
int
argc,
char **argv)
DS00643B-page 33
AN643
{
int
which;
short
unsigned char
int
struct ADPCMstate
FILE
*fpin;
FILE
*fpout;
sample;
code;
n;
state;
state.prevsample=0;
state.previndex=0;
/* Determine if this is an encode or decode operation */
if(argc <= 1)
Usage();
else if( strcmp(argv[1],"e")==0 || strcmp(argv[1],"E")==0 )
which = 0;
else if( strcmp(argv[1],"d")==0 || strcmp(argv[1],"D")==0 )
which = 1;
argc--;
argv++;
/* Open input file for processing */
if(argc <= 1)
Usage();
else if( (fpin=fopen(argv[1],"rb"))==NULL)
{
printf("ADPCM Encoder/Decoder\n");
printf("ERROR: Could not open %s for input\n",argv[1]);
exit(1);
}
argc--;
argv++;
/* Open output file */
if(argc <= 1)
{
fclose(fpin);
Usage();
}
else if( (fpout=fopen(argv[1],"wb"))==NULL)
{
fclose(fpin);
printf("ADPCM Encoder/Decoder\n");
printf("ERROR: Could not open %s for output\n",argv[1]);
exit(1);
}
// ADPCM Decoder selected
if(which)
{
printf("ADPCM Decoding in progress\n");
/* Read and unpack input codes and process them */
while (fread(&code, sizeof (char), 1, fpin) == 1)
{
// Send the upper 4-bits of code to decoder
sample = ADPCMDecoder((code>>4)&0x0f, &state);
// Write sample for upper 4-bits of code
fwrite(&sample, sizeof(short), 1, fpout);
// Send the lower 4-bits of code to decoder
sample = ADPCMDecoder(code&0x0f,&state);
// Write sample for lower 4-bits of code
fwrite(&sample,sizeof(short),1,fpout);
}
}
DS00643B-page 34
AN643
// ADPCM Encoder selected
else
{
printf("ADPCM Encoding in progress\n");
/* Read input file and process */
while (fread(&sample, sizeof(short), 1, fpin) == 1)
{
// Encode sample into lower 4-bits of code
code = ADPCMEncoder(sample,&state);
// Move ADPCM code to upper 4-bits
code = (code << 4) & 0xf0;
// Read new sample from file
if(fread(&sample,sizeof(short),1,fpin)==0)
{
// No more samples, write code to file
fwrite(&code,sizeof(char),1,fpout);
break;
}
// Encode sample and save in lower 4-bits of code
code |= ADPCMEncoder(sample,&state);
// Write code to file, code contains 2 ADPCM codes
fwrite(&code, sizeof (char), 1, fpout);
}
}
fclose(fpin);
fclose(fpout);
}
PCADPCM.H
/*****************************************************************************
*
Filename: PCADPCM.H
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Title:
Senior Applications Engineer
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-11-96
*
*
Compiled using Borland C+ Version 3.1
*
******************************************************************************
*
This is the header file that contains the ADPCM structure definition *
*
and the function prototypes.
*
*****************************************************************************/
struct ADPCMstate {
short prevsample;/* Predicted sample */
int previndex;/* Index into step size table */
};
/* Function prototype for the ADPCM Encoder routine */
char ADPCMEncoder(short , struct ADPCMstate *);
/* Function prototype for the ADPCM Decoder routine */
int ADPCMDecoder(char , struct ADPCMstate *);
PCADPCM.C
/*****************************************************************************
*
Filename: PCADPCM.C
*
******************************************************************************
*
Author:
Rodger Richey
*
*
Title:
Senior Applications Engineer
*
*
Company:
Microchip Technology Incorporated
*
*
Revision:
0
*
*
Date:
1-11-96
*
*
Compiled using Borland C+ Version 3.1
*
DS00643B-page 35
AN643
******************************************************************************
*
Include files:
*
*
stdio.h - Standard input/output header file
*
*
pcadpcm.h - ADPCM related information header file (Rev0)
*
******************************************************************************
*
This file contains the ADPCM encode and decode routines. These
*
*
routines were obtained from the Interactive Multimedia Association's *
*
Reference ADPCM algorithm. This algorithm was first implemented by *
*
Intel/DVI.
*
*****************************************************************************/
#include <stdio.h>
#include "pcadpcm.h"
/* Table of
signed char
-1, -1,
-1, -1,
};
index changes */
IndexTable[16] = {
-1, -1, 2, 4, 6, 8,
-1, -1, 2, 4, 6, 8,
/* Compute the difference between the acutal sample (sample) and the
the predicted sample (predsample)
*/
diff = sample - predsample;
if(diff >= 0)
code = 0;
DS00643B-page 36
AN643
else
{
code = 8;
diff = -diff;
}
/* Quantize the difference into the 4-bit ADPCM code using the
the quantizer step size
*/
/* Inverse quantize the ADPCM code into a predicted difference
using the quantizer step size
*/
diffq = step >> 3;
if( diff >= step )
{
code |= 4;
diff -= step;
diffq += step;
}
step >>= 1;
if( diff >= step )
{
code |= 2;
diff -= step;
diffq += step;
}
step >>= 1;
if( diff >= step )
{
code |= 1;
diffq += step;
}
/* Fixed predictor computes new predicted sample by adding the
old predicted sample to predicted difference
*/
if( code & 8 )
predsample -= diffq;
else
predsample += diffq;
/* Check for overflow of the new predicted sample
*/
if( predsample > 32767 )
predsample = 32767;
else if( predsample < -32767 )
predsample = -32767;
/* Find new quantizer stepsize index by adding the old index
to a table lookup using the ADPCM code
*/
index += IndexTable[code];
/* Check for overflow of the new quantizer step size index
*/
if( index < 0 )
index = 0;
if( index > 88 )
index = 88;
/* Save the predicted sample and quantizer step size index for
next iteration
*/
state->prevsample = (short)predsample;
state->previndex = index;
DS00643B-page 37
AN643
/* Return the new ADPCM code
*/
return ( code & 0x0f );
}
/*****************************************************************************
*
ADPCMDecoder - ADPCM decoder routine
*
******************************************************************************
*
Input variables:
*
*
char code - 8-bit number containing the 4-bit ADPCM code
*
*
struct ADPCMstate *state - ADPCM structure
*
*
Return variables:
*
*
int - 16-bit signed speech sample
*
*****************************************************************************/
int ADPCMDecoder(char code, struct ADPCMstate *state)
{
int step;/* Quantizer step size */
int predsample;/* Output of ADPCM predictor */
int diffq;/* Dequantized predicted difference */
int index;/* Index into step size table */
/* Restore previous values of predicted sample and quantizer step
size index
*/
predsample = (int)(state->prevsample);
index = state->previndex;
/* Find quantizer step size from lookup table using index
*/
step = StepSizeTable[index];
/* Inverse quantize the ADPCM code into a difference using the
quantizer step size
*/
diffq = step >> 3;
if( code & 4 )
diffq += step;
if( code & 2 )
diffq += step >> 1;
if( code & 1 )
diffq += step >> 2;
/* Add the difference to the predicted sample
*/
if( code & 8 )
predsample -= diffq;
else
predsample += diffq;
/* Check for overflow of the new predicted sample
*/
if( predsample > 32767 )
predsample = 32767;
else if( predsample < -32767 )
predsample = -32767;
/* Find new quantizer step size by adding the old index and a
table lookup using the ADPCM code
*/
index += IndexTable[code];
/* Check for overflow of the new quantizer step size index
*/
if( index < 0 )
index = 0;
if( index > 88 )
DS00643B-page 38
AN643
index = 88;
/* Save predicted sample and quantizer step size index for next
iteration
*/
state->prevsample = (short)predsample;
state->previndex = index;
/* Return the new speech sample */
return( predsample );
}
DS00643B-page 39
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.
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.
M
WORLDWIDE SALES AND SERVICE
AMERICAS
ASIA/PACIFIC
Japan
Corporate Office
Australia
Rocky Mountain
China - Beijing
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
San Jose
Hong Kong
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