Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Thread Closed: Issue successfully resolved

???
06/23/03 13:08
Read: times


 
#49076 - RE: Rob Redding and Michael Karas
Responding to: ???'s previous message
I have re-written the code so that it is working (on timer2 of an 8052 at 24mhz...
its been tested using an R2R network on P1 fed into an opamp...the ouptut of which could be connected to your 600ohm transformer.




#include <reg52.h>
#include <stdio.h> 
#include <stdlib.h>

#define SAMPLE_RATE 10000		 		 //10 kHz sample rate
#define MAX_PHASE_ACCUM 0x10000		 //16-bit phase accumulator overflow value
#define DURATION_100MS 1000				 //100 ms tone duration
/* Enumeration to identify DTMF characters */
bit dtmf_done; // end of tone flag
enum DTMF_CHAR
{
   DTMF_0,       // digit 0
   DTMF_1,       // digit 1
   DTMF_2,       // digit 2
   DTMF_3,       // digit 3
   DTMF_4,       // digit 4
   DTMF_5,       // digit 5
   DTMF_6,       // digit 6
   DTMF_7,       // digit 7
   DTMF_8,       // digit 8
   DTMF_9,       // digit 9
   DTMF_STAR,    // char *
   DTMF_POUND,   // char #
   DTMF_A,       // char A
   DTMF_B,       // char B
   DTMF_C,       // char C
   DTMF_D        // char D
};

/* Table of sine waveform points. These are unsigned integers that vary */
/* around 128 and range as high as 255 and as low as 1. Values in this  */
/* range are suitable for an 8-bit PWM register or unipolar DAC. For    */
/* a bipolar DAC use signed values in whatever format works best. Bear  */
/* in mind that you may need to average the two tones' sample values    */
/* together to keep from overranging the DAC with the sum of both       */
/* signals.                                                             */
/* The number of entries in this table corresponds to the number of     */
/* bits of the phase accumulator used to index it.                      */

unsigned char code sine_table[] =
{
   0x80, 0x83, 0x86, 0x89, 0x8C, 0x8F, 0x92, 0x95,
   0x98, 0x9B, 0x9E, 0xA1, 0xA4, 0xA7, 0xAA, 0xAD,
   0xB0, 0xB3, 0xB6, 0xB9, 0xBB, 0xBE, 0xC1, 0xC3,
   0xC6, 0xC9, 0xCB, 0xCE, 0xD0, 0xD2, 0xD5, 0xD7,
   0xD9, 0xDB, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE7,
   0xE9, 0xEB, 0xEC, 0xEE, 0xF0, 0xF1, 0xF2, 0xF4,
   0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFB,
   0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
   0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD,
   0xFC, 0xFB, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6,
   0xF5, 0xF4, 0xF2, 0xF1, 0xF0, 0xEE, 0xEC, 0xEB,
   0xE9, 0xE7, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDB,
   0xD9, 0xD7, 0xD5, 0xD2, 0xD0, 0xCE, 0xCB, 0xC9,
   0xC6, 0xC3, 0xC1, 0xBE, 0xBB, 0xB9, 0xB6, 0xB3,
   0xB0, 0xAD, 0xAA, 0xA7, 0xA4, 0xA1, 0x9E, 0x9B,
   0x98, 0x95, 0x92, 0x8F, 0x8C, 0x89, 0x86, 0x83,
   0x80, 0x7C, 0x79, 0x76, 0x73, 0x70, 0x6D, 0x6A,
   0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52,
   0x4F, 0x4C, 0x49, 0x46, 0x44, 0x41, 0x3E, 0x3C,
   0x39, 0x36, 0x34, 0x31, 0x2F, 0x2D, 0x2A, 0x28,
   0x26, 0x24, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x18,
   0x16, 0x14, 0x13, 0x11, 0x0F, 0x0E, 0x0D, 0x0B,
   0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x04,
   0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
   0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
   0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
   0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x11, 0x13, 0x14,
   0x16, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x24,
   0x26, 0x28, 0x2A, 0x2D, 0x2F, 0x31, 0x34, 0x36,
   0x39, 0x3C, 0x3E, 0x41, 0x44, 0x46, 0x49, 0x4C,
   0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64,
   0x67, 0x6A, 0x6D, 0x70, 0x73, 0x76, 0x79, 0x7C
};

/* Tone pairs that correspond to DTMF characters in enumeration above */
struct DTMF_FREQ
{
   unsigned short low_tone;
   unsigned short high_tone;
} idata dtmf_freq[] =
{
   941, 1336,   //digit 0
   697, 1209,   //digit 1
   697, 1336,   //digit 2
   697, 1477,   //digit 3
   770, 1209,   //digit 4
   770, 1336,   //digit 5
   770, 1477,   //digit 6
   852, 1209,   //digit 7
   852, 1336,   //digit 8
   852, 1477,   //digit 9
   941, 1209,   //char *
   941, 1477,   //char #
   697, 1633,   //char A
   770, 1633,   //char B
   852, 1633,   //char C
   941, 1633    //char D
};

/* Structure containing phase accumulators and phase increment */
/* values for the desired tone pair. Once this structure is    */
/* initialized for a given DTMF digit or character, it can be  */
/* used to keep generating tones indefinitely.                 */
struct DTMF_TONE
{
   unsigned short low_phase_accum;   //low tone phase accumulator
   unsigned short high_phase_accum;  //high tone phase accumulator
   unsigned short low_phase_incr;    //low tone phase increment
   unsigned short high_phase_incr;   //high tone phase increment
   unsigned short duration;   		 //tone duration
} dtmf_tone;

/* Initialize DTMF tone structure with new character */
void 
new_tone(enum DTMF_CHAR dtmf_char)
{
   unsigned long temp_increment;

   /* Zeroing phase accumulators makes both sine waves start at zero. */
   /* If you want to transition smoothly from one tone to the next    */
   /* without the glitch caused by dropping to zero at the end of the */
   /* previous tone, don't clear the phase accumulators.              */
   dtmf_tone.low_phase_accum = 0;
   dtmf_tone.high_phase_accum = 0;

   /* Calculate phase increments for low and high tones based on   */
   /* frequencies of each tone, phase accumulator size, and        */
   /* sample rate:                                                 */
   /* phase increment = frequency * accumulator size / sample rate */

   /* Use a long temporary because the max phase accumulator size  */
   /* is already 16 bits.                                          */
   temp_increment = dtmf_freq[dtmf_char].low_tone * MAX_PHASE_ACCUM;
   dtmf_tone.low_phase_incr = temp_increment / SAMPLE_RATE;
   temp_increment = dtmf_freq[dtmf_char].high_tone * MAX_PHASE_ACCUM;
   dtmf_tone.high_phase_incr = temp_increment / SAMPLE_RATE;
}

/* Get the next sample of the combined tone signal for the most */
/* recent DTMF character. Ordinarily this would be executed in  */
/* a 10 kHz periodic interrupt and the returned value would be  */
/* written to a DAC.                                            */
void
next_dtmf_sample(void)
{
   unsigned short temp_sample;   //for combining both tones' sample values

   /* Advance the low tone phase accumulator */
   dtmf_tone.low_phase_accum += dtmf_tone.low_phase_incr;

   /* Look up the next sample of the sine wave using the upper 8 bits */
   /* of the phase accumulator                                        */
   temp_sample = sine_table[dtmf_tone.low_phase_accum >> 8];

   /* Now repeat the process for the high tone, adding the sample     */
   /* value to that for the low tone                                  */
   dtmf_tone.high_phase_accum += dtmf_tone.high_phase_incr;
   temp_sample += sine_table[dtmf_tone.high_phase_accum >> 8];

   /* Average the two sample values so it won't overrange an 8-bit DAC */
   P1=(temp_sample / 2);
}

void 
Timer2(void) interrupt 5 using 2  { 
   /* 10 kHz sample rate, timer2 interrupt 10k interval on 24mhz 12 clocker
      Auto reload 65535 - 200 =65335  RCAP2H=0xff RCAP2L=0x37
	  This routine takes 43 cycles to complete ,so could be run at 1mips*/
	  
   TF2= 0; // Clear INTERRUPT FLAG
   dtmf_tone.duration++;
   /* Check if tone has been output for required duration */ 
   if(dtmf_tone.duration>DURATION_100MS){
   	ET2= 0; //disable timer2 - tone ended.
   	TR2= 0;
   	dtmf_done=1;
	P1=0x128;} // reset port for Pseudo zero output
   	
   /* Get the next sample of the combined tone signal */
   next_dtmf_sample();
}

void 
main(void)
{
	/* setup timer hardware and interrupt */
	
	
 	RCAP2H=0xff;
 	RCAP2L=0x37; 
       EA    = 1; // Enable all interrupts
	/* Main Example Routine Loop	 */
 	do{
   	
		/* Send 1st tone */
   		dtmf_tone.duration=0;
   		dtmf_done=0;
   		new_tone(DTMF_1);
    	       TH2=0xff;   //Ensure clean first pass
 		TL2=0x37; 
   		TR2	= 1;
		ET2 = 1;// Enable Timer 2 interrupts
   		while(!dtmf_done); // wait for tone duration to end
 
	  	/* Send 2nd tone */
		dtmf_tone.duration=0;
   		dtmf_done=0;
   		new_tone(DTMF_2);
    	       TH2=0xff;   //Ensure clean first pass
 		TL2=0x37; 
   		TR2	= 1;
		ET2 = 1;// Enable Timer 2 interrupts
 		while(!dtmf_done); // wait for tone duration to end
   }while(1);
}


List of 16 messages in thread
TopicAuthorDate
DTMF from 8052 pin            01/01/70 00:00      
   RE: DTMF from 8052 pin            01/01/70 00:00      
   RE: DTMF from 8052 pin            01/01/70 00:00      
   RE: DTMF from 8052 pin            01/01/70 00:00      
   RE:Rob Redding            01/01/70 00:00      
      RE: RE:Rob Redding            01/01/70 00:00      
         RE: Rob Redding and Michael Karas            01/01/70 00:00      
            RE: Rob Redding and Michael Karas            01/01/70 00:00      
            RE: Rob Redding and Michael Karas            01/01/70 00:00      
               RE: Rob Redding and Michael Karas            01/01/70 00:00      
                  RE: Rob Redding and Michael Karas            01/01/70 00:00      
                     RE: Rob Redding and Michael Karas            01/01/70 00:00      
      RE: RE:Rob Redding            01/01/70 00:00      
   RE: DTMF generation from ADuc812            01/01/70 00:00      
   RE: DTMF generation from ADuc812            01/01/70 00:00      
      RE: DTMF generation from ADuc812            01/01/70 00:00      

Back to Subject List