HT95R6x CPT (Call Progress Tone) Decoder Function D/N:AN0227E Introduction The CPT (Call Progress Tone), is a group of voice tones sent from the switchboard to the caller to indicate the call condition, such as Dial Tone, Busy Tone, Ring-back Tone, Record Tone etc. These tones and the information that they contain can be used by auto-dialing systems. After the auto-dialing system dials a number, the received CPT signals will determine the status of the called party and then act accordingly. For example, a Ring-back Tone indicates that the called party is in a connected status. Holtek s HT95R64/HT95R65 includes an internal CPT detector. The following describes how to use the CPT detector in the HT95R6x. Operation Principles Using switched capacitor technology, the internal band-pass filter with a band range of 305Hz to 640Hz (call progress tone zone) in the HT95R6x shows excellent performance as the figure shows below. When a CPT signal is detected by the CPT detector, corresponding envelope signals will be sent to the external device to distinguish which CPT signal it is from the Dial Tone, Busy Tone, Ring-back Tone and Recorder Tone. 1
The relevant CPT detector pins are CPTSIN, CPTENB, CPTVREF, CPTENV, CPTX1, CPTX2, VDD4 and VSS4. No register is related to the CPT. CPTSIN AC coupled analog signal input pin for CPT detector. CPTENB CPT detector enable bit. When CPTENB=VSS, the CPT detector is enabled, or disabled when CPTENB=VDD. Power consumption can be reduced when the CPT detector is disabled. CPTVREF 1/2 VDD reference voltage output pin. When CPTENB=VDD, CPTVREF is disabled. CPTENV When an input signal for the CPT detector is within specification, this pin will output the envelope relative to the input signal with a typical 40ms timing delay. CPTX1 and CPTX2 CPTX1 and CPTX2 are connected to an external 32768Hz crystal or resonator for the CPT detector clock source. VDD4 and VSS4 Power supply for the CPT detector. Users may connect CPTENB with a common I/O pin to enable or disable the CPT detector and another I/O pin to detect the CPT detector output signals and then through the specification of the CPT distinguish the CPT type by software applications. The following table describes the general CPT specifications. 2
Application Circuits HT95R6x CPT (Call Progress Tone) Decoder Function Pin PA7 connects to CPTENB in the figure above to enable/disable the CPT detector. Pin PA6 connects to CPTENV to detect the envelopes from the CPTENV output. 3
S/W Flowchart Start Enable CPT detector, set Timer0 as 2ms timer mode, enable Timer0 interrupt N CPTENV low -> High? Y N Flag1=1? Timer0 Interrupt Y T0ON=0, Flag1=0, count2=count0 Count0++ Check count1 and count2, Determine CPT type Check count0 T0ON=1, flag0=1 Return N CPTENV high -> Low and flag0=1? T0ON=0, flag0=0 Count1=count0, Flag1=1, T0ON=1 Y user_sub() 4
Program Description HT95R6x CPT (Call Progress Tone) Decoder Function The program will decide the the CPT type by detecting the high and low level time of the envelope signals out of one output cycle from the CPTENV pin. Set Timer0 to a 2ms timer mode and enable the interrupt. Count0 will add 1 at every interrupt. When the device detects the CPTENV pin changing from low to high, Timer0 will be enabled. When CPTENV changes from high to low, disable Timer0 first, save the Count0 values in Count1 (high level width,) and then set Count0 to zero, enable Timer0. Wait for another detection of CPTENV shifting from low to high, disable Timer0 and save Count0 values to Count2 (low level width.) Compare the specifications of count1 and count2, and then decide which type of Call Progress Tone the detected signal belongs to. If both count1 and count2 are larger than 245 and smaller than 255, it will be Busy Tone. The tolerance of the time from the program is ±10ms. Users may adjust this according to actual situations. The program uses the HCLK 3.58MHz as the system clock yet when the HT95R6x is reset, the default system clock will be 32768Hz, so it is necessary to set the UPEN and MODE1 in MODE register as 1. Program Example //Option :WDT Disable #include "HT95R65.h" #define cpt_en _12_7 //CPT Enable #define cpt_enc _13_7 #define cpt_in _12_6 //CPT CPTENV #define cpt_inc _13_6 #pragma vector ext_int @0x04 #pragma vector tmr0_int @0x08 #pragma vector tmr1_int @0x0c #pragma vector per_int @0x10 #pragma vector rtc_int @0x1c #pragma vector multi_int @0x18 typedef unsigned char uint8; typedef signed char int8; typedef unsigned long uint16; typedef signed long int16; #pragma rambank0 bit dial_tone; // detected flag for Precision Dial Tone and Old Dial Tone bit busy_tone; // detected flag for Precision Busy Tone and Old busy Tone bit pr_tone; // detected flag for Precision Recorder Tone bit or_tone; // detected flag for Old Recorder Tone bit rb_tone; // detected flag for Precision Ring-back Tone and Old Ring-back Tone bit flag0; // detected flag for cpt_in rising edge bit p_flag; // cpt_in previous state bit flag1; uint16 count0; 5
uint16 count1; // high pulse width counter uint16 count2; // low pulse width counter #pragma norambank //******************interrupt subroutine*******************// void ext_int(void) void tmr0_int(void) count0++; if(count0>1010&&flag0==1) flag0=0; count0=0; dial_tone=1; // Dial Tone was detected _t0on=0; if(count0>2100) // Anomalies happened _t0on=0; flag0=0; flag1=0; count0=0; count1=0; count2=0; void tmr1_int(void) void per_int(void) void rtc_int(void) void multi_int(void) void clear_ram(uint8 start_addr,uint8 end_addr,uint8 bankn) _tblp=end_addr; if(bankn==0) for(_mp0=start_addr;_mp0<_tblp;_mp0++) _iar0=0; else _tmr0l=bankn; for(_mp1=start_addr;_mp1<_tblp;_mp1++) _bp=_tmr0l;_iar1=0; void cpt_init_sub() cpt_enc=0; cpt_en=0; // enable cpt module cpt_inc=1; _emi=1; _et0i=1; _tmr0l=0x01; _tmr0h=0xf9; // Timer0 clock source:fsys/4,fsys=3.58mhz _tmr0c=0x80; // Timer0 used timer mode, generates interrupt every 2ms 6
void cpt_type_sub() //with count1 and count2,determines CPT type if((count1>120&&count1<130&&count2>120&&count2<130) (count1>95&&count1<105&&count2>1 45&&count2<155)) or_tone=1; if(count1>145&&count1<155&&count2>95&&count2<105) pr_tone=1; if(count1>245&&count1<255&&count2>245&&count2<255) busy_tone=1; if(count1>990&&count1<1010&&count2>1980&&count2<2020) rb_tone=1; void cpt_detect_sub() if(p_flag==0&&cpt_in==1) if(flag1==1) _t0on=0; count2=count0; //measure low pulse width flag1=0; count0=0; cpt_type_sub(); _t0on=1; flag0=1; if(p_flag==1&&cpt_in==0&&flag0==1) _t0on=0; flag0=0; count1=count0; //measure high pulse width count0=0; flag1=1; _t0on=1; p_flag=cpt_in; void user_sub() //user subroutine void main() _upen=1; // enable frequency up conversion to generate HCLK _delay(165); // 32768Hz->HCLK, execute 20ms delay,165*4/32.768 約 20ms _mode1=1; // select HCLK as as CPU clock system 7
_f0=0;_f1=0; clear_ram(0x40,0xff,0); cpt_init_sub(); while(1) cpt_detect_sub(); user_sub(); // select HCLK=3.58MHz as CPU clock system Conclusion The program provides users with a reference of how to use Timer0 as an interrupt timer counter to detect the time of an envelope high and low level out of one output cycle from the CPT detector so as to distinguish the type of CPT. 8