CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

MT8889 driver
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
Fausto



Joined: 26 Mar 2007
Posts: 2

View user's profile Send private message

MT8889 driver
PostPosted: Fri Aug 03, 2007 4:59 am     Reply with quote

//////////////////////////////////////////////////////////////////////////
// Driver per MC8889C DTMF Transceiver //
// //
// init_8889() Inizializza il chip. //
// //
// compose_dtmf_tone() Compone una stringa dtmf //
// //
// //
// decode_dtmf_tone() Decodifica il tono ricevuto //
// Il pin di interrupt del chip deve //
// essere collegato ad un pin di //
// interrupt del pic. //
// //
// utilzzo timer1.h per le temporizzazioni //
// //
// //
//----------------------------------------------------------------------//
// Tabella di codifica /decodifica | //
// | //
// digit D3 D2 D1 D0 | //
// 1 0 0 0 1 | //
// 2 0 0 1 0 | //
// 3 0 0 1 1 | //
// 4 0 1 0 0 | //
// 5 0 1 0 1 | //
// 6 0 1 1 0 | //
// 7 0 1 1 1 | //
// 8 1 0 0 0 | //
// 9 1 0 0 1 | //
// 0 1 0 1 0 | //
// * 1 0 1 1 | //
// # 1 1 0 0 | //
// A 1 1 0 1 | //
// B 1 1 1 0 | //
// C 1 1 1 1 | //
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// //
// Control Register A CRA //
// //
// bit 3 RSEL Register SELect = 1 seleziona CRB per il prossimo ciclo //
// dopo la scrittura su CRB torna a 0 //
// quindi punta di nuovo a RCA //
// //
// bit 2 IRQ interrupt enable = 1 abilita l'interrupt, (attivo basso) //
// si attiva per un tono valido oppure //
// quando il trasmettitore è pronto per //
// nuovi dati (solo in burst mode) //
// //
// bit 1 CP/DTMF call progress = 0 attiva il modo DTMF; //
// =1 call progress (legge il ring) //
// //
// bit 0 TOUT Tone Out Control = 1 abilitato; = 0 disabilitato //
// //
// //
//----------------------------------------------------------------------//
// Control Register B CRB //
// //
// bit 3 C/R selettore righe colonne da usare con bit 2 //
// //
// bit 2 S/D Singolo o Doppio Tono. = 1 tono singolo; //
// = 0 tono doppio DTMF //
// //
// bit 1 TEST = 1 test, configura il DTMF ed il //
// segnale di IRQ riproduce il //
// segnale di ritardo Steering //
// //
// bit 0 BURST = 1 BURST disattivato = 0 attivo //
// Se attivo la scrittura del dato nel //
// registro di trasmissione ne provoca //
// la generazione seguita da una pausa //
// altrettanto lunga (51ms). Dopo la //
// pausa se IRQ è attivato viene //
// generato un interrupt //
// //
//----------------------------------------------------------------------//
// Status Register //
// //
// bit 0 IRQ = 1 ho ricevuto un interrupt, nei //
// bit 1 e 2 ho le specifiche di cosa //
// è successo //
// //
// bit 1 TRANSMIT DATA REGISTER //
// EMPTY (BURST MODE) = 1 in burst mode posso inviare il //
// prossimo dato //
// //
// bit 2 RECEIVE DATA REGISTER //
// FULL = 1 ho un dato valido nel registro //
// di ricezione //
// //
//////////////////////////////////////////////////////////////////////////


// definizione dei pins di comunicazione

#define DTMF_D3 PIN_D7 // I/O
#define DTMF_D2 PIN_D6 // bits di dato I/O
#define DTMF_D1 PIN_D5 // I/O
#define DTMF_D0 PIN_D4 // I/O

#define DTMF_RD PIN_D3 // DS/!RD Read
#define DTMF_RSO PIN_D2 // RS0 Register Select
#define DTMF_WR PIN_D0 // R/!W/!WR Write
#define DTMF_CS PIN_D1 // Chip Select
//
// RS0 WR RD Funzione
//
// 0 0 1 Write to Transmit Data Register
// 0 1 0 Read from Receive Data Register
// 1 0 1 Write to Control Register
// 1 1 0 Read from Status Register

#define DTMF_IRQ PIN_B0 // Interrupt Request O

// definizine dello status register

#define IRQ PIN_D4
#define TX_EMPTY PIN_D5
#define RX_FULL PIN_D6

