Download a Free VPN Appliance for your home network!

DTMF Remote control – A software DTMF decoder for PIC 16F87X

©2003 Radu Constantinescu

This project is a simple DTMF Remote control. The DTMF detector is integrated in software. All the logic requested to receive and decode DTMF Commands over the phone line is integrated in the 16F877 chip, only few external components are used. As soon as possible I plan to switch to a 16F629-20 Pic and like that will be a Single Chip DTMF Remote Control. The debug possibilities of 16F877 made him a good choice in order to develop the application. Once the development is finished the downsize to a smaller Pic will reduce the cost and integrate the Comparator to.

The Line interface is designed to share the Phone Line with an Answering Machine; no supplementary Phone line is requested.

The Remote control has 4 Outputs capable to drive 10 Amps at 120VAC and accepts three simple commands – Set/Reset Output, Check Output Status and Change Password via DTMF digits. The commands are:

#Pass#1-4#0-1## - Ser output 1-4 to 0-ON, 1-OFF. The result is Beep on success.

#Pass#1-4## - Verify output 1-4, the result is Beep for Output on and Buzz for output off.

#Pass#NewPass#NewPass## - Change Password, where password is a 10 DIGIT string. The result is Beep on success. The default password is 1234567890.

The Output Values and the Password are backed up in EEPROM.


The hardware consists in the phone line interface and the relay drivers.

All the logical functions are integrated in the 16F877 micro controller.

The line interface was built as simple as possible. The purpose of this interface is to permanently monitor the Phone Line for incoming DTMF signals, output confirmation Beep’s to the line and keep the phone loop closed while the DTMF Remote is in use.

The phone line is connected at the JP1 jumper. R3, C1, line trafo and D2 are protecting the rest of the DTMF detector from the ringing signal and other power spikes coming from the phone line side. C1 should be a good quality capacitor designed for 250VAC at least. D2 should be a 1W – 5.1V zener diode in order to absorb all the power spikes.

The ground of the DTMF Remote must be floating in order to work as expected and cannot be connected to earth ground.

An external comparator is used in order to detect the passes through zero of the audio input. The square signal obtained from the comparator is applied to the PORTC0 Trigger Schmidt input of the PIC micro controller.

The audio out pin is PORTC1. This pin stays in high impedance mode (input) when no sound is transmitted. When a beep sound is transmitted the pin is programmed like output. A Piezo Buzzer is connected to the Audio Out pin to generate a local Beep sound.

The Hook On pin PORTC3 drives a Reed Relay. The contact of these Relay keep the Phone Loop closed while the DTMF Remote is active. The relay is optional, if the Answering Machine used with the DTMF Remote does not disconnect the phone line in a short time the relay and the resistor are not necessary.

The relay driver consists in 4 transistors and four relays. The relays are connected to 4 electrical plugs.

The power supply is a 12V wall wart adaptor that powers directly the relays and a 7805 linear regulator in order to obtain 5v for the PIC micro controller.

The schematic diagrams for the PIC micro controller and the relay drivers are attached at the end of this document.


The software can be divided in more parts – The DTMF Decoder, the Logic necessary to decode/execute Commands and the Beep generator/Line interface.

The software DTMF Decoder is based on a modified Goertzel algorithm. A good source of explanation for the this algorithm and how to implement it using a DSP can be found in "Modified Goertzel Algorithm in DTMF Detection Using the TMS320C80" – Application Report from Texas Instruments.

In order to implement this algorithm on a such small processor like a 16 series PIC it was necessary to switch to integers, an finally to work with bits. A good source of inspiration was DTMF - Decoding with a 1-bit A/D converter by Scott Datallo -

I will not go into theoretical details in here. I will just present the final formula used by the program. If Fsample is the sampling frequency, Fd is the frequency to be detected and In(t) is the input signal the program should compute:

If the computed Detect sum is higher than 254/4 than the input signal matches the Fd frequency.

