Notes on how tt works. Gary Bishop , 19 July 1994 Touch-Tone dialing requires the simultaneous generation of two frequencies. There are at least two approaches to doing this on the HP100 with only a PC (two-state) speaker. One is the approach taken by ATDT which is to attempt to reproduce the envelope of the sum of the two sines by PCM. A second approach is demonstrated by TT. Start with the desired signal "Sin[2 Pi f1 t] + Sin[2 Pi f2 t]", and square it up. When the desired signal is > 0, put the speaker in one state, when the desired signal is < 0, put it in the other. Now if you think this add tons of distortion, you're right. *BUT*, there is still plenty of energy at the key frequencies f1, and f2. If you look at the fourier power spectrum, you'll see that the distortion products are all better than 20dB (a factor of 100) down from the energy at f1 and f2. The DTMF tones were carefully chosen to prevent harmonics and intermodulation products from interfering with the decoding process. So, if we can get enough energy at the correct frequencies, we should be able to key the decoder. The function two_tone in the source file "tt.c", does the tone generation. It uses another trick to avoid generating the two-sines, adding them, then testing the arithmetic sign. The trick uses the trigonometric identity Sin[a] + Sin[b] = 2 Sin[(a + b) / 2] Cos[(a - b)/2] This identity changes the sum of two sines, into the product of a sine and a cosine. Now since we are only interested in zero crossings of this function, we will assume that the product crosses zero when ever either the sine or the cosine crosses zero (of course, they could both change signs simultaneously but with relatively prime frequencies this doesn't happen often). So, we need only determine the time for a half cycle of (f1+f2)/2 and a half cycle of (f1 - f2)/2. At each step, in the function two-tone, the speaker state is changed, then we delay until the next zero crossing. We keep track of the zero crossings by keeping two counters, one for (f1 + f2)/2 and one for (f1 - f2)/2. Which ever is less is used next. After a zero crossing, that timer is reset to the half period for its frequency. The other timer is decremented by the delay used up, and the process repeats. This gets us a squared-up version of the sum of two sines with no trig functions at all. The rest of the code is just window dressing to demonstrate the concept. Someone with more energy, and more knowledge of the PC internals should take it and make a real dialer out of it. The calibration constants K1 and K2 were determined using stop watch timings and linear regression. They will probably have to be tuned for another C compiler (I'm using an ancient version of Borland Turbo C). So, how well does it work? Not as well as I would like. My theory is that the HP100 just isn't sufficiently loud to do the job. If you listen to the tones generated by your keypad in another reciever, they are *REALLY* LOUD. The hp100 doesn't even come close to the volume. So the signals are marginal at best. If you phone handset does a good job of coupling the tones out of the hp100 and into the line, and your phone company switch is sensitive, you'll get good dialing. This code is freely distributed and you can do with it what you like. If you make a neat dialer for the hp100lx, I think you owe it to me to give me a copy for my use. gb