|The DTMF page
To make a long story short: It it *not* possible, to tone dial with the Palm so far, at least not without major hardware modifications. I did spend quite some time on it, so if you're interested WHY it is not possible (the true reasons), please read on. I'm basically through with DTMF on a Palm, I left that page on the web just because it was done :).
UPDATE: The TRGPro has a much better sound interface. TRG not only gave their unit a real audio amplifier with a nice volume control, but also a true little speaker. With the TRGPro, dialing is no problem - but not with my DTMF app!!! See next note, the TRGPro is running on an EZ CPU.
PLEASE NOTE: The new EZ CPU - used in the Palm IIIx and the Palm V - has a completely changed PWM module (sound module). The apps DTMF and TALK are NOT working on these models and they are crashing! If I find the time, I'll adapt both to the new CPU, but that has a quite low priority on myToDo list ...
|Nonsense and fairy tales
First of all, I want to contradict all the nonsense I read about, why it should not be possible to generate dual tones with the Palm, and I waited long for that chance :).
|How it basically works
I'm sorry, but I can't explain the whole theory of digital audio here, but I'll do my best :). For the first step, let's forget about DTMF and multifrequencies, let's just look at a single sine wave (excuse the handmade graphic, but I'm an engineer not an artist <g>)
|Above, you see a single sine wave of any period (the frequency doesn't
matter for the moment). To digitize that sine wave, we divide it into 10
equal time frames. That's far too less for a good qualiy, but enough to
show the principal. Now, every of that 10 moments we 'look' at the wave,
we get a value we could store. These values are not absolute, they are
just a scale from 0 to 1 (or 0% to 100%). For better undertanding of the
PWM later, I shifted the sine already to that scale (mathematically the
sine swings from -1 to +1, but just add +1 and divide it by 2). Now, that's
how you would digitize that sine wave. But for a sine wave we don't have
to do that, since it's quite easy to calculate these values and start immediately
with the reverse process, making it an analog signal again. When you look
at the line labeled PWM, you see the representation of each of our values
in the duty cycle of the PWM signal. In other words: In each period, the
ON-time of the PWM signal is as long as our value (always keep in mind,
the values are fractions of one or part of the total period). If you imagine,
you charge a capacitor with the pulses of the PWM output, it's quite clear,
that the longer the output is high, the more we get the capacitor charged.
If the output is low, the capacitor is discharged. So, the capacitor is
integrating our digital signal (or easier: building an average from it)
and voila ... we have our sine wave again. BTW, that is the capacitor that's
missing at the Palm sound interface. Now this capacitor has another important
duty: It must filter the PWM period frequency. Let's talk about more specific
numbers in the next paragraph.
|How to do it in reality
Next I want to explain, how the PWM modul in the DragonBall works and what makes that port bit so special among all the normal general port bits. To vary the duty cycle of the signal, you would have to keep track of the time, the bit is on or off, and you had to generate the repeating periods. From the above explanation, you can easily see, that it's necessary to have a much higher frequency for the PWM period, than the frequency we want to reproduce. Within that period again, you want to vary the duty cycle as fine as possible (this resolution is basically the bit count of our digital-to-analog converter). For DTMF, I used for example 50kHz or in other words, a 20uSec period. Lets assume, you only want to change the duty cycle in 64 steps (6-bit resolution), you have to be able to control the signal as fast as 20uSec / 64 ~ 0.3uSec. That's impossible for a processor running at 16MHz. But fortunately we don't have to deal with that. The PWM module has a period register and a width register, that works pretty automatically. You just load the period (which you do only once, since the period is constant) and you load the width register. When you start the PWM module, the period counter starts counting up with a frequency of 4Mhz and when it reaches the value in the period register, the period is automatically started over again. When the period starts, the output of the PWM module goes high and remains high until the value of the period counter reaches the value of the width register. Then the bit goes low and remains low until the period counter has reached zero and the whole process is started over again. Whenever a period is completed, a status bit is set, and the processor can load the next width value. So the processor has only to be fast enough to service each period.
An example: Let's assume we want a period of 20uSec (frequency 50kHz), we need to load the period register with a value of 80. Why? When that counter is incremented with 4MHz (0.25uSec), it reaches the 80 in the period register after 20uSec. If we want a duty cycle of 50%, we load the width register with 40. Now we can also see our resolution: it's 80 steps or something between 6 and 7 bits (please no exact logarithmic calculation now :) ). Of course it makes no sense (or harm), when the value of the width register is higher than the one of the period register. The output would remain high, since the period counter would never match the value in the width register.
Going as high as 50kHz has another advantage: On the output, you don't get only your sine wave, but unfortunately also the PWM period frequency. The higher this frequency is, compared to the frequency you originally want to produce, the easier it is to filter it. Regarding the DTMF tones for example, we don't have to worry about the 50kHz, since even if it's not filtered properly, no part of a telephone system has a bandwidth of 50kHz, such it's lost there. If the Palm would use a proper speaker, the speaker alone would probably already attenuate it enough. But Piezos are damn fast parts, so you can hear at least the harmonics of the 50kHz (and there are plenty since it's a rectangle signal) as a 'buzz' within the real signal.
|How to produce DTMF tones
Well, we basically saw how you can reproduce a sine wave. There is no reason, not to reproduce _any_ wave, including real audio or two merged sine waves, what DTMF tones are. The good thing about a single sine wave is, that it's a repetition of the same set of values over and over again. So you have to store only one period (in fact only a quarter of a period, but that's another story <g>). The mixture of two sines are repetive only, when their frequencies are dividable. Example: 1000 Hz and 250Hz mixed together need 4 repetitions of the 1000Hz sine, then the 250Hz sine is also at zero again. Below you see a table of the DTMF tones (don't ask me about that A to D, it's in the definition):
When you look at the frequencies (each key produces it's two according row and column frequencies), you can guess, that they don't repeat early. But I found a trick: Since our bit resolution is restricted anyway (remember we have only 80 different values for the width register), we don't have to worry whether the wave form reached 0 or 0.001. In other words: If you consider the limited sampling resolution, you can find repetitions after 500 - 1000 sample values (I wrote a program on my desktop to find that 'unaccurate correlation'). Now everything is easy: Store the values on your Palm (it takes about 9k for that data) and read them out to the width register. Well, there is one more problem to overcome. Since the processor has to reload the width register every 20uSec, the reaction time on that 'period-done-bit' is crucial for the quality of the signal. If a new period is more or less delayed, you'll get a jitter in your output signal, that distorts it. Since the Palm is an event driven machine, it is better to switch off all interrupts during that short sound output. But some machines, configurations, hacks, whatever don't like that obviously. So you'll find two different versions of the app in the archiv. DTMF_INT leaves the interrupts on and has a slightly worse sound quality (if to speak of sound quality anyway <g>). The file DTMF_!!! is the 'dangerous' one that disables the interrupt. Try it, if your Palm crashes, a simple soft reset should cure it :)
DTMF is a simple push-button solution in the moment. If there would be a possibility to overcome the hardware weaknesses, it would be possible of course, to code it for example as a hack, that allows direct dialing from an address book entry. The keys A to D are producing _not_ the usual dual tones, but pure sine waves for test purposes (if you happen to have a spectrum analyser like me, you will love it <g>). A to D sines are 700, 1000, 1300 and 1600 Hz. Also, the tone duration is quite long, but that's also better if you want to meassure something. Remember, it's a pure test app. I wouldn't have posted it, if I hadn't got so many mails about it :)
Since I stated, that with the PWM module _any_ waveform can be reproduced, I hacked together a little testapp, called TALK. Talk plays a 2 second voice sample. You better hold the back of your Palm close to your ear (best is, if you hear the constant hiss of the piezo already). Then tap the button (you'll find it blind, that's why it is so big <g>). You should hear: 'Hello everyone, I'm a talking Pilot' (Sorry 3Com, I don't code 'Palm' now instead of 'Pilot' into that old app <g>). As I said, due to the various lacks of the hardware, the quality is lousy, but I think it's understandable and the basics are proved. If you still have good ears, you can clearly hear the 16kHz sample frequency that's coming through unfiltered (used 16 kPeriods/sec for that one, otherwise it had taken too much memory). It's a fun app, but hey, you can say: My Palm talks! :)
|Why is it not possible to dial with your DTMF app?
Well, to say it clearly, because 3Com/USR saved $0.20 on the audio output! If you tried DTMF, you have noticed that the output sounds A) very low volume and B) you still can hear the harmonics of the 50kHz, that are distorting the true DTMF tones. If you do want to do an experiment (and you know where the hot end of a soldering iron is), replace the piezo with a little speaker (these 2 inch transitor radio things). I was able to dial right away with that combination. The much bigger speaker filters the 50kHz pretty good (you could also solder a 100nF capacitor in parallel to the speaker), and it produces a higher sound volume. I have found a speaker that is exactly the size of the piezo (Siemens makes it for their handies), but that again produces not enough sound pressure with the existing output driver.
ATTENTION: The sound output is _not_ DC free, that means when you replace the high impedance piezo with a low impedance speaker, you have a constant current flow of about 5mA. If you leave it long enough, it'll drain your batteries.
I personally, will design me a tiny, but true audio amplifier. There are phantastic 8-pin SMD amps on the market that should work. Basic specs to adapt it to the existing design are: High impedance input, low impedance output, operation voltage down to 3V. If I have schematics, I'll post them here.
Last updated: March 24th, 2000
Copyright © 1997-2000 by Peter Strobel, all rights reserved.