void init_8889(void);
//////////////////////////////////////////////////////////////////////////////////////////////
// variabili globali del modulo
//////////////////////////////////////////////////////////////////////////////////////////////

char trasmetti_toni[18]; // contiene la sequenza dei caratteri che devono essere trasmessi

char voce_toni[18]; // contiene la sequenza per dei toni e della fascia da riprodurre
// in modo vocale

char codice_programmazione[6]; // stringa che contiene i toni ricevuti durante la
// programmazione la struttura è :*123#

int cnt_toni_rx; // contatore dei toni ricevuti in programmazione


int trasmetti_prossimo_simbolo; // =1 indica che posso trasmettere il prossimo simbolo DTMF

char simbolo; // contiene il valore dell'ultimo simbolo letto
int ricevuto_nuovo_simbolo; // =1 quando ho ricevuto un nuovo simbolo
//////////////////////////////////////////////////////////////////////////////////////////////


void Write_bits(int dato){

if (bit_test(dato,0)==1){output_high(DTMF_D0);}
else {output_low(DTMF_D0);}

if (bit_test(dato,1)==1){output_high(DTMF_D1);}
else {output_low(DTMF_D1);}

if (bit_test(dato,2)==1){output_high(DTMF_D2);}
else {output_low(DTMF_D2);}

if (bit_test(dato,3)==1){output_high(DTMF_D3);}
else {output_low(DTMF_D3);}

}

//////////////////////////////////////////////////////////////////////////////////////////////
void Write_Data_Register(int temp){
output_low(DTMF_CS);
output_low(DTMF_RSO);
output_low(DTMF_WR);
output_high(DTMF_RD);
Write_bits(temp);
output_high(DTMF_CS);
delay_us(10);
}
//////////////////////////////////////////////////////////////////////////////////////////////
int Read_Data_Register(void){
int temp;

output_high(DTMF_RSO);
output_low(DTMF_CS);
output_low(DTMF_RD);
delay_us(10);
output_high(DTMF_RD);
output_high(DTMF_CS);
delay_us(10);
output_low(DTMF_RSO);
output_low(DTMF_CS);
output_low(DTMF_RD);
temp=input_D();
output_high(DTMF_RD);
output_high(DTMF_CS);
return(temp);
}
//////////////////////////////////////////////////////////////////////////////////////////////
void Write_Control_Register(int temp){
Write_bits(temp);
output_low(DTMF_CS);
output_high(DTMF_RSO);
output_high(DTMF_RD);
output_low(DTMF_WR);
output_high(DTMF_WR);
output_high(DTMF_CS);
delay_us(10);
}
//////////////////////////////////////////////////////////////////////////////////////////////
int Read_Status_Register(void){
int temp;

output_low(DTMF_CS);
output_high(DTMF_RSO);
output_high(DTMF_WR);
output_low(DTMF_RD);
output_high(DTMF_RD);
temp=input_D();
output_high(DTMF_CS);
delay_us(10);
return (temp);
}


//////////////////////////////////////////////////////////////////////////////////////////////
char decode_dtmf_tone(void){
int temp;
int32 temp1;
char simb[2];

temp=Read_Data_Register();

temp=temp>>4;
temp1=(int32)(temp);

if ((temp>0)&&(temp<=9))
{
itoa(temp,10,simb);
return (simb[0]);
}
if (temp==10){return('0');}
if (temp==11){return('*');}
if (temp==12){return('#');}
if (temp==13){return('A');}
if (temp==14){return('B');}
if (temp==15){return('C');}
if (temp==0) {return('D');}
}
//////////////////////////////////////////////////////////////////////////////////////////////
#int_ext
void isr_RB0(void){

// il pin IRQ è collegato all'interrupt esterno PIN_RB0
int status;
status=Read_Status_Register();


if (bit_test(status,0)==0){return;} // falsa segnalazione
else if (bit_test(status,1)==1)
{
// posso tramsettere il prossimo carattere dtmf in burst mode
trasmetti_prossimo_simbolo=1;
return;
}
else if (bit_test(status,2)==1)
{
// ho ricevuto un nuovo simbolo
ricevuto_nuovo_simbolo=1;
simbolo=decode_dtmf_tone();
output_high(DTMF_CS);
init_8889();
output_low(DTMF_CS);
return;
}


}

//////////////////////////////////////////////////////////////////////////////////////////////

