[comp.sys.handhelds] Phone tones

bgribble@jarthur.Claremont.EDU (Bill Gribble) (02/20/90)

Question:
(and I hope the answer is yes, 'cause I don't want to do it myself)

Did anyone ever come up with a way to generate multiple tones from
the hp's speaker?  (i.e. phone tones) 

The more I think about it, the more reasonable it sounds.  If the tone 
BEEP generates is a sine wave, there must be a lookup or some call
to generate the waves.  If this could be diverted to another table/function,
multiple tones could be generated by simple addition of two sine waves.

                                              Thanks.
                                              Bill Gribble
                                              bgribble@jarthur.claremont.edu

alonzo@microsoft.UUCP (Alonzo GARIEPY) (03/01/90)

In article <4501@jarthur.Claremont.EDU> bgribble@jarthur.Claremont.EDU (Bill Gribble) writes:
> Question:
> (and I hope the answer is yes, 'cause I don't want to do it myself)
> Did anyone ever come up with a way to generate multiple tones from
> the hp's speaker?  (i.e. phone tones) 
> The more I think about it, the more reasonable it sounds.  If the tone 
> BEEP generates is a sine wave, there must be a lookup or some call
> to generate the waves.  If this could be diverted to another table/function,
> multiple tones could be generated by simple addition of two sine waves.

I don't know if you saw my posting on this; I will send it under separate
cover.

The tone is a combination of two sine waves.  This makes it somewhat 
more difficult to synthesize with the beeper.  Since the beeper has 
only two levels 1 and -1 (and maybe 0) you have to do something like 
Pulse Duration Modulation to get a complex signal.  If there is a 0 
then a simple combination of two sinusoids may be possible without PDM.

In any case, the amount of distortion is horrendous.  It will take 
someone with more time than I have to experiment with this.  My posting 
contained all the information you need to try this once you have some
familiarity with hp28 machine code.  It includes sample machine code to 
drive the beeper, the frequencies for touch tone dialing, and some 
reasonable approximations to these frequencies.  I am told that this was 
tried once at HP and given up as not worth too much effort.

alonzo

bhil@ohs.UUCP (Brian T. Hill) (03/04/90)

From article <51114@microsoft.UUCP>, by alonzo@microsoft.UUCP (Alonzo GARIEPY):
>
> I don't know if you saw my posting on this; I will send it under separate
> cover.

[ stuff deleted ]

> someone with more time than I have to experiment with this.  My posting 
> contained all the information you need to try this once you have some
> familiarity with hp28 machine code.  It includes sample machine code to 
> drive the beeper, the frequencies for touch tone dialing, and some 
> reasonable approximations to these frequencies.  I am told that this was 
> tried once at HP and given up as not worth too much effort.
> 
> alonzo

I'd like to see the original posting.  I must have missed it.  Please
e-mail to me the information.  I'm particularly interested in the machine
code driver for the speaker.

Thanks,

Brian T. Hill,   bhil@ohs.UUCP,   bhil!ohs@uunet.UU.NET

robert@longs.LANCE.ColoState.Edu (Robert Thompson) (03/07/90)

In article <511@ohs.UUCP>, bhil@ohs.UUCP (Brian T. Hill) writes:
> From article <51114@microsoft.UUCP>, by alonzo@microsoft.UUCP (Alonzo
GARIEPY):
> >
> > I don't know if you saw my posting on this; I will send it under separate
> > cover.
> 
> [ stuff deleted ]
> 
 
 [More stuff deleted]

> I'd like to see the original posting.  I must have missed it.  Please
> e-mail to me the information.  I'm particularly interested in the machine
> code driver for the speaker.

Likewise, or have you put this in the archives at gmuvax2 ?  

Thank you

Robert Thompson
Center for Computer Assisted Engineering
Colorado State University

alonzo@microsoft.UUCP (Alonzo GARIEPY) (03/14/90)

Back by popular demand...

Newsgroups: comp.sys.handhelds
Subject: Beeeeeeeeeeeeeeeeeeep!

Here is a code fragment for controlling the beeper.  Before the code is 
executed, register B must contain a time constant that determines the 
frequency, and register D the number of half cycles in the duration.

	intoff
	move.5	#c0000,d1	; address of keymask
	move.x	@d1,c		; c = #0xx   (keymask is #0fe on hp48)
	out.x	c		; turn beeper off
	move.1	#2,p
	move.p1	#8,c		; c = #8xx
	move.1	#4,p
	move.5	#c00e6,d0	; address of abort flag
loop:	
	swap.1	p,c,#2		;\
	out.x	c		;-alternately output #4xx and #8xx

	move.x	b,a		;\ 
