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/
╨хщЄшэу@Mail.ru Rambler's Top100 Rambler's Top100 Rambler's Top100    
Используются технологии uCoz