void init_8889(void){
int dummy;
// sequenza di inizializzazione come da datasheet
output_high(DTMF_CS);
output_high(DTMF_WR);
output_high(DTMF_RD);
output_high(DTMF_RSO);
delay_ms(150);
dummy=Read_Status_Register();
Write_Control_Register(0b00000000);
Write_Control_Register(0b00000000);
Write_Control_Register(0b00001000);
Write_Control_Register(0b00000000);
dummy=Read_Status_Register();
//
// configurazione dei registri secondo le necessità del porgramma
//
// setup CRA Control Register A 1101
// il prossimo registro ad essere scritto è il B
// DTMF On
// IRQ On
// Tone Out Control On
Write_Control_Register(0b00001101);

// setup CRB Control Register B 0000
// (singol tone raw 0) Off
// Dual Tone On
// Test Off
// BURST On
Write_Control_Register(0b00000000);
output_low(DTMF_CS);
// seleziono l'interrupt sul fronte di discesa
#asm
bcf 0xFF1,6 // INTCON2,6
#endasm
enable_interrupts(int_ext);
}


//////////////////////////////////////////////////////////////////////////////////////////////

void tabella_dtmf(int tono){
int tono_binario;
int temp;
switch (tono){
case 48: // 0
tono_binario=0b00001010;
break;
case 49: // 1
tono_binario=0b00000001;
break;
case 50: // 2
tono_binario=0b00000010;
break;
case 51: // 3
tono_binario=0b00000011;
break;
case 52: // 4
tono_binario=0b00000100;
break;
case 53: // 5
tono_binario=0b00000101;
break;
case 54: // 6
tono_binario=0b00000110;
break;
case 55: // 7
tono_binario=0b00000111;
break;
case 56: // 8
tono_binario=0b00001000;
break;
case 57: // 9
tono_binario=0b00001001;
break;
case 42: // *
tono_binario=0b00001011;
break;
case 35: // #
tono_binario=0b00001100;
break;
case 65: // A
tono_binario=0b00001101;
break;
case 66: // B
tono_binario=0b00001110;
break;
case 67: // C
tono_binario=0b00001110;
break;
case 68: // D
tono_binario=0b00001111;
break;

}
output_low(DTMF_RSO);
output_low(DTMF_CS);
Write_bits(tono_binario);
output_low(DTMF_WR);
delay_us(10);
output_high(DTMF_WR);
output_high(DTMF_CS);
output_high(DTMF_RSO);
output_low(DTMF_CS);

Write_bits(0b00000101);
output_low(DTMF_WR);
delay_us(10);
output_high(DTMF_WR);

output_high(DTMF_CS);
delay_ms(150); //150
output_low(DTMF_CS);

Write_bits(0b00000100);
output_low(DTMF_WR);
delay_us(10);
output_high(DTMF_WR);

output_high(DTMF_CS);
temp=Read_Status_Register();
delay_ms(150); //150

}
void compose_dtmf_tone(void){
// la sequenza da trasmettere è nella stringa globale trasmetti_toni
int tono;
int lunghezza_stringa;
int i;

lunghezza_stringa=strlen(trasmetti_toni);
for (i=0;i<=lunghezza_stringa;i++)
{
tono=trasmetti_toni[i];
tabella_dtmf(tono);
}
}
foodwatch



Joined: 18 Apr 2006
Posts: 66

View user's profile Send private message Yahoo Messenger

DTMF Interface MT8889
PostPosted: Thu Sep 13, 2007 1:58 pm     Reply with quote

Does anybody have an English translation of this source code and its comments? Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 13, 2007 4:00 pm     Reply with quote

You can use an online translator, and have it translate the entire page.
http://babelfish.altavista.com/

Set it for Italian to English. Make sure to only have one "http://" at
the start of the URL.
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

DTMF transmission and generation
PostPosted: Tue Oct 30, 2007 12:37 pm     Reply with quote

Hello,

There is a reference to an external file timer.h. Where is that file located or can we have access to it somehow?

To everyone else that is looking for a chip to decode / transmit DTMF, I spent almost a day yesterday searching for older parts without success.

Motorola had the awesome MC145436 and they discontinued it in 1999. I contacted OKI Semiconductor, On Semiconductor, National Semiconductors, Analog Devices you name it and nobody seems to produce a DTMF detector/generator IC anymore as everything is now done through the host processor (DSP or whatever else). The only company that I know of that still produces such IC is Mitel (their semiconductor branch is called Zarlink) and the part I have is the MT8885 DTMF transceiver.