pulse:	dec.x	a		; time half wavelength (b is timing constant)
	brcc	pulse		;/

	dec.w	d		; decrement and test duration
	brcs	done		; d is # of half wavelengths in duration

	move.a	@d0,a		; check abort flag
	brz.a	a,loop		; abort if flag set (user interrupt?)


done:	move.x	@d1,c		;\
	out.x	c		;-turn beeper off
	inton

=================================================================
|
|   HP28 ROM	#22ad23 - #22bde			BEEPER
|   
|   You can find the HP code that does this by disassembling
|   the ROM between #22ad3 and #22bde.  It does more than my
|   simple example above.  It expects the duration in 1000ths
|   of a second to be in register C, and frequency in cycles-
|   per-second to be in register D.  The calibration factor
|   at location #c000f is then used to work out a pulse time
|   constant, which goes into register B.  Next, the duration
|   is converted to a pulse count with the equation, C * D *.002
|   (pulses = C seconds/1000 * D cycles/second * 2 pulses/cycle)
|   which then goes into register D.  The rest is similar to
|   my example, except that it decrements the duration count
|   in two steps (I don't know whether this was done for speed,
|   consistency, or as a bug fix.) 
|
|   The calculation of the time constant is still murky to me.
|   
=================================================================

I would not be surprised to find that the decrement instruction 
terminates early when there is no borrow from the next nibble.  
This optimization could cause some timing inconsistencies.

The above code should also shed some light on the use of 
C00E6 (marked ??? in Dave Kaffine's indispensable RAM map).
I assume that pressing the ON key puts something in this 
address.  I don't know what interrupts are disabled by the 
intoff instruction, but I'll guess it isn't the ones caused 
by the ON key or the timer.

Most interesting to me are the use of #4FE, #8FE, and #0FE
to control the beeper.  I presume that their respective
functions are positive pulse, negative pulse, and beeper
off.

Let's look at how you might combine two frequencies to
generate dialing tones.


  ________        ________        ________        ____        
__        ________        ________        ________        3000 Hz

     			+				    +          
  ______      ______      ______      ______      ____
__      ______      ______      ______      ______        4000 Hz    
								              
			=				    =
  ______          __                  ____        ____
        __    ____  ____________  ____    __              3000 Hz + 4000 Hz
__        ____                  __          ______            
								              
				       
    If you can't imagine the vertical lines, here 
    is a slightly more intuitive representation:


   ______          ______          ______         
  /      \        /      \        /      \        	  3000 Hz
          \______/        \______/        \______/
		       +				    +
   ____        ____        ____        ____       
  /    \      /    \      /    \      /    \      	  4000 Hz    
        \____/      \____/      \____/      \____/

                       
    __                 =                           	    =
   /  \                                /\         
  /    \__    ____/\____________  ____/  \__      	  3000 Hz + 4000 Hz
          \  /                  \/          \    /
           \/                                \__/


The above has an uncanny resemblance to the plot you get with:

	RAD 'SIN(3*X)+SIN(4*X)' STEQ 1.8 *H DRAW

The first representation of the wave is bipolar pulse width
modulated--the distortion is horrendous.  And how do you get 
the zero intermediate values between pulses?  Perhaps #0FE.  
If not, an intermediate value can be achieved by pulsing back 
and forth at some ridiculously high frequency (e.g., 20kHz).

If you add more than two frequencies, you need more different
intermediate values.  About the only way I can see to do that
is to modulate the signal on a carrier (i.e., 20kHz) and then
represent the carrier using bipolar pulse width modulation.

Standard pulse width modulation, known as PDM (pulse duration
modulation), may also serve here, but I'm not sure yet.

Below, I summarize the touch-tone dialing combinations.

697	 1	 2	 3	 -

770	 4	 5	 6	 - 

852	 7	 8	 9	 -

941	 *	 0	 #	 -

Hz	1209	1336	1477	1633

These frequency combinations were originally chosen to avoid 
harmonic relationships that are open to signal interference.  
This has an unfortunate side-effect of making them harder to 
synthesize.  

Below is a list of modified frequency combinations that can
be synthesized with minimal data (because they repeat at
least every 17 cycles) yet remain within 1% of the nominal
frequency.  The standard allows for a 2% drift in frequency, 
leaving us less than 1% error for synthesis.  The synthesis 
may also suggest better, fractional frequencies.

1	696:1218	4:7
2	702:1326	9:17
3	696:1479	8:17
4	770:1210	7:11
5	764:1337	4:7
6	783:1479	9:17
7	847:1210	7:10
8	847:1331	7:11
9	848:1484	4:7
*	945:1215	7:9
0	938:1340	7:10
#	938:1474	7:11

Since I don't have an oscilloscope, I encourage others to
analyse the accuracy of the current tone generation and
to develop programs for generating sound from a waveform.
I won't be able to pursue this further for some time.

Alonzo Gariepy
alonzo@microsoft