The DTMF signals are composed of a pair of two frequencies:


























So if a positive match is found for 1209Hz and 697Hz we can decide that digit 1 was transmitted.

The implementation of this algorithm uses two tables of 255 values each for Sin and Cos values. The bits corresponding to sin and cos for 697,770,852 and 941Hz are stored in the LOWBAND table and the bits for 1209,1336,1477 and 1633Hz are stored in the HIGHBAND table. The Tables were computed in Excel, please see attached DTMF Detect255_10K.xls for the values and a sample.

A 20Mhz crystal is used for the PIC16F877 clock.

Timer2 is used to generate interrupts at 9765.625 Hz. For each interrupt PORTC1 Value is used to get the next sample of the input signal and compute the sums for each frequency in the table. Once the program got 255 samples the final sums are computed and a decision is taken. If a digit is detected at least twice in a row then the digit is converted to ASCII character, placed in the RESULT1 location and the Done Flag is set.

The entire DTMF detector is contained in the ISR routine and is started by the START_DTMF routine and stop by itself when a valid digit is detected. The DONE bit is the control flag for the ISR Routine.

The Logic necessary to decode/execute Commands and the Beep generator/Line interface

The main loop is waiting for valid digits in order to execute commands. The first digit of any command is #, once a # is received the HOOK ON pin is set to on in order to keep the Phone Loop open – this was necessary because usually Answering Machines are trying to decode DTMF by themselves for remote access and is a wrong remote code is received the line is disconnected.

A timeout timer of about 7 seconds is started at each digit received. If another digit is not received in that time interval an error sound is transmitted and the line is disconnected (HOOK ON goes to zero)

The timeout timer uses TIME1 and TIME2 variables to create a 16bit counter decremented at each interrupt and set the TIMEOUT flag if the counter reaches zero.

Each time a Beep needs to be transmitted on the phone line the BEEPOK or BEEPERR routines are called.

These routines are setting the timeout value/ TIMEOUT flag and the Beep pitch and BEEP flag. Also PORTC0 is set up as an Output. Once the BEEP flag is set the ISR part of the Beep routine start to toggle the PORTC0 exit according to pitch.

The Main program starts with an INIT part that sets the Ram variables to the default values. Next step is to read the Outputs status from EEPROM and output these values to PORTB0-3 pins. Because the output status is kept in EEPROM a power failure will not alter the status of the exits.

The main loop is waiting for digits and executes the necessary commands.

If a set output command is received then the corresponding Output is set as requested and the new value is stored in EEPROM.

If a change password command is received the new password must be introduced twice in order to avoid any mistakes. Then the new password is store din EEPROM.

For more details please see the comments in the attached listing and the Flowcharts.


Construction and Debug

The construction of the prototype was made o a piece of perfboard. There is nothing special about that, just a bunch of wires under the board.

The used parts are quite common, any RadioShack or Junk Box will provide the necessary parts for a prototype.

Next I plan to downsize to a 16F629-20 that will integrate the comparator to.

The 16F877 used to develop the project has the ICD interface that was a real help during debugging.

The DTMF Remote is using a LCD connected to port D of the PIC for debugging purposes only. On that display the received digits could be watched in real time. Also at one moment during the development cycle the display was very useful in order to debug the DTMF detect algorithm.

It was a real challenge to try to understand what is happening in the small Pic from outside in real time. The solution was to display the partial sums from the Goertzel Algorithm on the display. Like signal generator I have used Spectra Lab from Sound Technology in order to output different frequencies/combinations and watch the result on the LCD. For those who are interested I will attach a file called dtmf_255_10k_diag.asm.

This file will display on the LCD the partial sums as shown:

697cos 770cos 852cos 941cos

1209cos 1336cos 1447cos 1633cos

The purpose of this file is for debug only and could be modified to display the sin sums or other useful thing

DTMF Serial Gateway - updated project