I found some broker company in the US that still has MC145436 IC's in stock (more than 50,000) but their asking price was 14.95$ each (they used to cost about 1.00$). They are taking advantage of the situation because that part is no longer available.

Anyhow, that company is Crestwood Technology Group 1-866-779-0807.

Benoit
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 30, 2007 1:48 pm     Reply with quote

Look at Holtek DTMF chips:
http://www.holtek.com/english/products/comm_2.htm
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Oct 30, 2007 2:14 pm     Reply with quote

Ah! I forgot about this company. I will see with them if they have any type of distributor.... and see if they plan in the near future to discontinue the DTMF products. Thanks.
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Wed Oct 31, 2007 8:35 pm     Reply with quote

So, has anybody used the code above? I've read the Zarlink documentation and closely looked and this guy's code and it makes sense. There's basically 3 functions to use: initialize, read tone and write string. These functions use all the other functions to access the internal registers of the 8885 (BTW, it's the same as the 8889).

I got an Italian colleague translate all the comments for me and everything makes lots of sense. However, there's no explanation as to how to use it although I've figured-out most of it. But has anybody ever had this chip working with a PIC and if so, can you share the MT8885 schematic part along with the code? If I get my code to work, I will paste it here. But in the mean time, if someone could help, it would be greatly appreciated.

Thanks
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Thu Dec 06, 2007 8:44 pm     Reply with quote

I finally got it to work. It works very well. The code above needs some modifications. It doesn't just work "out of the box" the way it is posted. It's close, but there's stuff missing.

To interface with a line which will be within the Bell Canada standards, you can obtain the MH88437 DAA (Data Access Arrangement) from Zarlink. This device connects directly to TIP and RING with very minimal parts (a few caps and a few resistors). Works straight out of the box with the caps and resistors. Has two outputs (loop current present, line ringing) and one input (hook-switch control). Has tone out and tone in to interface with the MT888x series DTMF out and DTMF in.
Dave_27



Joined: 01 Apr 2008
Posts: 2

View user's profile Send private message

PostPosted: Tue Apr 01, 2008 3:44 am     Reply with quote

We are trying control MT8889 via PIC, with software puts in this forum,
but doen't work very well, only send single TONE.
Could help me?
Thank you very much
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Apr 01, 2008 6:54 am     Reply with quote

Hello, in order to get this code working, you must ensure that PIC pin B0 (external interrupt) is active. Note that this forum seems to make all the code and comments out of alignment. You will have to realign the code.

Here it is...

The code below must be inserted in your main file:

// FROM HERE

// This code in your main before your "main" while loop:

InitializeMT8885(); // For MT8885
EnableDTMFReceiver(); // For MT8885
DisableDTMFTransmitter(); // For MT8885

// Then this code (also before the main while loop):

ext_int_edge( 0, H_TO_L ); // For MT8885
enable_interrupts( int_ext ); // For MT8885
enable_interrupts(GLOBAL);

// TO HERE


Below is RB0 interrupt routine code:

// FROM HERE

#int_ext
external_interrupt() // External interrupt on B0
{
iStatus = ReadStatusRegister(); // Read the status register. Cannot be read
// in the functions instead of iStatus as
// a single read of the register will clear
// the internal flags.

if( bit_test( iStatus, 0 ) == 0 ) // False interrupt detected - bit 0 of the
{ // status register should be 1 when a DTMF
}
else
{
/*
if( bit_test( iStatus, 1 ) == 1 ) // Transmit the next character in BURST mode
{
bFlagTxNextDigit = 1;
}
*/

if( bit_test( iStatus, 2 ) == 1 ) // Received a new digit
{
bFlagRxNextDigit = 1;
iStatus = ReadStatusRegister(); // Read the status register.

while( bit_test( iStatus, 3 ) == 0 ) // Check the /DELAYED_STEERING bit in STATUS until it goes to 0
// which is the pause after the detection of a DTMF is detected
// considered and valid.
{
iStatus = ReadStatusRegister(); // Read the status register.
}
}
}
}

// TO HERE

Note that the iStatus variable is a global variable.


Below are the prototype lines for the functions to put in your header file:

// FROM HERE

void InitializeMT8885(void);
char RetrieveDTMFDigit( void );
void DialDTMFString( char *sDTMFString, unsigned int uiCount );
void TransmitTone( char cDTMFTone );

