Telephone Call Progress tone generator

Hi Everyone,

I'm working on (another) project: I need to hack an old rotary phone and when the proper number is dialed, a dry contact is activated. The phone IS NOT connected to any phone line.

when people are picking up the phone, I want to generate/simulate the "Call Progress" tone, to make the illusion even better.

has anyone ever done this with an Arduino ? Is it possible ?

the "Call Progress" tone seemed to be made of 350HZ and 440 HZ, but I couldn't figure out the duration of each frequencies and the pattern.....

I found a chip made by Clare, M-991, that is supposed to do that, but it is fairly expensive and rare ....

any suggestions ?

Do you need a dial tone when the handset is picked up?
Do you need to actually be able to talk and listen?
Is there another phone to talk to?
Or is this just some kind of limited simulation?

There are many circuits you can find with Google image search for telephone line simulator or similar terms.
It would seem easy enough to simply connect the phone to a digital input pulled up to VCC.
Then the phone will pull the pin low when you pick up the handset.
And the pin will go high as a series of pulses as each number is dialed.

You can write a sketch that will sense off-hook, and then dialed numbers.

You could create the two-frequency tone with a dual 555 timer chip (or similar) and some rather simple R/C filter/mixing circuit. And it would be easy enough to use a digital output from your Arduino to turn the tone(s) on or off.

The phone is not going to be used on a phone line or connected to another phone to talk to.

It's going to be a props for an escape game: player pick up the phone, hear the tone then dial a specific number. If the number is right, a relay will activate.

I have already hacked the phone. Since it's a rotary phone, I can simply count the pulse. Off-hook is also easy.

The call-progress is made of 2 frequencies that seems to be blended together. Would I be able to take 2 outputs and connect them to the same speaker ?

I was planning on using the tone() instruction. It is my understanding that tone() will generate square wave. Is there a way to distort/modify so it look a bit more like a sine ?

A low-pass filter will round off the corners of the square wave. That's what you are doing when you wire a speaker to a tone() pin. The speaker can't transmit the high frequencies into the air so you hear a sort-of pure tone.

2 outputs should not be connected together. And the tone library can only play one at a time.

I would brute-force it. I would get an MP3 shield and play a recording of the correct sound.

If you aren’t too concerned about the audio quality, you can generate the dial tone using a single digital output by, in effect, simulating a 1-bit waveform. To do this only requires figuring out the times between zero-crossings of a real dial-tone signal and then using those to toggle the digital output. The resulting sound is very noisy, as must be expected with such a low quality signal, but it might be enough for what you want to do.
I had already written a PC program to generate WAV files with multiple tones so it was easy to generate a file with the 350+440Hz of a dialtone. I modified the code to print out where the zero crossings occur and some of that output was then pasted into the tone_zeroes array.
This code was tested on a Teensy 3.2 but should run unmodified on a Nano or Uno.

/*
  Generate a low-quality dial tone on a digital pin.
  Copyright 2016 Pete El_Supremo
*/

// Piezo buzzer pin, but an 8-ohm speaker will give somewhat
// better quality sound.
// Use a 22ohm resistor from this pin to the piezo/speaker
int piezoPin = 15;

// The tone will stop playing while this pin is grounded.
// Or the code can be modified to terminate the tone when
// the pin is grounded.
int stopPin = 4;


// Times of zero crossing when sampled at 8000Hz
// therefore multiply each one by 125 microseconds
// to get its cumulative elapsed time.

