DTMF

From Wiki
Jump to navigationJump to search

Google

PIC Implementations

Encoder Chips

  • TC35219F (used in EHM-57)
  • TP5089 (Jameco, keypad)
  • TP5088 (Obsolete, binary)
  • NTE1690
  • UM91531
  • HT9200B

PIC Code

// DTMF.C

#define  T2CON    0x12
#define  TMR2ON   0x02
#define  RP0      0x05

struct DTMF_Type
{
   unsigned int HighFreq_Pointer;// Pointer for high frequency band, points to sinusoidal pattern
   unsigned int LowFreq_Pointer; // Pointer for low  frequency band, points to sinusoidal pattern
   unsigned int HighFreq_Offset; // Offset necessary to give the wave frequency to HF Pointer
   unsigned int LowFreq_Offset;  // Offset necessary to give the wave frequency to LF Pointer
   long     int Tone_Duration;   // Tone duration
   short    int Active;
} DTMF_Generator;

// The keypad has the tones as follows:
//
//                1209  1336  1477  1633
//                  1     2     3     A   697
//                  4     5     6     B   770
//                  7     8     9     C   852
//                  *     0     #     D   941
//
// To assembly the sinusoidal wave form with these frequencies
// from the sinusoidal pattern table Sine, we step an offset a fixed
// time, as follow below:
//
//                   697 Hz -> Offset 09
//                   770 Hz -> Offset 10
//                   852 Hz -> Offset 11
//                   941 Hz -> Offset 12
//                  1209 Hz -> Offset 15
//                  1336 Hz -> Offset 17
//                  1477 Hz -> Offset 19
//                  1633 Hz -> Offset 21

#define  O_0697  9
#define  O_0770 10
#define  O_0852 11
#define  O_0941 12
#define  O_1209 15
#define  O_1336 17
#define  O_1477 19
#define  O_1633 21

const unsigned int Offsets [32]={O_0941,O_1336, // '0' -> 941 and 1336
                                 O_0697,O_1209, // '1' -> 697 and 1209
                                 O_0697,O_1336, // '2' -> 697 and 1336
                                 O_0697,O_1477, // '3' -> 697 and 1477
                                 O_0770,O_1209, // '4' -> 770 and 1209
                                 O_0770,O_1336, // '5' -> 770 and 1336
                                 O_0770,O_1477, // '6' -> 770 and 1477
                                 O_0852,O_1209, // '7' -> 852 and 1209
                                 O_0852,O_1336, // '8' -> 852 and 1336
                                 O_0852,O_1477, // '9' -> 852 and 1477
                                 O_0697,O_1633, // 'A' -> 697 and 1633
                                 O_0770,O_1633, // 'B' -> 770 and 1633
                                 O_0852,O_1633, // 'C' -> 852 and 1633
                                 O_0941,O_1633, // 'D' -> 941 and 1633
                                 O_0941,O_1209, // 'E' -> 941 and 1209
                                 O_0941,O_1477};// 'F' -> 941 and 1477

const unsigned int Sine [256]=
{ 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86,
  88, 89, 91, 92, 93, 95, 96, 97, 99,100,101,103,104,105,106,107,
 108,109,111,112,113,114,115,115,116,117,118,119,120,120,121,122,
 122,123,123,124,124,125,125,125,126,126,126,127,127,127,127,127,
 127,127,127,127,127,127,126,126,126,125,125,125,124,124,123,123,
 122,122,121,120,120,119,118,117,116,115,115,114,113,112,111,109,
 108,107,106,105,104,103,101,100, 99, 97, 96, 95, 93, 92, 91, 89,
  88, 86, 85, 83, 82, 80, 79, 77, 76, 74, 73, 71, 70, 68, 67, 65,
  64, 62, 60, 59, 57, 56, 54, 53, 51, 50, 48, 47, 45, 44, 42, 41,
  39, 38, 36, 35, 34, 32, 31, 30, 28, 27, 26, 24, 23, 22, 21, 20,
  19, 18, 16, 15, 14, 13, 12, 12, 11, 10,  9,  8,  7,  7,  6,  5,
   5,  4,  4,  3,  3,  2,  2,  2,  1,  1,  1,  0,  0,  0,  0,  0,
   0,  0,  0,  0,  0,  0,  1,  1,  1,  2,  2,  2,  3,  3,  4,  4,
   5,  5,  6,  7,  7,  8,  9, 10, 11, 12, 12, 13, 14, 15, 16, 18,
  19, 20, 21, 22, 23, 24, 26, 27, 28, 30, 31, 32, 34, 35, 36, 38,
  39, 41, 42, 44, 45, 47, 48, 50, 51, 53, 54, 56, 57, 59, 60, 62};

void DTMF_ExecuteTone (unsigned int tone);
void DTMF_Setup (void);
void DTMF_DutyUpdate (void);

void DTMF_ExecuteTone (unsigned int tone)
{
   DTMF_Generator.HighFreq_Offset = Offsets [2*tone];
   DTMF_Generator.LowFreq_Offset  = Offsets [2*tone+1];

   DTMF_Generator.HighFreq_Pointer = 0;
   DTMF_Generator.LowFreq_Pointer  = 0;

   DTMF_Generator.Tone_Duration = 0;

   enable_interrupts (INT_TIMER2);

   setup_ccp2 (CCP_PWM_PLUS_2);  // Configures PWM with 2 Duty LSBs to B'10' (mean value).
   set_pwm2_duty (127>>2);       // Set duty initial value to 0 (Duty 50%).
   set_timer2 (0);               // Clears Timer 2.
   setup_timer_2 (T2_DIV_BY_1, 0x3F, 4);  // Configures Timer 2 to 78,12 KHz.

   return;
}

void DTMF_DutyUpdate (void)
{
   set_pwm2_duty ((Sine[DTMF_Generator.HighFreq_Pointer]>>2)+
                  (Sine[DTMF_Generator.LowFreq_Pointer ]>>2));

   DTMF_Generator.HighFreq_Pointer += DTMF_Generator.HighFreq_Offset;
   DTMF_Generator.LowFreq_Pointer  += DTMF_Generator.LowFreq_Offset;

   return;
}

void DTMF_TurnOff (void)
{
   disable_interrupts (INT_TIMER2);
#asm
   bcf   STATUS,RP0
   bcf   T2CON,TMR2ON
#endasm
   return;
}