int ReadRXDataRegister( void );
void WriteControlRegister( int temp );
int ReadStatusRegister( void );
void SetDataBits( int data );

void EnableDTMFReceiver( void );
void DisableDTMFReceiver( void );
void EnableDTMFTransmitter( void );
void DisableDTMFTransmitter( void );

// TO HERE



Below are the #define's to put in your header file (for pin definition):

// FROM HERE:

// Pin definition for MT8885
#define DATA_D0 PIN_C0 // Data 0
#define DATA_D1 PIN_C1 // Data 1
#define DATA_D2 PIN_C2 // Data 2
#define DATA_D3 PIN_C3 // Data 3


#define DATA_iIRQ PIN_B0 // Interrupt Request
#define DATA_iCS PIN_A4 // Chip Select
#define DATA_DIRECTION PIN_A5 // R/!W / !WR Write
#define DATA_STROBE PIN_E0 // DS/!RD Read
#define DATA_RS PIN_E1 // RS0 Register Select

// TO HERE


Below are the exact lines of code in my .C file that I am using at the moment. Note that the DialDTMFString function is commented-out. I don't remember if it worked or not as I simply dial a single DTMF at a time.

//******************************************************************************
//** Initialize the 8889 DTMF transceiver registers.
//******************************************************************************
void InitializeMT8885(void)
{
ReadStatusRegister(); // Read STATUS REGISTER to clear flags.

WriteControlRegister( 0b00000000 );
WriteControlRegister( 0b00000000 );
WriteControlRegister( 0b00001000 );
WriteControlRegister( 0b00000000 );

ReadStatusRegister(); // Read STATUS REGISTER to clear flags.

WriteControlRegister( 0b00001101 ); // Configure CRA
// 0bxxxxxxx1 = TOUT - Tone OUT enabled
// 0bxxxxxx0x = CP/*DTMF - DTMF mode selected
// 0bxxxxx1xx = IRQ - IRQ enabled when DTMF detected
// 0bxxxx1xxx = RSEL - Next write cycle will write to CRB

WriteControlRegister( 0b00000000 ); // Configure CRB
// 0bxxxxxxx0 = *BURST - Burst mode enabled
// 0bxxxxxx0x = *RxEN - DTMF/CP detectors enabled
// 0bxxxxx0xx = S/*D - DTMF mode selected (as opposed to single tone)
// 0bxxxx0xxx = C/*R - Not used as this is for S/*D when in single tone mode
}

//******************************************************************************
//** Decode the read DTMF digit and convert it to a valid DTMF ASCII value.
//******************************************************************************
char RetrieveDTMFDigit( void )
{
int iTempData;
char sDigit[2];

iTempData = ReadRXDataRegister(); // Get the received data.

if(( iTempData > 0 ) && ( iTempData <= 9 )) // Check to see if the data is 1 < data < 9
{
sprintf( sDigit, "%d", iTempData ); // Convert the digit to a character
return( sDigit[0] );
}
else
{
switch( iTempData )
{
case 10: return( '0' ); break;
case 11: return( '*' ); break;
case 12: return( '#' ); break;
case 13: return( 'A' ); break;
case 14: return( 'B' ); break;
case 15: return( 'C' ); break;
case 0: return( 'D' ); break;
}
}
}

//******************************************************************************
//** Enables the MT8885's DTMF receiver
//******************************************************************************
void EnableDTMFReceiver( void )
{
WriteControlRegister( 0b00001101 ); // Configure CRA
// 0bxxxxxxx1 = TOUT - Tone OUT enabled
// 0bxxxxxx0x = CP/*DTMF - DTMF mode selected
// 0bxxxxx1xx = IRQ - IRQ enabled when DTMF detected
// 0bxxxx1xxx = RSEL - Next write cycle will write to CRB


WriteControlRegister( 0b00000000 ); // Configure CRB
// 0bxxxxxxx0 = *BURST - Burst mode enabled
// 0bxxxxxx0x = *RxEN - DTMF/CP detectors enabled
// 0bxxxxx0xx = S/*D - DTMF mode selected (as opposed to single tone)
// 0bxxxx0xxx = C/*R - Not used as this is for S/*D when in single tone mode
}