uint16_t tone_zeroes[] = {
//#define TONES_1
#ifdef TONES_1
      10,
      20,
      30,
      40,
      44,
      50,
      60,
      70,
      81,
      91,
     101,
     111,
     121,
     131,
     133,
     141,
     151,
     162,
     172,
     182,
     192,
     202,
     212,
     232,
     243,
     253,
     263,
     273,
     283,
     293,
     303,
     311,
     313,
     324,
     334,
     344,
     354,
     364,
     374,
     384,
     394,
     399,
     400,
     405,
     415,
     425,
     435,
     445,
     455,
     465,
     475,
     486,
     488,
     496,
     506,
     516,
     526,
     536,
     546,
     556,
     567,
     587,
     597,
     607,
     617,
     627,
     637,
     648,
     658,
     666,
     668,
     678,
     688,
     698,
     708,
     718,
     729,
     739,
     749,
     755,
     759,
     769,
     779,
     789,
     799,
     800,
     810,
     820,
     830,
     840,
     844,
     850,
     860,
     870,
     881,
     891,
     901,
     911,
     921,
     931,
     933,
     941,
     951,
     962,
     972,
     982,
     992,
#else
      10,
      20,
      30,
      40,
      44,
      50,
      60,
      70,
      81,
      91,
     101,
     111,
     121,
     131,
     133,
     141,
     151,
     162,
     172,
     182,
     192,
     202,
     212,
     232,
     243,
     253,
     263,
     273,
     283,
     293,
     303,
     311,
     313,
     324,
     334,
     344,
     354,
     364,
     374,
     384,
     394,
     399,
     405,
     415,
     425,
     435,
     445,
     455,
     465,
     475,
     486,
     488,
     496,
     506,
     516,
     526,
     536,
     546,
     556,
     567,
     587,
     597,
     607,
     617,
     627,
     637,
     648,
     658,
     666,
     668,
     678,
     688,
     698,
     708,
     718,
     729,
     739,
     749,
     755,
     759,
     769,
     779,
     789,
     799,
     810,
     820,
     830,
     840,
     844,
     850,
     860,
     870,
     881,
     891,
     901,
     911,
     921,
     931,
     933,
     941,
     951,
     962,
     972,
     982,
     992,
    1002,
    1012,
    1032,
    1043,
    1053,
    1063,
    1073,
    1083,
    1093,
    1103,
    1111,
    1113,
    1124,
    1134,
    1144,
    1154,
    1164,
    1174,
    1184,
    1194,
    1199,
    1205,
    1215,
    1225,
    1235,
    1245,
    1255,
    1265,
    1275,
    1286,
    1288,
    1296,
    1306,
    1316,
    1326,
    1336,
    1346,
    1356,
    1367,
    1387,
    1397,
    1407,
    1417,
    1427,
    1437,
    1448,
    1458,
    1466,
    1468,
    1478,
    1488,
    1498,
    1508,
    1518,
    1529,
    1539,
    1549,
    1555,
    1559,
    1569,
    1579,
    1589,
    1599,
    1610,
    1620,
    1630,
    1640,
    1644,
    1650,
    1660,
    1670,
    1681,
    1691,
    1701,
    1711,
    1721,
    1731,
    1733,
    1741,
    1751,
    1762,
    1772,
    1782,
    1792,
    1802,
    1812,
    1832,
    1843,
    1853,
    1863,
    1873,
    1883,
    1893,
    1903,
    1911,
    1913,
    1924,
    1934,
    1944,
    1954,
    1964,
    1974,
    1984,
    1994,
    1999,
    2005,
    2015,
    2025,
    2035,
    2045,
    2055,
    2065,
    2075,
    2086,
    2088,
    2096,
    2106,
    2116,
    2126,
    2136,
    2146,
    2156,
    2167,
    2187,
    2197,
    2207,
    2217,
    2227,
    2237,
    2248,
    2258,
    2266,
    2268,
    2278,
    2288,
    2298,
    2308,
    2318,
    2329,
    2339,
    2349,
    2355,
    2359,
    2369,
    2379,
    2389,
    2399,
    2410,
    2420,
    2430,
    2440,
    2444,
    2450,
    2460,
    2470,
    2481,
    2491,
    2501,
    2511,
    2521,
    2531,
    2533,
    2541,
    2551,
    2562,
    2572,
    2582,
    2592,
    2602,
    2612,
    2632,
    2643,
    2653,
    2663,
    2673,
    2683,
    2693,
    2703,
    2711,
    2713,
    2724,
    2734,
    2744,
    2754,
    2764,
    2774,
    2784,
    2794,
    2799,
    2805,
    2815,
    2825,
    2835,
    2845,
    2855,
    2865,
    2875,
    2886,
    2888,
    2896,
    2906,
    2916,
    2926,
    2936,
    2946,
    2956,
    2967,
    2987,
    2997,
    3007,
    3017,
    3027,
    3037,
    3048,
    3058,
    3066,
    3068,
    3078,
    3088,
    3098,
    3108,
    3118,
    3129,
    3139,
    3149,
    3155,
    3159,
    3169,
    3179,
    3189,
    3199,
    3210,
    3220,
    3230,
    3240,
    3244,
    3250,
    3260,
    3270,
    3281,
    3291,
    3301,
    3311,
    3321,
    3331,
    3333,
    3341,
    3351,
    3362,
    3372,
    3382,
    3392,
    3402,
    3412,
    3432,
    3443,
    3453,
    3463,
    3473,
    3483,
    3493,
    3503,
    3511,
    3513,
    3524,
    3534,
    3544,
    3554,
    3564,
    3574,
    3584,
    3594,
    3599,
    3605,
    3615,
    3625,
    3635,
    3645,
    3655,
    3665,
    3675,
    3686,
    3688,
    3696,
    3706,
    3716,
    3726,
    3736,
    3746,
    3756,
    3767,
    3787,
    3797,
    3807,
    3817,
    3827,
    3837,
    3848,
    3858,
    3866,
    3868,
    3878,
    3888,
    3898,
    3908,
    3918,
    3929,
    3939,
    3949,
    3955,
    3959,
    3969,
    3979,
    3989,
    3999,
#endif
};

