This is
DTMF decoding program, provided by:
Stephen
James Hardy (T/A SW Tekno) Canberra, Australia
hardy@sweng.stortek.com
========
Source code ========
; Caveat:
Requires tone duration of 160ms.а DTMF
standard only
; requires
50ms tone.
; This
source code is copyright (C) 1996 to Stephen James Hardy.
;
Permission is hereby granted to reproduce, assemble and run this code
; for
non-commercial purposes providing this notice is not removed
; from
source code copies.
;
; This
source code is provided as-is with no warranty expressed or
;
implied.а Do not use where damage to
persons or property may result
; from
source code failure.
;
; Written
for the 16C84, but should run on most any 16Cxx...
;
; Target
configuration:
;аа PORTB: Sample input as unsigned binary.а With a 16C7x, change the
;ааааааааа code to read the ADC instead.
;аа PORTA: Connnected to 5 LEDs:
;ааааааааа RA0-3 : indicate decoded tone (0-F)
;ааааааааа RA4аа
: 0 if tone OK, 1 if tone not recognised.
;аа Osc: 10MHz xtal.
;
; Assemble
using MPASM /C- flag.
;
;
ааааааа listааа
p=pic16c84
ааааааа include "p16c84.inc"ааа ; Mchip standard include
ааааааа radixаа
dec
; NB: If
the following is changed, check assembly to ensure timer
; constants
(TONEL0 etc) fit in 1 byte.
CLKSPDа equаааа
10ааааааааааааа ; Target clock
speed (MHz)
; Register
mapping:
RBASEаа equаааа
0Chаааааааааааа ; First general
register.
;------------------
; Bank 0
registers.а Rather profligate use made
thereof.а Could be
; reduced
with a bit of twiddling.
;------------------
ааааааа cblockа
RBASE
ааааааа dtmf_code1ааааааааааааа ; Result of first trial
ааааааа dtmf_code2ааааааааааааа ; Result of 2nd trial
ааааааа dtmf_rааааааааааааааааа ; Result of high- or
low-group trial
ааааааа dtmf_rrааааааааааа ааааа; Temp result
ааааааа dtmf_t1lааааааааааааааа ; Regs for correlation
accumulators.
ааааааа dtmf_t1h
ааааааа dtmf_t2l
ааааааа dtmf_t2h
ааааааа dtmf_tcаааааааааааааааа ; Tick counter for timing
ааааааа dtmf_tccааааааааааааааа ; Tick counter reload constant
ааааааа dtmf_scаааааааааааааааа ; Sample counter for 1 tone
ааааааа dtmf_stаааааааааааааааа ; Sample state (0-3)
ааааааа dtmf_csаааааааааааааааа ; Latest sample
ааааааа dtmf_slаааааааааааааа аа; sum/avg low
ааааааа dtmf_shаааааааааааааааа ; sum/avg high
ааааааа dtmf_mlаааааааааааааааа ; max low
ааааааа dtmf_mhаааааааааааааааа ; max high
ааааааа endc
ааааааа orgаааа
0
;------------------------
; Power-up
initialisation
;------------------------
pwrupаа bsfаааа
status,rp0ааааа ; Select bank 2
; Set RB
pullups, falling edge interrupt, increment t0 on instruction cycle,
; assign
prescaler to WDT (not used), prescale 1:1.
ааааааа movlwаа
(1<<psa)
ааааааа movwfаа
option_reg
ааааааа clrfааа
trisaаааааааааа ; Set port A to
outputs
ааааааа movlwаа
0FFh
ааааааа movwfаа
trisbаааааааааа ; Set port B to
inputs
ааааааа clrfааа
statusааааааааа ; Back to bank 0.
demo_dtmf_listen
ааааааа bcfаааа
intcon,GIEааааа ; Disable
interrupts
а ааааааcallааа dtmf_listenаааа ; Do it...
; W
contains code
ааааааа movwfаа
portaаааааааааа ; Show on LEDs
attached to port A.
ааааааа gotoааа
demo_dtmf_listenааааааа ;
...forever
;--------------------------------------------------------------
; dtmf_listen:а Detects and decodes DTMF tones applied to the
ADC.
;
;
Interrupts must be disabled (as written) since instruction cycle
; counting
is used to perform timing.а This
restriction may be removed
; if
rewritten to use interrupts to perform controlled timebase sampling.
;
; On return
W contains the DTMF signal (0-15) with following correspondence
; to
standard telephone keypad:
; Wаааа Key
; -аааа ---
; 0аааа 1
; 1аааа 4
; 2аааа 7
; 3аааа *
; 4аааа 2
; 5аааа 5
; 6аааа 8
; 7аааа 0
; 8аааа 3
; 9аааа 6
; Aаааа 9
; Bаааа #
; Cаааа A
; Dаааа B
; Eаааа C
; Fаааа D
; i.e the 2
LSBs of W index the low tone group, and the other 2 bits
; index the
high tone group.
; In the
case that no tone was reliably detected, W contains FF.
;
;
Note:а 8-bit ADC is used.а For maximum reliability, the DTMF tone
; should
use the full range of the ADC.а However,
if the low- and
;
high-group tones are within 1dB of each other, it is possible to
; use a
1-bit ADC (i.e. comparator)
;
;
Algorithm:
; The eight
possible tones used in DTMF are searched for one-by-one.
; This
approach is allowable because of the 200ms required for each
;
signal.а 78.2us are allocated for
sampling (a total of 4*10*8
; samples;
this is repeated for reliability hence sampling takes
; 156.4ms
which allows the rest of the application a few ms to determine
; whether a
tone is present.
;
; Since one
tone is being searched for at a time, the following method
; is
appropriate:а Sample at 4 times the
frequency of the search tone,
; for a
total of 10 waves.а This allows
correlation of the signal with
; the
search tone; a high correlation indicating the tone is present.
; 10 waves
are selected since the DTMF tones differ by 10% steps.а The
; other
tones will thus cancel out when correlated with the search tone
; (as a
consequence of the orthogonality of the sine function basis).
;
; The 8
tones are tried in sequence.а The largest
correlation from each
; of the
high and low tone groups is selected.а If
the highest correl in
; each group
is greater than or equal 1.5 times the average, then
; that tone
is adjudged present.а If both the high
and low tone group
; is
present, an initial DTMF code is decided.а
The process is repeated
; and, if
the same code is present the next time, that code is returned.
;
Otherwise, the 'uncertain' code (FF) is returned.
;
;--------------------------------------------------------------
SAMPSPC
equаааа 4аааааааааааааа ; Sample points per tone
cycle.а Don't change!
WAVESаа equаааа
10ааааааааааааа ; Number of tone
cycles to sample
SINTVLа equаааа
250000*CLKSPD/SAMPSPC ; PIC cycles between samples at f=1Hz
ааааааааааааааааааааааааааааааа ; - divide by
tone (Hz) to get cycles.
ааааааааааааааааааааааааааааааа ; For DTMF,
will range from 897 (697Hz)
ааааааааааааааа аааааааааааааааа; to 382 (1633Hz) at 10MHz
xtal.
FIXDLAY
equаааа 36ааааааааааааа ; Fixed delay to make following
<= 256.
аааааа ; Select according to the formula:
аааааа ; FIXDLAY = 29.89*CLKSPD - 263.7
аааааа ; (round up).
SLCYCLES
equааа (FIXDLAY-1)*3+29а ; PIC cycles taken in the dtmf_lp loop
ааааааааааааааааааааааааааааааа ; not counting
the wait loop at dtmf_wtim
ааааааааааааааааааааааааааааааа ; Code is
designed so this is constant!
TLCYCLES
equааа 3аааааааааааааа ; Number of PIC cycles per wait
loop,
ааааааааааааааааааааааааааааааа ; 1 less than
this on last execution.
; Loop
constants for each DTMF tone. Must be 1..256 inclusive.а TONEL0
; is the
largest and should be made as close as possible to 256 by adjusting
; the
constant FIXDLAY (and hence SLCYCLES).а The
smallest constant
; (TONEH3)
should also be as large as possible for accuracy - this places
; limits on
the lowest clock speed that will work.а Min
clock speed should
; be around
3.7MHz.а If clock is faster than 17.3MHz,
then the code will
; need to
be modified to add yet more delay since FIXDLAY will be over 256.
TONEL0а equаааа
(SINTVL/697-SLCYCLES)/TLCYCLES
TONEL1а equаааа
(SINTVL/770-SLCYCLES)/TLCYCLES
TONEL2а equаааа
(SINTVL/852-SLCYCLES)/TLCYCLES
TONEL3а equаааа
(SINTVL/941-SLCYCLES)/TLCYCLES
TONEH0а equаааа
(SINTVL/1209-SLCYCLES)/TLCYCLES
TONEH1а equаааа
(SINTVL/1336-SLCYCLES)/TLCYCLES
TONEH2а equаааа
(SINTVL/1477-SLCYCLES)/TLCYCLES
TONEH3а equаааа
(SINTVL/1633-SLCYCLES)/TLCYCLES
dtmf_listen
ааааааа callааа
dtmf_lgаааааааа ; Sample for low
group => dtmf_r
done_lg
btfscаа dtmf_r,7ааааааа ; Done lg: check result reg (0-3 or FF)
ааааааа retlwаа
0FFhааааааааааа ; Return if
uncertain
ааааааа movfааа
dtmf_r,w
ааааааа movwfаа
dtmf_code1ааааа ; Move to code
result 1
ааааааа callааа
dtmf_hgаааааааа ; Sample for high
group => dtmf_r
done_hg
btfscаа dtmf_r,7ааааааа ; Done hg: check result
ааааааа retlwаа
0FFhааааааааааа ; return if
uncertain
ааааааа bcfаааа
status,C
ааааааа rlfаааа
dtmf_r
ааааааа rlfаааа
dtmf_r,wааааааа ; *4, into W
ааааааа iorwfаа
dtmf_code1,fааа ; Or in low group
; Now
repeat to make sure...
ааааааа callааа
dtmf_lgаааааааа ; Sample for low
group => dtmf_r
ааааааа btfscаа
dtmf_r,7ааааааа ; check result reg
(0-3 or FF)
ааааааа retlwаа
0FFhааааааааааа ; Return if
uncertain
ааааааа movfааа
dtmf_r,w
ааааааа movwfаа
dtmf_code2ааааа ; Move to code
result 2
ааааааа callааа
dtmf_hgаааааааа ; Sample for high
group => dtmf_r
ааааааа btfscаа
dtmf_r,7
ааааааа retlwаа
0FFhааааааааааа ; return if
uncertain
ааааааа bcfаааа
status,C
ааааааа rlfаааа
dtmf_r
ааааааа rlfаааа
dtmf_r,wааааааа ; *4, into W
ааааааа iorwfаа
dtmf_code2ааааа ; Or in low group
(result in W)
; Check if
both agree
ааааааа subwfаа
dtmf_code1,fааа ; code1 = code1 -
code2
ааааааа btfssаа
status,Zааааааа ; equal?
ааааааа retlwаа
0FFhааааааааааа ; no, return
uncertain.
ааааааа returnааааааааааааааааа ; else return w = DTMF code.
; Sample
for all low group tones, select the largest.
dtmf_lg
clrfааа dtmf_slаааааааа ; Clear sum
ааааааа clrfааа
dtmf_sh
ааааааа clrfааа
dtmf_mlаааааааа ; Clear max
ааааааа clrfааа
dtmf_mh
ааааааа clrfааа
dtmf_rrаааааааа ; Tone 0
ааааааа movlwаа
TONEL0
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for low tone 0.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEL1
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for low tone 1.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEL2
ааааааа
movwfаа dtmf_tccааааааа ; Set timer constant for low tone 2.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEL3
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for low tone 3.
ааааааа callааа
dtmf_samp аааааа; Sample etc.
dtmf_gа bcfаааа
status,C
ааааааа rrfаааа
dtmf_shаааааааа ; Div sum by 4 to
get average
ааааааа rrfаааа
dtmf_sl
dtmf_01
bcfаааа status,C
ааааааа rrfаааа
dtmf_sh
ааааааа rrfаааа
dtmf_sl
; while
dtmf_mh non zero, div m and s by 2.
ааааааа movfааа
dtmf_mh,w
ааааааа btfscаа
status,Z
ааааааа gotoааа
dtmf_02
ааааааа bcfаааа
status,C
ааааааа rrfаааа
dtmf_mh
ааааааа rrfаааа
dtmf_ml
ааааааа gotoааа
dtmf_01
; Now
results in LSB.а Mult s (avg) by 1.5
dtmf_02
bcfаааа status,C
ааааааа rrfаааа
dtmf_sl,w
ааааааа addwfаа
dtmf_sl,w
ааааааа btfscаа
status,C
ааааааа gotoааа
dtmf_03аааааааа ; Return uncertain
if carry.
; Compare
with m (max).а If max is not >=
1.5*avg, then uncertain.
ааааааа subwfаа
dtmf_ml,wаааааа ; w = max -
1.5*avg.а C set if >= 0 (OK)
ааааааа btfscаа
status,C
ааааааа returnааааааааааааааааа ; return OK (result in
dtmf_r)
dtmf_03
movlwаа 0FFh
ааааааа movwfаа
dtmf_rааааааааа ; set uncertain
result
ааааааа return
; Sample
for all high group tones, select the largest.
dtmf_hg
clrfааа dtmf_slаааааааа ; Clear sum
ааааааа clrfааа
dtmf_sh
ааааааа clrfааа
dtmf_mlаааааааа ; Clear max
ааааааа clrfааа
dtmf_mh
ааааааа clrfааа
dtmf_rrаааааааа ; Tone 0
ааааааа movlwаа
TONEH0
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for high tone 0.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEH1
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for high tone 1.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEH2
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for high tone 2.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа incfааа
dtmf_rr
ааааааа movlwаа
TONEH3
ааааааа movwfаа
dtmf_tccааааааа ; Set timer
constant for high tone 3.
ааааааа callааа
dtmf_sampаааааа ; Sample etc.
ааааааа gotoааа
dtmf_gааааааааа ; Go to common
processing for lo, hi groups
;
; This
routine performs all samples for a particular tone.а It selects
; the
largest correlation into dtmf_t1l/h (which is the return value).
;
dtmf_samp
movlw SAMPSPC*WAVESаа ; Total samples
ааааааа movwfаа
dtmf_scаааааааа ; move to sample
counter
ааааааа clrfааа
dtmf_stаааааааа ; Initial state
ааааааа clrfааа
dtmf_t1lааааааа ; Clear
correlation accumulators
ааааааа clrfааа
dtmf_t1h
ааааааа clrfааа
dtmf_t2l
ааааааа clrfааа
dtmf_t2h
;
; Main
sample loop.а The code is written to take
a constant number of
; cycles no
matter what.а This explains some of the
odd things like
; seemingly
unnecessary goto's.
;
dtmf_lp
movfааа portb,wаааааааа ; 1 - Get sample (e.g. from port B)
ааааааа movwfаа
dtmf_csаааааааа ; 2 -Save it
ааааааа movlwаа
high dtmf_bstate ; 3
ааааааа movwfаа
pclathааааааааа ; 4
ааааааа movfааа
dtmf_st,wаааааа ; 5 - Get current
state
ааааааа addwfаа
pcl,fаааааааааа ; 6,7 - Branch on
state (0-3)
dtmf_bstate
ааааааа gotoааа
dtmf_st0ааааааа ; 8,9 - Check asm
list to make sure all
ааааааа gotoааа
dtmf_st1ааааааа ; of these 4
instr's on same 256-byte page
ааааааа gotoааа
dtmf_st2ааааааа ;
ааааааа
gotoааа dtmf_st3ааааааа ;
dtmf_st0
movfаа dtmf_cs,wаааааа ; 10 - Get sample
ааааааа addwfаа
dtmf_t1l,fааааа ; 11 - Add to
accumulator
ааааааа btfscаа
status,Cааааааа ; 12,13 - Test
carry out
ааааааа incfааа
dtmf_t1hааааааа ; 13 - Increment
high byte if carry out
ааааааа gotoааа
dtmf_joinаааааа ; 14,15 - continue
common
dtmf_st1
movfаа dtmf_cs,wаааааа ; Get sample
ааааааа addwfаа
dtmf_t2l,fааааа ; Add to
accumulator
ааааааа btfscаа
status,Cааааааа ; Test carry out
ааааааа incfааа
dtmf_t2hааааааа ; Increment high
byte if carry out
ааааааа gotoааа
dtmf_joinаааааа ; continue common
dtmf_st2
comfаа dtmf_cs,wаааааа ; Get 'negative' sample
ааааааа addwfаа
dtmf_t1l,fааааа ; Add to
accumulator
ааааааа btfscаа
status,Cааааааа ; Test carry out
ааааааа incfаа
аdtmf_t1hааааааа ; Increment high byte if carry out
ааааааа gotoааа
dtmf_joinаааааа ; continue common
dtmf_st3
comfаа dtmf_cs,wаааааа ; Get 'negative' sample
ааааааа addwfаа
dtmf_t2l,fааааа ; Add to
accumulator
ааааааа btfscаа
status,Cааааааа ; Test carry out
ааааааа incfааа
dtmf_t2hааааааа ; Increment high
byte if carry out
ааааааа gotoааа
dtmf_joinаааааа ; continue common
dtmf_join
incfа dtmf_st,wаааааа ; 16
ааааааа andlwаа
3аааааааааааааа ; 17
ааааааа movwfа
аdtmf_stаааааааа ; 18 - Update state
ааааааа decfszа
dtmf_scаааааааа ; 19,20 -
Decrement sample count
ааааааа gotoааа
dtmf_tmrааааааа ; 20,21 - If not
finished, sample again
; Finished
samples, select largest from dtmf_t1 and dtmf_t2 into dtmf_t1.
; Average
expected value is subtracted, abs value taken.а
Avg expected
; value is
WAVES in high byte, zero in low byte.
dtmf_lx
movlwаа WAVES
ааааааа subwfаа
dtmf_t1h,fааааа ; t1 -= expavg
ааааааа btfssаа
dtmf_t1h,7ааааа ; t1 -ve?
ааааааа gotoааа
$+3аааааааааааа ; no, skip next
ааааааа comfааа
dtmf_t1hааааааа ; Negate (don't
worry about the 1 diff!)
ааааааа comfааа
dtmf_t1l
ааааааа movlwаа
WAVES
ааааааа subwfаа
dtmf_t2h,fааааа ; t2 -= expavg
ааааааа btfssаа
dtmf_t2h,7ааааа ; t2 -ve?
ааааааа gotoааа
$+3ааааааааааа а; no, skip next
ааааааа comfааа
dtmf_t2h
ааааааа comfааа
dtmf_t2l
ааааааа movfааа
dtmf_t1h,w
ааааааа subwfаа
dtmf_t2h,wааааа ; w = t2h-t1h (C
set if t1h<=t2h)
ааааааа btfssаа
status,C
ааааааа gotoааа
dtmf_04аааааааа ; cont if t1 >
t2
ааааааа btfssаа
status,Z
ааааааа gotoааа
dtmf_swapаааааа ; move t2->t1
if t2>t1
ааааааа movfааа
dtmf_t1l,wааааа ; high equal, test
low
ааааааа subwfаа
dtmf_t2l,wааааа ; w = t2l-t1l
ааааааа btfssаа
status,C
ааааааа gotoааа
dtmf_04аааааааа ; cont if t1 >
t2
dtmf_swap
movfа dtmf_t2h,wааааа ; Set t1 = t2 (return value)
ааааааа movwfаа
dtmf_t1h
ааааааа movfааа
dtmf_t2l,w
ааааааа movwfаа
dtmf_t1l
;
; Sum.
dtmf_04
movfааа dtmf_t1l,w
ааааааа addwfаа
dtmf_sl,f
ааааааа movfааа
dtmf_t1h,w
ааааааа btfscаа
status,C
ааа ааааaddlwаа
1
ааааааа addwfаа
dtmf_sh,f
;
; Compare
with current maximum.а If greater, set
new max.
dtmf_05
movfааа dtmf_mh,w
ааааааа subwfаа
dtmf_t1h,wааааа ; w = t1h-mh (C
set if mh<=t1h)
ааааааа btfssаа
status,C
ааааааа returnааааааааааааааааа ; ret if m > t1
ааааааа btfssаа
status,Z
ааааааа gotoааа
dtmf_sw2ааааааа ; move t1->m if
t1>m
ааааааа movfааа
dtmf_ml,wаааааа ; high equal, test
low
ааааааа subwfаа
dtmf_t1l,wааааа ; w = t1l-ml
ааааааа btfssаа
status,C
ааааааа returnааааааааааааааааа ; ret if m > t1
dtmf_sw2
movfаа dtmf_t1h,wааааа ; Set m = t1
ааааааа movwfаа
dtmf_mh
ааааааа movfааа
dtmf_t1l,w
ааааааа movwfаа
dtmf_ml
ааааааа movfааа
dtmf_rr,wаааааа ; Tone number
ааааааа movwfаа
dtmf_rааааааааа ; Set new tone
number
ааааааа return
; Waste
time until ready for next sample
dtmf_tmr
movlwа FIXDLAYаааааааа ; 22 - Constant delay
ааааааа movwfаа
dtmf_tcаааааааа ; 23
ааааааа decfszа
dtmf_tcаааааааа ; 24,25
ааааааа gotoааа
$-1аааааааааааа ;
ааааааа movfааа
dtmf_tcc,wааааа ; 26+3(n-1)
ааааааа movwfаа
dtmf_tcаааааааа ; 27 - Load tick
counter constant
dtmf_wtim
decfsz dtmf_tcааааааа ; Decrement tick
counter
ааааааа gotoааа
dtmf_wtimаааааа ; Tight loop until
zero
ааааааа gotoааа
dtmf_lpаааааааа ; 28,29 - Get next
sample
ааааааа end
╧хЁхщЄш:
/├ыртэр /
CBuild/
JavaScript 1.2-5.6/
Delifi6/
I2C ъюэЄЁюыыхЁ√/
AVR ъюэЄЁюыыхЁ√/
╧╦╚╤/
AHDL/
VHDL/
LPT EPP/ LPT ECP/ PCI/ COM port/ I2C/ RS-232/
Используются технологии uCoz
|