//******************************************************************************
//** Disables the MT8885's DTMF receiver
//******************************************************************************
void DisableDTMFReceiver( void )
{
WriteControlRegister( 0b00001101 ); // Configure CRA
// 0bxxxxxxx1 = TOUT - Tone OUT enabled
// 0bxxxxxx0x = CP/*DTMF - DTMF mode selected
// 0bxxxxx1xx = IRQ - IRQ enabled when DTMF detected
// 0bxxxx1xxx = RSEL - Next write cycle will write to CRB


WriteControlRegister( 0b00000010 ); // Configure CRB
// 0bxxxxxxx0 = *BURST - Burst mode enabled
// 0bxxxxxx1x = *RxEN - DTMF/CP detectors disabled
// 0bxxxxx0xx = S/*D - DTMF mode selected (as opposed to single tone)
// 0bxxxx0xxx = C/*R - Not used as this is for S/*D when in single tone mode

}

//******************************************************************************
//** Enables the MT8885's DTMF receiver
//******************************************************************************
void EnableDTMFTransmitter( void )
{
WriteControlRegister( 0b00000101 ); // Configure CRA
// 0bxxxxxxx1 = TOUT - Tone OUT enabled
// 0bxxxxxx0x = CP/*DTMF - DTMF mode selected
// 0bxxxxx1xx = IRQ - IRQ enabled when DTMF detected
// 0bxxxx0xxx = RSEL - Next write cycle will write to CRA
}

//******************************************************************************
//** Disables the MT8885's DTMF receiver
//******************************************************************************
void DisableDTMFTransmitter( void )
{
WriteControlRegister( 0b00000100 ); // Configure CRA
// 0bxxxxxxx0 = TOUT - Tone OUT disabled
// 0bxxxxxx0x = CP/*DTMF - DTMF mode selected
// 0bxxxxx1xx = IRQ - IRQ enabled when DTMF detected
// 0bxxxx0xxx = RSEL - Next write cycle will write to CRA
}


//******************************************************************************
//** Dials the DTMF string sDTMFString
//******************************************************************************
/*
void DialDTMFString( char *sDTMFString, unsigned int uiCount )
{
unsigned int uiTone;
unsigned int uiCounter = 0;
unsigned int uiPosition = 0;
short bFlagString = false;

//disable_interrupts( INT_EXT );
EnableDTMFTransmitter();
DisableDTMFReceiver();

if( uiCount == 0 ) // A string, not a single character, needs to be played
{
uiCount = strlen( sDTMFString ); // Get the total string length to initialize the counter
bFlagString = true;
}

while( uiCounter < uiCount )
{
TransmitTone( sDTMFString[uiPosition] ); // Transmit that tone
delay_ms( 100 );

if( bFlagString == true )
{
uiPosition ++;
}

uiCounter ++;
}

EnableDTMFReceiver();
DisableDTMFTransmitter();
//enable_interrupts( INT_EXT );
}
*/

//******************************************************************************
//** Converts 'tone' to a binary value 'binary_tone' and sends it.
//******************************************************************************
void TransmitTone( char cDTMFTone )
{
int iBinaryValue;

//disable_interrupts( INT_EXT );
EnableDTMFTransmitter();
DisableDTMFReceiver();

switch( cDTMFTone )
{
case '0': iBinaryValue = 0b00001010; break;
case '1': iBinaryValue = 0b00000001; break;
case '2': iBinaryValue = 0b00000010; break;
case '3': iBinaryValue = 0b00000011; break;
case '4': iBinaryValue = 0b00000100; break;
case '5': iBinaryValue = 0b00000101; break;
case '6': iBinaryValue = 0b00000110; break;
case '7': iBinaryValue = 0b00000111; break;
case '8': iBinaryValue = 0b00001000; break;
case '9': iBinaryValue = 0b00001001; break;
case '*': iBinaryValue = 0b00001011; break;
case '#': iBinaryValue = 0b00001100; break;
case 'A': iBinaryValue = 0b00001101; break;
case 'B': iBinaryValue = 0b00001110; break;
case 'C': iBinaryValue = 0b00001111; break;
case 'D': iBinaryValue = 0b00000000; break;
}

output_high( DATA_iCS );
output_low( DATA_STROBE );

SetDataBits( iBinaryValue );

output_low( DATA_RS );
output_bit( DATA_DIRECTION, WRITE );

output_low( DATA_iCS );
output_high( DATA_STROBE );
delay_us( 100 );
output_low( DATA_STROBE );
output_high( DATA_iCS );

delay_ms( 200 );

EnableDTMFReceiver();
DisableDTMFTransmitter();
//enable_interrupts( INT_EXT );

}