void setup()   
{
//  Serial.begin(9600);
//  while(!Serial);
//  delay(2000);
  
  pinMode(piezoPin, OUTPUT);
  pinMode(stopPin, INPUT_PULLUP);
  // Initialize the tone_zeroes array
  for(int i = sizeof(tone_zeroes)/sizeof(tone_zeroes[0])-1;i > 0 ;i--) {
    tone_zeroes[i] = tone_zeroes[i] - tone_zeroes[i-1];
//Serial.println(tone_zeroes[i]);
  }
  play_dial();
}       

void loop()
{

}       

// Play the dial tone
void play_dial (void)
{

  int idx = 0;
  int output = 0;
  unsigned long delayCount;    
  while(1) {
    output ^= 1;
    delayCount = tone_zeroes[idx++];
    digitalWrite(piezoPin,output);
    delayMicroseconds(delayCount*125L);
    if (idx >= sizeof(tone_zeroes)/sizeof(tone_zeroes[0]))idx = 0;
    // This hangs the code if stopPin is grounded.
    // Or it can be used to terminate the tone and return from the
    // function by adding "break" to the while loop.
    while(digitalRead(stopPin) == 0);
  }   
  digitalWrite(piezoPin, LOW);
}

Pete

It has been a long time since I've worked with phones, but you may also need battery to get the receiver work. Can you take a line level signal, drive it into the phone, and hear it in the receiver? If not, you may need an amp or -48v (that is what the phone system uses) in order to hear the tone.

follow-up:

got it to work, and it's pretty close to the real thing !

I have my main Arduino, that has a pin that generate a tone of 350 HZ

I have a second one, (a Pro Mini...3$ on Ebay) that only does one thing : tone at 440 HZ.

both are connected to the same speaker....I don't think I can get any better that that !

Thanks MorganS for pointing out that only one tone can be played at a time.

Only one? Nonsense. Here's 8, with code that supports 13.

You may program many, but only one is "working" at a time.

here's an extract from the Arduino's web site, when looking at the "Tone()" instruction.

"Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency."

That may be true for that library, but there are ways to generate multiple simultaneous frequencies (not very high frequency, but in the low end of the audio range, it can be done). Look into using counters or interrupts as possible ways to do multiple things at the same time.