//******************************************************************************
//** ReadRXDataRegister: Read a value from the receive data register.
//******************************************************************************
int ReadRXDataRegister( void )
{
int temp = 0;

output_high( DATA_iCS );
output_low( DATA_STROBE );

output_bit( DATA_DIRECTION, READ );
output_low( DATA_RS );

delay_us( 100 );
output_low( DATA_iCS );
delay_us( 100 );

output_high( DATA_STROBE );
delay_us( 100 );
temp = (( input( DATA_D3 ) * 8 ) + ( input( DATA_D2 ) * 4 ) + ( input( DATA_D1 ) * 2 ) + ( input( DATA_D0 ) * 1 ));

output_low( DATA_STROBE );
output_high( DATA_iCS );

return( temp );

}

//******************************************************************************
//** ReadStatusRegister: Read a value from the Status register.
//******************************************************************************
int ReadStatusRegister( void )
{
int temp = 0;

output_high( DATA_iCS );
output_low( DATA_STROBE );

output_bit( DATA_DIRECTION, READ );
output_high( DATA_RS );

delay_us( 100 );
output_low( DATA_iCS );
delay_us( 100 );

output_high( DATA_STROBE );
delay_us( 100 );
temp = (( input( DATA_D3 ) * 8 ) + ( input( DATA_D2 ) * 4 ) + ( input( DATA_D1 ) * 2 ) + ( input( DATA_D0 ) * 1 ));

output_low( DATA_STROBE );
output_high( DATA_iCS );


delay_us( 100 );

return( temp );
}

//******************************************************************************
//** WriteControlRegister: Write a value to the control register.
//******************************************************************************
void WriteControlRegister( int temp )
{
output_high( DATA_iCS );
output_low( DATA_STROBE );

SetDataBits( temp ); // Set the state of each DATA bit based on binary 'temp'.
delay_us( 100 );
output_high( DATA_RS );
output_bit( DATA_DIRECTION, WRITE );
delay_us( 100 );

output_low( DATA_iCS );
delay_us( 100 );
output_high( DATA_STROBE );
delay_us( 100 );
output_low( DATA_STROBE );
output_high( DATA_iCS );
}

//******************************************************************************
//** SetDataBits: Compares a specific bit in the 'data' byte to see if it is
//** SET (1) or not (0).
//******************************************************************************
void SetDataBits( int data )
{
// Check if data bit 0 is set (1) or not (0).
if( bit_test( data, 0 ) == 1 )
{
output_high( DATA_D0 );
}
else
{
output_low( DATA_D0 );
}

if( bit_test( data, 1 ) == 1 )
{
output_high( DATA_D1 );
}
else
{
output_low( DATA_D1 );
}

if( bit_test( data, 2 ) == 1 )
{
output_high( DATA_D2 );
}
else
{
output_low( DATA_D2 );
}

if( bit_test ( data, 3 ) == 1 )
{
output_high( DATA_D3 );
}
else
{
output_low( DATA_D3 );
}
}

How this code works is simple: once a valid DTMF is detected by the MT8885, it will toggle its IRQ pin, which will toggle the PIC's RB0 interrupt pin, which will jump to the RB0 interrupt routine and set the bFlagRXNextDigit flag to 1 (this flag must be declared in your header file as short bFlagRXextDigit = 0).

In your main file, your main while loop will be very short:

while( 1 )
{
if( bFlagRxNextDigit == 1 )
{
bFlagRxNextDigit = 0;
DTMFStateMachine();
}
}

When the while loop runs, it only checks the bFlagRxNextDigit flag and when that flag is set to '1', it sets it back to 0 and runs the DTMFStateMachine function. This function does whatever you want it to do when a valid DTMF is detected, however, you must ensure that the following line is in the function:

cDigit = RetrieveDTMFDigit();

I didn't put my actual function in here as it is proprietary to me, but the important thing is the line above to retrive the detected DTMF digit.

Hope this helps. If you interface this to a phone line, I strongly suggest you get the MH88437 DAA (Direct Access Arrangement) from MITEL as it can be directly connected to TIP and RING plus is also has all the amplifiers for interfacing with the MT8885 for incoming and outgoing audio. Unfortunately I cannot send you my full source code but what I provided here will get you started. Note that I originally took this code from the italian guy's original posting and modified it as it didn't work. I also added some stuff.

Good Luck!
Dave_27



Joined: 01 Apr 2008
Posts: 2

View user's profile Send private message

PostPosted: Wed Apr 02, 2008 5:47 am     Reply with quote

Dear benoitstjean,

Thanks for your DRIVER code, we can call a different country without any problem, it's a fantastic DRIVER.

Thank you again and congratulations for this job.
kamakshi.vairagi



Joined: 12 Apr 2009
Posts: 3

View user's profile Send private message Send e-mail

Dtmf driver qry
PostPosted: Sun Apr 12, 2009 11:08 pm     Reply with quote

Hello friends,
I have to implement DTMF transceiver driver my IC is MT88L85(Zarlink).
I already have written driver for it by taking help from the code given by an indian guy. But facing one major problem.

My problem is during transmission IC should give an interrrupt after valid Dtmf tone which is successful but proper DTMF tone generation is not successful.
Friends its very urgent can u please help me out.
kamakshi.vairagi



Joined: 12 Apr 2009
Posts: 3

View user's profile Send private message Send e-mail

MT88L85 driver Query
PostPosted: Tue Apr 14, 2009 5:28 am     Reply with quote

Hello Friend,
I am posting my code which is not working properly..can u plz help me out where i am goin wrong..

I have implemented only transmitter part of this IC.
I have interfaced with 8051 family..

unsigned int iCounter=0;
bit bInt1=0;
unsigned char cTempBuff[20];
void main(void)
{
PortPin_Init() ;
Init_MT88L85() ; //Initialze transreciver
strcpy(cTempBuff,"123456789") ;
while(1)
{

bInt1=0 ;
Dial_No() ;
while(!bInt1) ;
}
}

void PortPin_Init(void)
{
P0 = 0xFF ;
P1 = 0xFF ;
P2 = 0xFF ;
P0 = 0xFF ;

RELAYCTRL = 0 ;
MUTEIN = 0 ;
LED = 0 ;
CS = 0 ;
PWDN = 0 ;
S1 = 0 ;
S2 = 0 ;
S3 = 0 ;
TXD = 1 ;
IRQ = 1 ;
}

void Init_MT88L85(void)
{

RS0=1 ; WR=1; RD=0; //Read Status Register ;

RS0=1 ; WR=0; RD=1; D0=0 ; D1=0 ; D2=0 ; D3=0 ;
Ms_Delay(10);

RS0=1; WR=0; RD=1; D0=0; D1=0; D2=0; D3=0;
Ms_Delay(10);


RS0=1; WR=0; RD=1; D0=0; D1=0; D2=0; D3=1;
Ms_Delay(10);

RS0=1; WR=0; RD=1; D0=0; D1=0; D2=0; D3=0;
Ms_Delay(10);

RS0 = 1 ; WR = 1; RD = 0;
Ms_Delay(10);

}

void Dial_No(void)
{
unsigned char cTemp ;
unsigned char cCount ;

RS0=0; WR=0; RD=1; //Write to xmit data reg
cTemp = cTempBuff[iCounter] ;
cTemp = cTemp & 0x0F ;
P0 = _cror_(cTemp,4) ;
Ms_Delay(100) ;
}

void ext0(void) interrupt 0 using 3
{

bInt1 = 1 ;
iCounter++ ;

}
benoitstjean



Joined: 30 Oct 2007
Posts: 542
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Thu Apr 16, 2009 9:08 am     Reply with quote

Sorry, I can't help you. The code I posted on this board was specific to a PIC18F4620 and an MT8885 DTMF transceiver. It took me weeks to get it to work properly and has now been working for over a year. If you are not using the same ICs (especially if you're not using an MT8885), then I can't help you as I have no clue how the other ones work or behave. If you look at the comments of DAVE_27, he says my code worked, so, there's the proof that it works.
kamakshi.vairagi



Joined: 12 Apr 2009
Posts: 3

View user's profile Send private message Send e-mail

MT8885 driver
PostPosted: Thu Apr 16, 2009 10:16 pm     Reply with quote

Thanks for your reply.
But my dear friend IC which I am using is MT8885 only but low voltage package i.e. MT88L85, which is exactly the same only controller is diff.
I tried your code I am getting proper interrupts but after getting interrupt dtmf tone should be generated which is not being generated.
And in your code can you give me the lines where you are checking for an interrupt ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group